content_server 1.5.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +15 -0
  2. data/bin/file_utils +118 -0
  3. data/lib/content_data/content_data.rb +114 -48
  4. data/lib/content_server/version.rb +1 -1
  5. data/lib/file_monitoring/file_monitoring.rb +94 -50
  6. data/lib/file_monitoring/monitor_path.rb +196 -113
  7. data/lib/file_utils/file_utils.rb +10 -49
  8. data/lib/networking/tcp.rb +4 -4
  9. data/spec/content_data/content_data_spec.rb +331 -0
  10. data/spec/content_data/validations_spec.rb +5 -0
  11. data/spec/content_server/content_server_spec.rb +5 -0
  12. data/spec/content_server/file_streamer_spec.rb +5 -0
  13. data/spec/file_copy/copy_spec.rb +5 -0
  14. data/spec/file_indexing/index_agent_spec.rb +5 -0
  15. data/spec/networking/tcp_spec.rb +5 -0
  16. data/spec/validations/index_validations_spec.rb +5 -0
  17. metadata +9 -89
  18. data/test/content_data/content_data_test.rb +0 -291
  19. data/test/file_generator/file_generator_spec.rb +0 -85
  20. data/test/file_monitoring/monitor_path_test.rb +0 -189
  21. data/test/file_monitoring/monitor_path_test/dir1000/test_file.1000 +0 -1000
  22. data/test/file_monitoring/monitor_path_test/dir1000/test_file.1000.0 +0 -1000
  23. data/test/file_monitoring/monitor_path_test/dir1000/test_file.1000.1 +0 -1000
  24. data/test/file_monitoring/monitor_path_test/dir1500/test_file.1500 +0 -1500
  25. data/test/file_monitoring/monitor_path_test/dir1500/test_file.1500.0 +0 -1500
  26. data/test/file_monitoring/monitor_path_test/dir1500/test_file.1500.1 +0 -1500
  27. data/test/file_monitoring/monitor_path_test/test_file.500 +0 -500
  28. data/test/file_monitoring/monitor_path_test/test_file.500.0 +0 -500
  29. data/test/file_monitoring/monitor_path_test/test_file.500.1 +0 -500
  30. data/test/file_utils/fileutil_mksymlink_test.rb +0 -134
  31. data/test/file_utils/fileutil_mksymlink_test/dir1000/dir1500/test_file.1500 +0 -1500
  32. data/test/file_utils/fileutil_mksymlink_test/dir1000/dir1500/test_file.1500.0 +0 -1500
  33. data/test/file_utils/fileutil_mksymlink_test/dir1000/dir1500/test_file.1500.1 +0 -1500
  34. data/test/file_utils/fileutil_mksymlink_test/dir1000/test_file.1000 +0 -1000
  35. data/test/file_utils/fileutil_mksymlink_test/dir1000/test_file.1000.0 +0 -1000
  36. data/test/file_utils/fileutil_mksymlink_test/dir1000/test_file.1000.1 +0 -1000
  37. data/test/file_utils/fileutil_mksymlink_test/test_file.500 +0 -500
  38. data/test/file_utils/fileutil_mksymlink_test/test_file.500.0 +0 -500
  39. data/test/file_utils/fileutil_mksymlink_test/test_file.500.1 +0 -500
  40. data/test/file_utils/time_modification_test.rb +0 -136
  41. data/test/params/params_spec.rb +0 -280
  42. data/test/params/params_test.rb +0 -43
  43. data/test/run_in_background/run_in_background_test.rb +0 -122
  44. data/test/run_in_background/test_app +0 -59
@@ -1,3 +1,3 @@
1
1
  module ContentServer
2
- VERSION = "1.5.0"
2
+ VERSION = "1.6.0"
3
3
  end
@@ -11,6 +11,93 @@ module FileMonitoring
11
11
  # Manages file monitoring of number of file system locations
12
12
  class FileMonitoring
13
13
 
