Permalink
Browse files

- move platform-specific stuff to specific separate files and functions.

  • Loading branch information...
jordansissel committed Oct 16, 2013
1 parent 407dfad commit 2b2c6e38e0884ea9fcddfc511a358ea665a8a66d
Showing with 111 additions and 42 deletions.
  1. +35 −0 filecompare.go
  2. +21 −0 filecompare_windows.go
  3. +11 −0 fileinfo_darwin.go
  4. +11 −0 fileinfo_linux.go
  5. +10 −0 fileinfo_windows.go
  6. +8 −0 filestate_windows.go
  7. +11 −37 prospector.go
  8. +3 −4 registrar.go
  9. +1 −1 syslog_windows.go
View
@@ -0,0 +1,35 @@
// +build !windows
package main
import (
"os"
"syscall"
)
func is_file_same(path string, info os.FileInfo, state *FileState) bool {
fstat := info.Sys().(*syscall.Stat_t)
return (fstat.Ino != state.Inode && fstat.Dev == state.Device)
}
func is_fileinfo_same(a os.FileInfo, b os.FileInfo) bool {
af := a.Sys().(*syscall.Stat_t)
bf := b.Sys().(*syscall.Stat_t)
return (af.Dev != bf.Dev || af.Ino != bf.Ino)
}
func is_file_renamed(file string, info os.FileInfo, fileinfo map[string]os.FileInfo) bool {
stat := info.Sys().(*syscall.Stat_t)
for kf, ki := range fileinfo {
if kf == file {
continue
}
ks := ki.Sys().(*syscall.Stat_t)
if stat.Dev == ks.Dev && stat.Ino == ks.Ino {
return true
}
}
return false
}
View
@@ -0,0 +1,21 @@
package main
import (
"os"
)
func is_file_same(path string, info os.FileInfo, state *FileState) bool {
// Do we have any other way to validate a file is the same file
// under windows?
return path == *state.Source
}
func is_fileinfo_same(a os.FileInfo, b os.FileInfo) bool {
// Anything meaningful to compare on file infos?
return true
}
func is_file_renamed(file string, info os.FileInfo, fileinfo map[string]os.FileInfo) bool {
// Can we detect if a file was renamed on Windows?
return false
}
View
@@ -0,0 +1,11 @@
package main
import (
"os"
"syscall"
)
func file_ids(info *os.FileInfo) (uint64, int32) {
fstat := (*(info)).Sys().(*syscall.Stat_t)
return fstat.Ino, fstat.Dev
}
View
@@ -0,0 +1,11 @@
package main
import (
"os"
"syscall"
)
func file_ids(info *os.FileInfo) (uint64, uint64) {
fstat := (*info).Sys().(*syscall.Stat_t)
return fstat.Ino, fstat.Dev
}
View
@@ -0,0 +1,10 @@
package main
import (
"os"
)
func file_ids(info *os.FileInfo) (uint64, uint64) {
// No dev and inode numbers on windows, right?
return 0, 0
}
View
@@ -0,0 +1,8 @@
package main
type FileState struct {
Source *string `json:"source,omitempty"`
Offset int64 `json:"offset,omitempty"`
Inode uint64 `json:"inode,omitempty"`
Device uint64 `json:"device,omitempty"`
}
View
@@ -4,7 +4,6 @@ import (
"time"
"path/filepath"
"encoding/json"
"syscall"
"os"
"log"
)
@@ -52,8 +51,7 @@ func resume_tracking(fileconfig FileConfig, fileinfo map[string]os.FileInfo, out
info, err := os.Stat(path)
if err != nil { continue }
fstat := info.Sys().(*syscall.Stat_t)
if fstat.Ino != state.Inode && fstat.Dev == state.Device {
if is_file_same(path, info, state) {
// same file, seek to last known position
fileinfo[path] = info
@@ -116,44 +114,20 @@ func prospector_scan(path string, fields map[string]string,
// TODO(sissel): Make the 'ignore if older than N' tunable
if time.Since(info.ModTime()) > 24*time.Hour {
log.Printf("Skipping old file: %s\n", file)
} else {
} else if is_file_renamed(file, info, fileinfo) {
// Check to see if this file was simply renamed (known inode+dev)
stat := info.Sys().(*syscall.Stat_t)
renamed := false
for kf, ki := range fileinfo {
if kf == file {
continue
}
ks := ki.Sys().(*syscall.Stat_t)
if stat.Dev == ks.Dev && stat.Ino == ks.Ino {
log.Printf("Skipping %s (old known name: %s)\n", file, kf)
renamed = true
// Delete the old entry
delete(fileinfo, kf)
break
}
}
if !renamed {
log.Printf("Launching harvester on new file: %s\n", file)
harvester := Harvester{Path: file, Fields: fields}
go harvester.Harvest(output)
}
}
} else {
// TODO(sissel): FileInfo.Sys() can be nil on unsupported platforms.
laststat := lastinfo.Sys().(*syscall.Stat_t)
stat := info.Sys().(*syscall.Stat_t)
// Compare inode and device; it's a 'new file' if either have changed.
// aka, the file was rotated/renamed/whatever
if stat.Dev != laststat.Dev || stat.Ino != laststat.Ino {
log.Printf("Launching harvester on rotated file: %s\n", file)
// TODO(sissel): log 'file rotated' or osmething
// Start a harvester on the path; a new file appeared with the same name.
} else {
// Most likely a new file. Harvest it!
log.Printf("Launching harvester on new file: %s\n", file)
harvester := Harvester{Path: file, Fields: fields}
go harvester.Harvest(output)
}
} else if !is_fileinfo_same(lastinfo, info) {
log.Printf("Launching harvester on rotated file: %s\n", file)
// TODO(sissel): log 'file rotated' or osmething
// Start a harvester on the path; a new file appeared with the same name.
harvester := Harvester{Path: file, Fields: fields}
go harvester.Harvest(output)
}
} // for each file matched by the glob
}
View
@@ -3,7 +3,6 @@ package main
import (
"log"
"os"
"syscall"
"encoding/json"
)
@@ -20,14 +19,14 @@ func Registrar(input chan []*FileEvent) {
// 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)
ino, dev := file_ids(event.fileinfo)
state[*event.Source] = &FileState{
Source: event.Source,
// 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,
Inode: fstat.Ino,
Device: fstat.Dev,
Inode: ino,
Device: dev,
}
}
View
@@ -3,5 +3,5 @@ package main
import "log"
func configureSyslog() {
log.Logf("Logging to syslog not supported on this platform\n");
log.Printf("Logging to syslog not supported on this platform\n");
}

0 comments on commit 2b2c6e3

Please sign in to comment.