Skip to content
This repository has been archived by the owner on Jun 8, 2022. It is now read-only.

Feature: Add FSN type. #123

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 30 additions & 5 deletions fsnotify.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@ package fsnotify
import "fmt"

const (
FSN_CREATE = 1
FSN_MODIFY = 2
FSN_DELETE = 4
FSN_RENAME = 8
FSN_CREATE = 1 << iota
FSN_MODIFY
FSN_DELETE
FSN_RENAME
FSN_CLOSE_WRITE

FSN_ALL = FSN_MODIFY | FSN_DELETE | FSN_RENAME | FSN_CREATE
FSN_ALL = FSN_MODIFY | FSN_DELETE | FSN_RENAME | FSN_CREATE | FSN_CLOSE_WRITE
)

// Purge events from interal chan to external chan if passes filter
Expand All @@ -40,6 +41,26 @@ func (w *Watcher) purgeEvents() {
sendEvent = true
}

// In some cases, we make sure a file change is finished before we read it.
// So how do you do that? Try using IN_CLOSE_WRITE instead.
//
// https://stackoverflow.com/questions/32377517/inotify-event-in-modify-occurring-twice-for-tftp-put/32424150
// Q: What is the difference between IN_MODIFY and IN_CLOSE_WRITE?
// The IN_MODIFY event is emitted on a file content change (e.g. via the write() syscall)
// while IN_CLOSE_WRITE occurs on closing the changed file.
// It means each change operation causes one IN_MODIFY event (it may occur many times during manipulations with an open file)
// whereas IN_CLOSE_WRITE is emitted only once (on closing the file).
//
// Q: Is it better to use IN_MODIFY or IN_CLOSE_WRITE?
// It varies from case to case. Usually it is more suitable to use IN_CLOSE_WRITE
// because if emitted the all changes on the appropriate file are safely written inside the file.
// The IN_MODIFY event needn't mean that a file change is finished (data may remain in memory buffers in the application).
// On the other hand, many logs and similar files must be monitored using IN_MODIFY -
// in such cases where these files are permanently open and thus no IN_CLOSE_WRITE can be emitted.
if (fsnFlags&FSN_CLOSE_WRITE == FSN_CLOSE_WRITE) && ev.IsCloseWrite() {
sendEvent = true
}

if sendEvent {
w.Event <- ev
}
Expand Down Expand Up @@ -103,6 +124,10 @@ func (e *FileEvent) String() string {
events += "|" + "ATTRIB"
}

if e.IsCloseWrite() {
events += "|" + "CLOSE_WRITE"
}

if len(events) > 0 {
events = events[1:]
}
Expand Down
7 changes: 6 additions & 1 deletion fsnotify_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const (
sys_IN_MOVE_SELF uint32 = syscall.IN_MOVE_SELF
sys_IN_OPEN uint32 = syscall.IN_OPEN

sys_AGNOSTIC_EVENTS = sys_IN_MOVED_TO | sys_IN_MOVED_FROM | sys_IN_CREATE | sys_IN_ATTRIB | sys_IN_MODIFY | sys_IN_MOVE_SELF | sys_IN_DELETE | sys_IN_DELETE_SELF
sys_AGNOSTIC_EVENTS = sys_IN_CLOSE_WRITE | sys_IN_MOVED_TO | sys_IN_MOVED_FROM | sys_IN_CREATE | sys_IN_ATTRIB | sys_IN_MODIFY | sys_IN_MOVE_SELF | sys_IN_DELETE | sys_IN_DELETE_SELF

// Special events
sys_IN_ISDIR uint32 = syscall.IN_ISDIR
Expand Down Expand Up @@ -87,6 +87,11 @@ func (e *FileEvent) IsAttrib() bool {
return (e.mask & sys_IN_ATTRIB) == sys_IN_ATTRIB
}

// IsCloseWrite reports whether the FileEvent was triggered by closing the changed file.
func (e *FileEvent) IsCloseWrite() bool {
return (e.mask & sys_IN_CLOSE_WRITE) == sys_IN_CLOSE_WRITE
}

type watch struct {
wd uint32 // Watch descriptor (as returned by the inotify_add_watch() syscall)
flags uint32 // inotify flags of this watch (see inotify(7) for the list of valid flags)
Expand Down