14
+ def create_sub_paths(path)
15
+ sub_paths=[]
16
+ while path != '.' && path != '/'
17
+ sub_paths.push(path)
18
+ path = File.dirname(path)
19
+ end
20
+ sub_paths.reverse!
21
+ end
22
+
23
+ def load_instances(file_attr_to_checksum, dir_stat_array)
24
+ inst_count = 0
25
+ # If file is under monitoring path - Add to DirStat tree as stable with path,size,mod_time read from file
26
+ # If file is NOT under monitoring path - skip (not a valid usage)
27
+ $local_content_data.each_instance {
28
+ |checksum, size, _, mod_time, _, path, index_time|
29
+
30
+ if Params['manual_file_changes']
31
+ file_attr_key = [File.basename(path), size, mod_time]
32
+ ident_file_info = file_attr_to_checksum[file_attr_key]
33
+ unless ident_file_info
34
+ # Add file checksum to map
35
+ file_attr_to_checksum[file_attr_key] = IdentFileInfo.new(checksum, index_time)
36
+ else
37
+ # File already in map. Need to mark as not unique
38
+ ident_file_info.unique = false # file will be skipped if found at new location
39
+ end
40
+ end
41
+ # construct sub paths array from full file path:
42
+ # Example:
43
+ # instance path = /dir1/dir2/file_name
44
+ # sub_paths holds array => ["/dir1","/dir1/dir2","/dir1/dir2/file_name"]
45
+ # sub paths would create DirStat objs or FileStat(FileStat create using last sub path).
46
+ sub_paths = create_sub_paths(path)
47
+
48
+ # Loop over monitor paths to start build tree under each
49
+ dir_stat_array.each { | dir_stat|
50
+ # check if monitor path is one of the sub paths and find it's sub path index
51
+ # if index is found then it the monitor path
52
+ # the next index indicates the next sub path to insert to the tree
53
+ # the index will be raised at each recursive call down the tree
54
+ sub_paths_index = sub_paths.index(dir_stat[0].path)
55
+ if sub_paths_index
56
+ # monitor path was found. Add to tree
57
+ # start the recursive call with next sub path index
58
+ ::FileMonitoring.stable_state = dir_stat[1]
59
+ inst_count += 1
60
+ dir_stat[0].load_instance(sub_paths, sub_paths_index+1, size, mod_time)
61
+ break
62
+ end
63
+ }
64
+ }
65
+ Log.info("loaded instances:#{inst_count}")
66
+ end
67
+
68
+ def load_symlinks(dir_stat_array)
69
+ # If symlink file is under monitoring path - Add to DirStat tree
70
+ # If file is NOT under monitoring path - skip (not a valid usage)
71
+ symlink_count = 0
72
+ $local_content_data.each_symlink {
73
+ |_, symlink_path, symlink_target|
74
+
75
+ # construct sub paths array from symlink path:
76
+ # Example:
77
+ # symlink path = /dir1/dir2/file_name
78
+ # sub_paths holds array => ["/dir1","/dir1/dir2","/dir1/dir2/file_name"]
79
+ # sub paths should match the paths of DirStat objs in the tree to reach the symlink location in Tree.
80
+ sub_paths = create_sub_paths(symlink_path)
81
+
82
+ # Loop over monitor paths to start enter tree
83
+ dir_stat_array.each { | dir_stat|
84
+ # check if monitor path is one of the sub paths and find it's sub path index
85
+ # if index is found then it the monitor path
86
+ # the next index indicates the next sub path to insert to the tree
87
+ # the index will be raised at each recursive call down the tree
88
+ sub_paths_index = sub_paths.index(dir_stat[0].path)
89
+ if sub_paths_index
90
+ # monitor path was found. Add to tree
91
+ # start the recursive call with next sub path index
92
+ ::FileMonitoring.stable_state = dir_stat[1]
93
+ symlink_count += 1
94
+ dir_stat[0].load_symlink(sub_paths, sub_paths_index+1, symlink_path, symlink_target)
95
+ break
96
+ end
97
+ }
98
+ }
99
+ Log.info("loaded symlinks:#{symlink_count}")
100
+ end
14
101
  # The main method. Loops on all paths, each time span and monitors them.
15
102
  #
16
103
  # =Algorithm:
@@ -45,7 +132,7 @@ module FileMonitoring
45
132
  @log4r.outputters << file_outputter
46
133
  ::FileMonitoring::DirStat.set_log(@log4r)
47
134
 
48
- conf_array = Params['monitoring_paths']
135
+ conf_array = Params['monitoring_paths']
49
136
 
50
137
  # create root dirs of monitoring
