Commit 2b2c6e38 authored by Jordan Sissel's avatar Jordan Sissel

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

parent 407dfadf
// +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
}
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
}
package main
import (
"os"
"syscall"
)
func file_ids(info *os.FileInfo) (uint64, int32) {
fstat := (*(info)).Sys().(*syscall.Stat_t)
return fstat.Ino, fstat.Dev
}
package main
import (
"os"
"syscall"
)
func file_ids(info *os.FileInfo) (uint64, uint64) {
fstat := (*info).Sys().(*syscall.Stat_t)
return fstat.Ino, fstat.Dev
}
package main
import (
"os"
)
func file_ids(info *os.FileInfo) (uint64, uint64) {
// No dev and inode numbers on windows, right?
return 0, 0
}
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"`
}
......@@ -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
}
......@@ -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,
}
}
......
......@@ -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");
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment