spongy/spongy.cgi/network.go

177 lines
3.1 KiB
Go
Raw Normal View History

2015-02-11 20:19:46 -07:00
package main
import (
"bufio"
"fmt"
2015-02-18 20:33:17 -07:00
"github.com/go-fsnotify/fsnotify"
"io/ioutil"
2015-02-11 20:19:46 -07:00
"os"
2015-02-18 20:33:17 -07:00
"path"
2015-02-22 16:06:22 -07:00
"strconv"
2015-02-18 20:33:17 -07:00
"strings"
"time"
2015-02-11 20:19:46 -07:00
)
2015-02-22 16:06:22 -07:00
const eventIdSep = "/"
2015-02-11 20:19:46 -07:00
type Network struct {
2015-02-21 21:45:56 -07:00
running bool
2015-02-22 16:06:22 -07:00
Name string
2015-02-11 20:19:46 -07:00
currentLog string
lineno int64
basePath string
2015-02-18 20:33:17 -07:00
seq int
2015-02-11 20:19:46 -07:00
}
func NewNetwork(basePath string) (*Network) {
return &Network{
2015-02-21 21:45:56 -07:00
running: true,
2015-02-22 16:06:22 -07:00
Name: path.Base(basePath),
2015-02-11 20:19:46 -07:00
basePath: basePath,
}
}
2015-02-21 21:45:56 -07:00
func (nw *Network) Close() {
nw.running = false
}
2015-02-22 16:06:22 -07:00
func (nw *Network) ReadLastEventId(lastEventId string) {
for _, eventId := range strings.Split(lastEventId, " ") {
parts := strings.Split(eventId, eventIdSep)
if len(parts) != 3 {
continue
}
if parts[0] != nw.Name {
continue
}
nw.currentLog = parts[1]
nw.lineno, _ = strconv.ParseInt(parts[2], 10, 64)
return
}
2015-02-11 20:19:46 -07:00
}
2015-02-22 16:06:22 -07:00
func (nw *Network) LastEventId() string {
parts := []string{nw.Name, nw.currentLog, strconv.FormatInt(nw.lineno, 10)}
return strings.Join(parts, eventIdSep)
2015-02-11 20:19:46 -07:00
}
2015-02-21 21:45:56 -07:00
func (nw *Network) errmsg(err error) []string {
s := fmt.Sprintf("ERROR: %s", err.Error())
return []string{s}
}
func (nw *Network) Tail(out chan<- []string) {
2015-02-11 20:19:46 -07:00
if nw.currentLog == "" {
2015-02-18 20:33:17 -07:00
var err error
2015-02-11 20:19:46 -07:00
currentfn := path.Join(nw.basePath, "log", "current")
2015-02-18 20:33:17 -07:00
nw.currentLog, err = os.Readlink(currentfn)
2015-02-11 20:19:46 -07:00
if err != nil {
2015-02-21 21:45:56 -07:00
out <- nw.errmsg(err)
return
2015-02-11 20:19:46 -07:00
}
}
filepath := path.Join(nw.basePath, "log", nw.currentLog)
f, err := os.Open(filepath)
if err != nil {
2015-02-21 21:45:56 -07:00
out <- nw.errmsg(err)
return
2015-02-11 20:19:46 -07:00
}
defer f.Close()
watcher, err := fsnotify.NewWatcher()
if err != nil {
2015-02-21 21:45:56 -07:00
out <- nw.errmsg(err)
return
2015-02-11 20:19:46 -07:00
}
defer watcher.Close()
2015-02-18 20:33:17 -07:00
watcher.Add(filepath)
2015-02-21 21:45:56 -07:00
lineno := int64(0)
2015-02-11 20:19:46 -07:00
2015-02-20 16:48:52 -07:00
// XXX: some way to stop this?
2015-02-21 21:45:56 -07:00
for nw.running {
2015-02-11 20:19:46 -07:00
bf := bufio.NewScanner(f)
2015-02-21 21:45:56 -07:00
lines := make([]string, 0)
2015-02-11 20:19:46 -07:00
for bf.Scan() {
2015-02-21 21:45:56 -07:00
lineno += 1
if lineno <= nw.lineno {
continue
} else {
nw.lineno = lineno
}
2015-02-11 20:19:46 -07:00
t := bf.Text()
2015-02-21 21:45:56 -07:00
// XXX: Consider omitting PING and PONG
2015-02-11 20:19:46 -07:00
parts := strings.Split(t, " ")
if (len(parts) >= 4) && (parts[2] == "NEXTLOG") {
watcher.Remove(filepath)
2015-02-18 20:33:17 -07:00
filename := parts[3]
2015-02-20 16:48:52 -07:00
filepath = path.Join(nw.basePath, "log", filename)
2015-02-11 20:19:46 -07:00
f.Close()
f, err = os.Open(filepath)
if err != nil {
2015-02-21 21:45:56 -07:00
out <- nw.errmsg(err)
return
2015-02-11 20:19:46 -07:00
}
watcher.Add(filepath)
2015-02-21 21:45:56 -07:00
lineno = 0
2015-02-11 20:19:46 -07:00
nw.lineno = 0
}
2015-02-18 20:33:17 -07:00
lines = append(lines, t)
2015-02-11 20:19:46 -07:00
}
2015-02-18 20:33:17 -07:00
if len(lines) > 0 {
2015-02-21 21:45:56 -07:00
out <- lines
2015-02-11 20:19:46 -07:00
}
select {
case _ = <-watcher.Events:
// Somethin' happened!
case err := <-watcher.Errors:
2015-02-21 21:45:56 -07:00
out <- nw.errmsg(err)
return
2015-02-11 20:19:46 -07:00
}
}
}
2015-02-18 20:33:17 -07:00
func (nw *Network) Write(data []byte) {
epoch := time.Now().Unix()
pid := os.Getpid()
filename := fmt.Sprintf("%d-%d-%d.txt", epoch, pid, nw.seq)
filepath := path.Join(nw.basePath, "outq", filename)
ioutil.WriteFile(filepath, data, 0750)
nw.seq += 1
}
2015-02-20 16:48:52 -07:00
func Networks(basePath string) (found []*Network) {
dir, err := os.Open(basePath)
if err != nil {
return
}
defer dir.Close()
entities, _ := dir.Readdirnames(0)
for _, fn := range entities {
netdir := path.Join(basePath, fn)
_, err = os.Stat(path.Join(netdir, "nick"))
if err != nil {
continue
}
nw := NewNetwork(netdir)
found = append(found, nw)
}
return
}