51
138
  dir_stat_array = []
@@ -54,58 +141,15 @@ module FileMonitoring
54
141
  dir_stat_array.push([dir_stat, elem['stable_state']])
55
142
  }
56
143
 
144
+ # This structure is used to optimize indexing when user specifies a directory was moved.
145
+ file_attr_to_checksum = {}
146
+
57
147
  #Look over loaded content data if not empty
58
- # If file is under monitoring path - Add to DirStat tree as stable with path,size,mod_time read from file
59
- # If file is NOT under monitoring path - skip (not a valid usage)
60
- file_attr_to_checksum = {} # This structure is used to optimize indexing when user specifies a directory was moved.
61
148
  unless $local_content_data.empty?
62
149
  Log.info("Start build data base from loaded file. This could take several minutes")
63
- inst_count = 0
64
- $local_content_data.each_instance {
65
- |checksum, size, _, mod_time, _, path, index_time|
66
-
67
- if Params['manual_file_changes']
68
- file_attr_key = [File.basename(path), size, mod_time]
69
- ident_file_info = file_attr_to_checksum[file_attr_key]
70
- unless ident_file_info
71
- # Add file checksum to map
72
- file_attr_to_checksum[file_attr_key] = IdentFileInfo.new(checksum, index_time)
73
- else
74
- # File already in map. Need to mark as not unique
75
- ident_file_info.unique = false # file will be skipped if found at new location
76
- end
77
- end
78
- # construct sub paths array from full file path:
79
- # Example:
80
- # instance path = /dir1/dir2/file_name
81
- # Sub path 1: /dir1
82
- # Sub path 2: /dir1/dir2
83
- # Sub path 3: /dir1/dir2/file_name
84
- # sub paths would create DirStat objs or FileStat(FileStat create using last sub path).
85
- split_path = path.split(File::SEPARATOR)
86
- sub_paths = (0..split_path.size-1).inject([]) { |paths, i|
87
- paths.push(File.join(*split_path.values_at(0..i)))
88
- }
89
- # sub_paths holds array => ["/dir1","/dir1/dir2","/dir1/dir2/file_name"]
90
-
91
- # Loop over monitor paths to start build tree under each
92
- dir_stat_array.each { | dir_stat|
93
- # check if monitor path is one of the sub paths and find it's sub path index
94
- # if index is found then it the monitor path
95
- # the next index indicates the next sub path to insert to the tree
96
- # the index will be raised at each recursive call down the tree
97
- sub_paths_index = sub_paths.index(dir_stat[0].path)
98
- next if sub_paths_index.nil? # monitor path was not found. skip this instance.
99
-
100
- # monitor path was found. Add to tree
101
- # start the recursive call with next sub path index
102
- ::FileMonitoring.stable_state = dir_stat[1]
103
- inst_count += 1
104
- dir_stat[0].load_instance(sub_paths, sub_paths_index+1, size, mod_time)
105
- break
106
- }
107
- }
108
- Log.info("End build data base from loaded file. loaded instances:#{inst_count}")
150
+ load_instances(file_attr_to_checksum, dir_stat_array)
151
+ load_symlinks(dir_stat_array)
152
+ Log.info("End build data base from loaded file")
109
153
  $last_content_data_id = $local_content_data.unique_id
110
154
 
111
155
  if Params['manual_file_changes']
@@ -137,6 +137,13 @@ module FileMonitoring
137
137
  @@log = log
138
138
  end
139
139
 
140
+ def write_to_log(msg)
141
+ if @@log
142
+ @@log.info(msg)
143
+ @@log.outputters[0].flush if Params['log_flush_each_message']
144
+ end
145
+ end
146
+
140
147
  public_class_method :set_log
141
148
 
142
149
  # Initializes new directory monitoring object
@@ -148,7 +155,7 @@ module FileMonitoring
148
155
  @dirs = {}
149
156
  @files = {}
150
157
  @non_utf8_paths = {} # Hash: ["path" -> true|false]
151
-
158
+ @symlinks = {} # Hash: [[server, link file name]] -> " target file name"]
152
159
  # indicates if path EXISTS in file system.
153
160
  # If true, file will not be removed during removed_unmarked_paths phase.
154
161
  @marked = false
@@ -169,7 +176,7 @@ module FileMonitoring
169
176
  # size - the instance size to insert to the tree
