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
|
|
|
|
}
|
|
|
|
|