Class: FileSystemWatcher

Inherits:
Object
  • Object
show all
Includes:
ServiceState
Defined in:
lib/filesystemwatcher/filesystemwatcher.rb

Overview

This class will watch a directory or a set of directories and alert you of new files, modified files, deleted files. You can optionally only be alerted when a files md5 hash has been changed so you only are alerted to real changes. this of course means slower performance and higher cpu/io usage.

Constant Summary collapse

CREATED =
0
MODIFIED =
1
DELETED =
2

Constants included from ServiceState

ServiceState::CONFIGURED, ServiceState::NOT_STARTED, ServiceState::STARTED, ServiceState::STOPPED

Instance Attribute Summary collapse

Attributes included from ServiceState

#endTime, #startTime

Instance Method Summary collapse

Methods included from ServiceState

#initializeState, #isConfigured?, #isStarted?, #isStopped?, #onStateChange, #setState, #stopWhen

Constructor Details

#initialize(dir = nil, expression = "**/*") ⇒ FileSystemWatcher

Returns a new instance of FileSystemWatcher.



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/filesystemwatcher/filesystemwatcher.rb', line 22

def initialize(dir=nil, expression="**/*")
  @sleepTime = 5
  @useMD5 = false
  @priority = 0
  @stopWhen = nil

  @directories = Array.new()
  @files = Array.new()

  @foundFiles = nil
  @firstLoad = true
  @watchThread = nil
  
  initializeState()

  if dir then
    addDirectory(dir, expression)
  end
end

Instance Attribute Details

#directoriesObject

the time to wait before checking the directories again



17
18
19
# File 'lib/filesystemwatcher/filesystemwatcher.rb', line 17

def directories
  @directories
end

#priorityObject

the time to wait before checking the directories again



17
18
19
# File 'lib/filesystemwatcher/filesystemwatcher.rb', line 17

def priority
  @priority
end

#sleepTimeObject

the time to wait before checking the directories again



17
18
19
# File 'lib/filesystemwatcher/filesystemwatcher.rb', line 17

def sleepTime
  @sleepTime
end

#useMD5Object

you can optionally use the file contents md5 to detect if a file has changed



20
21
22
# File 'lib/filesystemwatcher/filesystemwatcher.rb', line 20

def useMD5
  @useMD5
end

Instance Method Details

#addDirectory(dir, expression = "**/*") ⇒ Object

add a directory to be watched

Parameters:

  • dir

    the directory to watch

  • expression (defaults to: "**/*")

    the glob pattern to search under the watched directory



45
46
47
48
49
50
51
# File 'lib/filesystemwatcher/filesystemwatcher.rb', line 45

def addDirectory(dir, expression="**/*")
  if FileTest.exists?(dir) && FileTest.readable?(dir) then
    @directories << FSWatcher::Directory.new(dir, expression)
  else
    raise FSWatcher::InvalidDirectoryError, "Dir '#{dir}' either doesnt exist or isnt readable"
  end
end

#addFile(file) ⇒ Object

add a specific file to the watch list

Parameters:

  • file

    the file to watch



59
60
61
62
63
64
65
# File 'lib/filesystemwatcher/filesystemwatcher.rb', line 59

def addFile(file)
  if FileTest.exists?(file) && FileTest.readable?(file) then
    @files << file
  else
    raise FSWatcher::InvalidFileError, "File '#{file}' either doesnt exist or isnt readable"
  end
end

#joinObject

wait for the filewatcher to finish



139
140
141
# File 'lib/filesystemwatcher/filesystemwatcher.rb', line 139

def join()
  @watchThread.join() if @watchThread
end

#removeDirectory(dir) ⇒ Object



53
54
55
# File 'lib/filesystemwatcher/filesystemwatcher.rb', line 53

def removeDirectory(dir)
  @directories.delete(dir)
end

#removeFile(file) ⇒ Object



67
68
69
# File 'lib/filesystemwatcher/filesystemwatcher.rb', line 67

def removeFile(file)
  @files.delete(file)
end

#start(&block) ⇒ Object

start watching the specified files/directories



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/filesystemwatcher/filesystemwatcher.rb', line 72

def start(&block)
  if isStarted? then
    raise RuntimeError, "already started"
  end

  setState(STARTED)

  @firstLoad = true
  @foundFiles = Hash.new()

  # we watch in a new thread
  @watchThread = Thread.new {
    # we will be stopped if someone calls stop or if someone set a stopWhen that becomes true
    while !isStopped? do
	if (!@directories.empty?) or (!@files.empty?) then	
 # this will hold the list of the files we looked at this iteration
 # allows us to not look at the same file again and also to compare
 # with the foundFile list to see if something was deleted
 alreadyExamined = Hash.new()
 
 # check the files in each watched directory
 if not @directories.empty? then
   @directories.each { |dirObj|
     examineFileList(dirObj.getFiles(), alreadyExamined, &block)
   }
 end
 
 # now examine any files the user wants to specifically watch
 examineFileList(@files, alreadyExamined, &block) if not @files.empty?
 
 # see if we have to delete files from our found list
 if not @firstLoad then
   if not @foundFiles.empty? then
     # now diff the found files and the examined files to see if
     # something has been deleted
     allFoundFiles = @foundFiles.keys()
     allExaminedFiles = alreadyExamined.keys()
     intersection = allFoundFiles - allExaminedFiles
     intersection.each { |fileName|
# callback
block.call(DELETED, fileName)
# remove deleted file from the foundFiles list
@foundFiles.delete(fileName)
     }	  
   end
 else
   @firstLoad = false
 end
	end
	
	# go to sleep
	sleep(@sleepTime)
    end
  }
  
  # set the watch thread priority
  @watchThread.priority = @priority

end

#stopObject

kill the filewatcher thread



133
134
135
136
# File 'lib/filesystemwatcher/filesystemwatcher.rb', line 133

def stop()
  setState(STOPPED)
  @watchThread.wakeup()
end