170
177
  # modification_time - the instance modification_time to insert to the tree
171
178
  def load_instance(sub_paths, sub_paths_index, size, modification_time)
172
- # initialize dirs and files. This will indicate that the current DirStat is not new.
179
+ # initialize dirs and files.
173
180
  @dirs = {} unless @dirs
174
181
  @files = {} unless @files
175
182
  if sub_paths.size-1 == sub_paths_index
@@ -189,6 +196,40 @@ module FileMonitoring
189
196
  end
190
197
  end
191
198
 
199
+ # add symlink while initializing tree using content data from file.
200
+ # Assumption is that Tree already built
201
+ # Parameters:
202
+ # sub_paths - Array of sub paths of the symlink which is added to tree
203
+ # Example:
204
+ # instance path = /dir1/dir2/file_name
205
+ # Sub path 1: /dir1
206
+ # Sub path 2: /dir1/dir2
207
+ # Sub path 3: /dir1/dir2/file_name
208
+ # sub paths would create DirStat objs or FileStat(FileStat create using last sub path).
209
+ # sub_paths_index - the index indicates the next sub path to insert to the tree
210
+ # the index will be raised at each recursive call down the tree
211
+ # symlink_path - symlink file path
212
+ # symlink_target - the target path pointed by the symlink
213
+ def load_symlink(sub_paths, sub_paths_index, symlink_path, symlink_target)
214
+ # initialize dirs and files.
215
+ @dirs = {} unless @dirs
216
+ @files = {} unless @files
217
+ if sub_paths.size-1 == sub_paths_index
218
+ # index points to last entry - leaf case. Add the symlink.
219
+ @symlinks[symlink_path] = symlink_target
220
+ else
221
+ # Add Dir to tree if not present. index points to new dir path.
222
+ dir_stat = @dirs[sub_paths[sub_paths_index]]
223
+ #create new dir if not exist
224
+ unless dir_stat
225
+ dir_stat = DirStat.new(sub_paths[sub_paths_index])
226
+ add_dir(dir_stat)
227
+ end
228
+ # continue recursive call on tree with next sub path index
229
+ dir_stat.load_instance(sub_paths, sub_paths_index+1, symlink_path, symlink_target)
230
+ end
231
+ end
232
+
192
233
  # Adds directory for monitoring.
193
234
  def add_dir (dir)
194
235
  @dirs[dir.path] = dir
@@ -223,7 +264,7 @@ module FileMonitoring
223
264
  def to_s(indent = 0)
224
265
  indent_increment = 2
225
266
  child_indent = indent + indent_increment
226
- res = super
267
+ res = super()
227
268
  @files.each_value do |file|
228
269
  res += "\n" + file.to_s(child_indent)
229
270
  end if @files
@@ -245,10 +286,7 @@ module FileMonitoring
245
286
  dir_stat.removed_unmarked_paths
246
287
  else
247
288
  # directory is not marked. Remove it, since it does not exist.
248
- if @@log
249
- @@log.info("NON_EXISTING dir: " + dir_stat.path)
250
- @@log.outputters[0].flush if Params['log_flush_each_message']
251
- end
289
+ write_to_log("NON_EXISTING dir: " + dir_stat.path)
252
290
  # remove file with changed checksum
