registrar.go 1.41 KB
Newer Older
1
package main
2 3 4 5 6 7 8 9 10 11 12 13 14 15

import (
  "log"
  "os"
  "syscall"
  "encoding/json"
)

func Registrar(input chan []*FileEvent) {
  for events := range input {
    state := make(map[string]*FileState)
    log.Printf("Registrar received %d events\n", len(events))
    // Take the last event found for each file source
    for _, event := range events {
16
      // skip stdin
17 18 19 20 21 22 23 24 25
      if *event.Source == "-" {
        continue
      }
      // have to dereference the FileInfo here because os.FileInfo is an
      // interface, not a struct, so Go doesn't have smarts to call the Sys()
      // method on a pointer to os.FileInfo. :(
      fstat := (*(event.fileinfo)).Sys().(*syscall.Stat_t)
      state[*event.Source] = &FileState{
        Source: event.Source,
26 27 28
        // take the offset + length of the line + newline char and
        // save it as the new starting offset.
        Offset: event.Offset + int64(len(*event.Text)) + 1,
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
        Inode: fstat.Ino,
        Device: fstat.Dev,
      }
    }

    if len(state) > 0 {
      write(state)
      os.Rename(".lumberjack.new", ".lumberjack")
    }
  }
}

func write(state map[string]*FileState) {
  log.Printf("Saving registrar state.\n")
  // Open tmp file, write, flush, rename
  file, err := os.Create(".lumberjack.new")
  if err != nil {
    log.Printf("Failed to open .lumberjack.new for writing: %s\n", err)
    return
  }

  encoder := json.NewEncoder(file)
  encoder.Encode(state)
  file.Close()
}