Method: FileMonitoring::DirStat#monitor

Defined in:
lib/file_monitoring/monitor_path.rb

#monitor(file_attr_to_checksum = nil) ⇒ Object

Recursively, read files and dirs from file system (using Glob) Handle new filesdirs. Change state for existing filesdirs Index stable files Remove non existing filesdirs is handled in method: remove_unmarked_paths



287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
# File 'lib/file_monitoring/monitor_path.rb', line 287

def monitor(file_attr_to_checksum=nil)

  # Algorithm:
  # assume that current dir is present
  # ls (glob) the dir path for child dirs and files
  # if child file is not already present, add it as new, mark it and handle its state
  # if file already present, mark it and handle its state.
  # if child dir is not already present, add it as new, mark it and propagates
  #    the recursive call
  # if child dir already present, mark it and handle its state
  # marked files will not be remove in next remove phase

  # ls (glob) the dir path for child dirs and files
  globed_paths_enum = Dir.glob(@path + "/*").to_enum
  loop do
    globed_path = globed_paths_enum.next rescue break

    # if symlink - skip
    next if File.symlink?(globed_path)

    # UTF-8 - keep only files with names in
    next if @non_utf8_paths[globed_path]
    check_utf_8_encoding_file = globed_path.clone
    unless check_utf_8_encoding_file.force_encoding("UTF-8").valid_encoding?
      Log.warning("Non UTF-8 file name '#{check_utf_8_encoding_file}', skipping.")
      @non_utf8_paths[globed_path]=true
      check_utf_8_encoding_file=nil
      next
    end

    # Get File \ Dir status
    globed_path_stat = File.lstat(globed_path) rescue next  # File or dir removed from OS file system
    if globed_path_stat.file?
      # ----------------------------- FILE -----------------------
      child_stat = @files[globed_path]
      if child_stat
        # -------------- EXISTS in Tree
        unless Params['manual_file_changes']
          # --------- NON MANUAL MODE
          child_stat.marked = true
          if child_stat.changed?(globed_path_stat)
            # ---------- STATUS CHANGED
            # Update changed status
            child_stat.state = FileStatEnum::CHANGED
            child_stat.cycles = 0
            child_stat.size = globed_path_stat.size
            child_stat.modification_time = globed_path_stat.mtime.to_i
            if @@log
              @@log.info("CHANGED file: " + globed_path)
              @@log.outputters[0].flush if Params['log_flush_each_message']
            end
            # remove file with changed checksum. File will be added once indexed
            $local_content_data_lock.synchronize{
              $local_content_data.remove_instance(Params['local_server_name'], globed_path)
            }
          else  # case child_stat did not change
            # ---------- SAME STATUS
            # File status is the same
            if child_stat.state != FileStatEnum::STABLE
              child_stat.state = FileStatEnum::UNCHANGED
              child_stat.cycles += 1
              if child_stat.cycles >= ::FileMonitoring.stable_state
                child_stat.state = FileStatEnum::STABLE
                if @@log
                  @@log.info("STABLE file: " + globed_path)
                  @@log.outputters[0].flush if Params['log_flush_each_message']
                end
              else
                if @@log
                  @@log.info("UNCHANGED file: " + globed_path)
                  @@log.outputters[0].flush if Params['log_flush_each_message']
                end
              end
            end
          end
        else  # case Params['manual_file_changes']
          # --------- MANUAL MODE
          child_stat.marked = true
        end
      else
        # ---------------------------- NEW FILE ----------
        unless Params['manual_file_changes']
          child_stat = FileStat.new(globed_path,
                                    FileStatEnum::NEW,
                                    globed_path_stat.size,
                                    globed_path_stat.mtime.to_i)
          if @@log
            @@log.info("NEW file: " + globed_path)
            @@log.outputters[0].flush if Params['log_flush_each_message']
          end
          child_stat.marked = true
          add_file(child_stat)
        else  # case Params['manual_file_changes']
          # --------------------- MANUAL MODE
          # check if file name and attributes exist in global file attr map
          file_attr_key = [File.basename(globed_path), globed_path_stat.size, globed_path_stat.mtime.to_i]
          file_ident_info = file_attr_to_checksum[file_attr_key]
          # If not found (real new file) or found but not unique then file needs indexing. skip in manual mode.
          next unless (file_ident_info and file_ident_info.unique)
          Log.debug1("update content data with file:%s  checksum:%s  index_time:%s",
                     File.basename(globed_path), file_ident_info.checksum, file_ident_info.index_time.to_s)
          # update content data (no need to update Dir tree)
          $local_content_data_lock.synchronize{
            $local_content_data.add_instance(file_ident_info.checksum,
                                             globed_path_stat.size,
                                             Params['local_server_name'],
                                             globed_path,
                                             globed_path_stat.mtime.to_i,
                                             file_ident_info.index_time)
          }
        end
      end
    else
      # ------------------------------ DIR -----------------------
      child_stat = @dirs[globed_path]
      unless child_stat
        # ----------- ADD NEW DIR
        child_stat = DirStat.new(globed_path)
        add_dir(child_stat)
        if @@log
          @@log.info("NEW dir: " + globed_path)
          @@log.outputters[0].flush if Params['log_flush_each_message']
        end
      end
      child_stat.marked = true
      # recursive call for dirs
      child_stat.monitor(file_attr_to_checksum)
    end
  end
  GC.start
end