253
291
  $local_content_data_lock.synchronize{
254
292
  $local_content_data.remove_directory(dir_stat.path, Params['local_server_name'])
@@ -265,10 +303,7 @@ module FileMonitoring
265
303
  file_stat.marked = false # unset flag for next monitoring\index\remove phase
266
304
  else
267
305
  # file not marked meaning it is no longer exist. Remove.
268
- if @@log
269
- @@log.info("NON_EXISTING file: " + file_stat.path)
270
- @@log.outputters[0].flush if Params['log_flush_each_message']
271
- end
306
+ write_to_log("NON_EXISTING file: " + file_stat.path)
272
307
  # remove file with changed checksum
273
308
  $local_content_data_lock.synchronize{
274
309
  $local_content_data.remove_instance(Params['local_server_name'], file_stat.path)
@@ -279,14 +314,139 @@ module FileMonitoring
279
314
  end
280
315
  end
281
316
 
282
- # Recursively, read files and dirs from file system (using Glob)
283
- # Handle new files\dirs.
284
- # Change state for existing files\dirs
285
- # Index stable files
286
- # Remove non existing files\dirs is handled in method: remove_unmarked_paths
317
+ ################ All monitoring helper methods #################
318
+
319
+ # Checks that the globed path is valid.
320
+ def is_globed_path_valid(globed_path)
321
+ # UTF-8 - keep only files with names in
322
+ return true if @non_utf8_paths[globed_path]
323
+ check_utf_8_encoding_file = globed_path.clone
324
+ unless check_utf_8_encoding_file.force_encoding("UTF-8").valid_encoding?
325
+ Log.warning("Non UTF-8 file name '#{check_utf_8_encoding_file}', skipping.")
326
+ @non_utf8_paths[globed_path] = true
327
+ # TODO(bbfsdev): Remove line below and redundant clones of string after
328
+ # those lines are not a GC problem.
329
+ check_utf_8_encoding_file = nil
330
+ return false
331
+ end
332
+
333
+ true
334
+ end
335
+
336
+ def handle_existing_file(child_stat, globed_path, globed_path_stat)
337
+ if child_stat.changed?(globed_path_stat)
338
+ # ---------- STATUS CHANGED
339
+ # Update changed status
340
+ child_stat.state = FileStatEnum::CHANGED
341
+ child_stat.cycles = 0
342
+ child_stat.size = globed_path_stat.size
343
+ child_stat.modification_time = globed_path_stat.mtime.to_i
344
+ write_to_log("CHANGED file: " + globed_path)
345
+ # remove file with changed checksum. File will be added once indexed
346
+ $local_content_data_lock.synchronize{
347
+ $local_content_data.remove_instance(Params['local_server_name'], globed_path)
348
+ }
349
+ else # case child_stat did not change
350
+ # ---------- SAME STATUS
351
+ # File status is the same
352
+ if child_stat.state != FileStatEnum::STABLE
353
+ child_stat.cycles += 1
354
+ if child_stat.cycles >= ::FileMonitoring.stable_state
355
+ child_stat.state = FileStatEnum::STABLE
356
+ write_to_log("STABLE file: " + globed_path)
357
+ else
358
+ child_stat.state = FileStatEnum::UNCHANGED
359
+ write_to_log("UNCHANGED file: " + globed_path)
360
+ end
361
+ end
362
+ end
363
+ end
364
+
365
+ # This method handles the case where we set the 'manual_file_changes' param meaning
366
+ # some files were moved/copied and no need to reindex them. In that case search "new files"
367
+ # in old files to get the checksum (skipp the index phase).
368
+ # The lookup is done via specially prepared file_attr_to_checksum map.
369
+ def handle_moved_file(globed_path, globed_path_stat, file_attr_to_checksum)
370
+ # --------------------- MANUAL MODE
371
+ # check if file name and attributes exist in global file attr map
372
+ file_attr_key = [File.basename(globed_path), globed_path_stat.size, globed_path_stat.mtime.to_i]
373
+ file_ident_info = file_attr_to_checksum[file_attr_key]
374
+ # If not found (real new file) or found but not unique then file needs indexing. skip in manual mode.
375
+ if file_ident_info && file_ident_info.unique
376
+ Log.debug1("update content data with file:%s checksum:%s index_time:%s",
377
+ File.basename(globed_path), file_ident_info.checksum, file_ident_info.index_time.to_s)
378
+ # update content data (no need to update Dir tree)
379
+ $local_content_data_lock.synchronize{
380
+ $local_content_data.add_instance(file_ident_info.checksum,
381
+ globed_path_stat.size,
382
+ Params['local_server_name'],
383
+ globed_path,
384
+ globed_path_stat.mtime.to_i,
385
+ file_ident_info.index_time)
386
+ }
387
+ end
388
+ end
389
+
390
+ def handle_new_file(child_stat, globed_path, globed_path_stat)
391
+ child_stat = FileStat.new(globed_path,
392
+ FileStatEnum::NEW,
393
+ globed_path_stat.size,
394
+ globed_path_stat.mtime.to_i)
395
+ write_to_log("NEW file: " + globed_path)
396
+ child_stat.marked = true
397
+ add_file(child_stat)
398
+ end
399
+
400
+ def handle_dir(globed_path, file_attr_to_checksum)
401
+ # ------------------------------ DIR -----------------------
402
+ child_stat = @dirs[globed_path]
403
+ unless child_stat
404
+ # ----------- ADD NEW DIR
405
+ child_stat = DirStat.new(globed_path)
406
+ add_dir(child_stat)
407
+ write_to_log("NEW dir: " + globed_path)
408
+ end
409
+ child_stat.marked = true
410
+ # recursive call for dirs
411
+ child_stat.monitor(file_attr_to_checksum)
412
+ end
413
+
414
+ def add_found_symlinks(globed_path, found_symlinks)
415
+ # if symlink - add to symlink temporary map and content data (even override).
416
+ # later all non existing symlinks will be removed from content data
417
+ pointed_file_name = File.readlink(globed_path)
418
+ found_symlinks[globed_path] = pointed_file_name
419
+ # add to content data
420
+ $local_content_data_lock.synchronize{
421
+ $local_content_data.add_symlink(Params['local_server_name'], globed_path, pointed_file_name)
422
+ }
423
+ end
424
+
425
+ def remove_not_found_symlinks(found_symlinks)
426
+ # check if any symlink was removed and update current symlinks map
427
+ symlinks_enum = @symlinks.each_key
428
+ loop {
429
+ symlink_key = symlinks_enum.next rescue break
430
+ unless found_symlinks.has_key?(symlink_key)
431
+ # symlink was removed. remove from content data
432
+ $local_content_data_lock.synchronize{
433
+ $local_content_data.remove_symlink(Params['local_server_name'], symlink_key)
434
+ }
435
+ end
436
+ }
437
+ @symlinks = found_symlinks
438
+ end
439
+
440
+ # Recursively, read files and dirs lists from file system (using Glob)
441
+ # - Adds new files\dirs.
442
+ # - Change state for existing files\dirs
443
+ # - Index stable files
444
+ # - Remove non existing files\dirs is handled in method: remove_unmarked_paths
445
+ # - Handles special case for param 'manual_file_changes' where files are moved and
446
+ # there is no need to index them
287
447
  def monitor(file_attr_to_checksum=nil)
288
448
 
289
- # Algorithm:
449
+ # Marking/Removing Algorithm:
290
450
  # assume that current dir is present
291
451
  # ls (glob) the dir path for child dirs and files
292
452
  # if child file is not already present, add it as new, mark it and handle its state
@@ -298,19 +458,14 @@ module FileMonitoring
298
458
 
299
459
  # ls (glob) the dir path for child dirs and files
300
460
  globed_paths_enum = Dir.glob(@path + "/*").to_enum
461
+
462
+ found_symlinks = {} # Store found symlinks under dir
301
463
  loop do
302
464
  globed_path = globed_paths_enum.next rescue break
303
465
 
304
- # if symlink - skip
305
- next if File.symlink?(globed_path)
306
-
307
- # UTF-8 - keep only files with names in
308
- next if @non_utf8_paths[globed_path]
309
- check_utf_8_encoding_file = globed_path.clone
310
- unless check_utf_8_encoding_file.force_encoding("UTF-8").valid_encoding?
311
- Log.warning("Non UTF-8 file name '#{check_utf_8_encoding_file}', skipping.")
312
- @non_utf8_paths[globed_path]=true
313
- check_utf_8_encoding_file=nil
466
+ next unless is_globed_path_valid(globed_path)
467
+ if File.symlink?(globed_path)
468
+ add_found_symlinks(globed_path, found_symlinks)
314
469
  next
315
470
  end
316
471
 
@@ -320,99 +475,27 @@ module FileMonitoring
320
475
  # ----------------------------- FILE -----------------------
321
476
  child_stat = @files[globed_path]
322
477
  if child_stat
323
- # -------------- EXISTS in Tree
324
- unless Params['manual_file_changes']
325
- # --------- NON MANUAL MODE
326
- child_stat.marked = true
327
- if child_stat.changed?(globed_path_stat)
328
- # ---------- STATUS CHANGED
329
- # Update changed status
330
- child_stat.state = FileStatEnum::CHANGED
331
- child_stat.cycles = 0
332
- child_stat.size = globed_path_stat.size
333
- child_stat.modification_time = globed_path_stat.mtime.to_i
334
- if @@log
335
- @@log.info("CHANGED file: " + globed_path)
336
- @@log.outputters[0].flush if Params['log_flush_each_message']
337
- end
338
- # remove file with changed checksum. File will be added once indexed
339
- $local_content_data_lock.synchronize{
340
- $local_content_data.remove_instance(Params['local_server_name'], globed_path)
341
- }
342
- else # case child_stat did not change
343
- # ---------- SAME STATUS
344
- # File status is the same
345
- if child_stat.state != FileStatEnum::STABLE
346
- child_stat.state = FileStatEnum::UNCHANGED
347
- child_stat.cycles += 1
348
- if child_stat.cycles >= ::FileMonitoring.stable_state
349
- child_stat.state = FileStatEnum::STABLE
350
- if @@log
351
- @@log.info("STABLE file: " + globed_path)
352
- @@log.outputters[0].flush if Params['log_flush_each_message']
353
- end
354
- else
355
- if @@log
356
- @@log.info("UNCHANGED file: " + globed_path)
357
- @@log.outputters[0].flush if Params['log_flush_each_message']
358
- end
359
- end
360
- end
361
- end
362
- else # case Params['manual_file_changes']
363
- # --------- MANUAL MODE
364
- child_stat.marked = true
365
- end
478
+ # Mark that file exists (will not be deleted at end of monitoring)
479
+ child_stat.marked = true
480
+ # Handle existing file If we are not in manual mode.
481
+ # In manual mode do nothing
482
+ handle_existing_file(child_stat, globed_path, globed_path_stat) unless Params['manual_file_changes']
366
483
  else
367
- # ---------------------------- NEW FILE ----------
368
484
  unless Params['manual_file_changes']
369
- child_stat = FileStat.new(globed_path,
370
- FileStatEnum::NEW,
371
- globed_path_stat.size,
372
- globed_path_stat.mtime.to_i)
373
- if @@log
374
- @@log.info("NEW file: " + globed_path)
375
- @@log.outputters[0].flush if Params['log_flush_each_message']
376
- end
377
- child_stat.marked = true
378
- add_file(child_stat)
379
- else # case Params['manual_file_changes']
380
- # --------------------- MANUAL MODE
381
- # check if file name and attributes exist in global file attr map
382
- file_attr_key = [File.basename(globed_path), globed_path_stat.size, globed_path_stat.mtime.to_i]
383
- file_ident_info = file_attr_to_checksum[file_attr_key]
384
- # If not found (real new file) or found but not unique then file needs indexing. skip in manual mode.
385
- next unless (file_ident_info and file_ident_info.unique)
386
- Log.debug1("update content data with file:%s checksum:%s index_time:%s",
387
- File.basename(globed_path), file_ident_info.checksum, file_ident_info.index_time.to_s)
388
- # update content data (no need to update Dir tree)
389
- $local_content_data_lock.synchronize{
390
- $local_content_data.add_instance(file_ident_info.checksum,
391
- globed_path_stat.size,
392
- Params['local_server_name'],
393
- globed_path,
394
- globed_path_stat.mtime.to_i,
395
- file_ident_info.index_time)
396
- }
485
+ # Handle regular case of new file.
486
+ handle_new_file(child_stat, globed_path, globed_path_stat)
487
+ else
488
+ # Only create new content data instance based on copied/moved filed.
489
+ handle_moved_file(globed_path, globed_path_stat, file_attr_to_checksum)
397
490
  end
398
491
  end
399
492
  else
400
- # ------------------------------ DIR -----------------------
401
- child_stat = @dirs[globed_path]
402
- unless child_stat
403
- # ----------- ADD NEW DIR
404
- child_stat = DirStat.new(globed_path)
405
- add_dir(child_stat)
406
- if @@log
407
- @@log.info("NEW dir: " + globed_path)
408
- @@log.outputters[0].flush if Params['log_flush_each_message']
409
- end
410
- end
411
- child_stat.marked = true
412
- # recursive call for dirs
413
- child_stat.monitor(file_attr_to_checksum)
493
+ handle_dir(globed_path, file_attr_to_checksum)
414
494
  end
415
495
  end
496
+
497
+ remove_not_found_symlinks(found_symlinks)
498
+
416
499
  GC.start
417
500
  end
418
501