content_server 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. data/bin/backup_server +8 -20
  2. data/bin/content_server +8 -20
  3. data/bin/testing_memory +60 -0
  4. data/bin/testing_server +57 -0
  5. data/ext/run_in_background/mkrf_conf.rb +34 -0
  6. data/lib/content_data/content_data.rb +613 -0
  7. data/lib/content_data/version.rb +3 -0
  8. data/lib/content_data.rb +6 -0
  9. data/lib/content_server/backup_server.rb +65 -86
  10. data/lib/content_server/content_server.rb +47 -77
  11. data/lib/content_server/file_streamer.rb +27 -33
  12. data/lib/content_server/queue_copy.rb +154 -49
  13. data/lib/content_server/queue_indexer.rb +19 -11
  14. data/lib/content_server/remote_content.rb +41 -23
  15. data/lib/content_server/server.rb +91 -0
  16. data/lib/content_server/version.rb +1 -1
  17. data/lib/content_server.rb +0 -15
  18. data/lib/email/email.rb +87 -0
  19. data/lib/email/version.rb +3 -0
  20. data/lib/email.rb +4 -0
  21. data/lib/file_copy/copy.rb +68 -0
  22. data/lib/file_copy/version.rb +4 -0
  23. data/lib/file_copy.rb +4 -0
  24. data/lib/file_indexing/index_agent.rb +170 -0
  25. data/lib/file_indexing/indexer_patterns.rb +72 -0
  26. data/lib/file_indexing/version.rb +3 -0
  27. data/lib/file_indexing.rb +9 -0
  28. data/lib/file_monitoring/file_monitoring.rb +105 -0
  29. data/lib/file_monitoring/monitor_path.rb +304 -0
  30. data/lib/file_monitoring/version.rb +3 -0
  31. data/lib/file_monitoring.rb +29 -0
  32. data/lib/file_utils/file_generator/README +97 -0
  33. data/lib/file_utils/file_generator/file_generator.rb +156 -0
  34. data/lib/file_utils/file_utils.rb +260 -0
  35. data/lib/file_utils/version.rb +3 -0
  36. data/lib/file_utils.rb +4 -0
  37. data/lib/log/version.rb +3 -0
  38. data/lib/log.rb +188 -0
  39. data/lib/networking/tcp.rb +213 -0
  40. data/lib/networking/version.rb +3 -0
  41. data/lib/networking.rb +4 -0
  42. data/lib/params/version.rb +3 -0
  43. data/lib/params.rb +419 -0
  44. data/lib/process_monitoring/monitoring.rb +85 -0
  45. data/lib/process_monitoring/monitoring_info.rb +79 -0
  46. data/lib/process_monitoring/send_email.rb +40 -0
  47. data/lib/process_monitoring/thread_safe_hash.rb +77 -0
  48. data/lib/process_monitoring/version.rb +3 -0
  49. data/lib/process_monitoring.rb +6 -0
  50. data/lib/run_in_background/version.rb +3 -0
  51. data/lib/run_in_background.rb +432 -0
  52. data/lib/testing_memory/testing_memory.rb +187 -0
  53. data/lib/testing_server/testing_server.rb +236 -0
  54. data/lib/testing_server/version.rb +3 -0
  55. data/lib/testing_server.rb +12 -0
  56. data/lib/validations/index_validations.rb +106 -0
  57. data/lib/validations/version.rb +3 -0
  58. data/lib/validations.rb +4 -0
  59. data/spec/content_data/validations_spec.rb +113 -0
  60. data/spec/file_copy/copy_spec.rb +54 -0
  61. data/spec/file_indexing/index_agent_spec.rb +53 -0
  62. data/spec/networking/tcp_spec.rb +95 -0
  63. data/spec/validations/index_validations_spec.rb +77 -0
  64. data/test/content_data/content_data_test.rb +290 -0
  65. data/test/file_generator/file_generator_spec.rb +84 -0
  66. data/test/file_indexing/index_agent_test/New.txt +0 -0
  67. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/bin/libexslt.dll +0 -0
  68. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/bin/libxslt.dll +0 -0
  69. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/bin/xsltproc.exe +0 -0
  70. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libexslt/exslt.h +102 -0
  71. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libexslt/exsltconfig.h +73 -0
  72. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libexslt/exsltexports.h +140 -0
  73. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libexslt/libexslt.h +29 -0
  74. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/attributes.h +38 -0
  75. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/documents.h +93 -0
  76. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/extensions.h +262 -0
  77. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/extra.h +80 -0
  78. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/functions.h +78 -0
  79. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/imports.h +75 -0
  80. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/keys.h +53 -0
  81. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/libxslt.h +30 -0
  82. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/namespaces.h +68 -0
  83. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/numbersInternals.h +69 -0
  84. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/pattern.h +81 -0
  85. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/preproc.h +43 -0
  86. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/security.h +104 -0
  87. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/templates.h +77 -0
  88. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/transform.h +207 -0
  89. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/trio.h +216 -0
  90. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/triodef.h +220 -0
  91. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/variables.h +91 -0
  92. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/win32config.h +101 -0
  93. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xslt.h +103 -0
  94. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xsltInternals.h +1967 -0
  95. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xsltconfig.h +172 -0
  96. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xsltexports.h +142 -0
  97. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xsltlocale.h +57 -0
  98. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xsltutils.h +309 -0
  99. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xsltwin32config.h +105 -0
  100. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/lib/libexslt.lib +0 -0
  101. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/lib/libexslt_a.lib +0 -0
  102. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/lib/libxslt.lib +0 -0
  103. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/lib/libxslt_a.lib +0 -0
  104. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/readme.txt +22 -0
  105. data/test/file_indexing/index_agent_test/patterns.input +3 -0
  106. data/test/file_indexing/index_agent_test.rb +51 -0
  107. data/test/file_monitoring/file_monitoring_test/conf.yml +4 -0
  108. data/test/file_monitoring/file_monitoring_test/conf_win32.yml +5 -0
  109. data/test/file_monitoring/file_monitoring_test/log +56 -0
  110. data/test/file_monitoring/file_monitoring_test.rb +0 -0
  111. data/test/file_monitoring/monitor_path_test/dir1000/test_file.1000 +1000 -0
  112. data/test/file_monitoring/monitor_path_test/dir1000/test_file.1000.0 +1000 -0
  113. data/test/file_monitoring/monitor_path_test/dir1000/test_file.1000.1 +1000 -0
  114. data/test/file_monitoring/monitor_path_test/dir1500/test_file.1500 +1500 -0
  115. data/test/file_monitoring/monitor_path_test/dir1500/test_file.1500.0 +1500 -0
  116. data/test/file_monitoring/monitor_path_test/dir1500/test_file.1500.1 +1500 -0
  117. data/test/file_monitoring/monitor_path_test/test_file.500 +500 -0
  118. data/test/file_monitoring/monitor_path_test/test_file.500.0 +500 -0
  119. data/test/file_monitoring/monitor_path_test/test_file.500.1 +500 -0
  120. data/test/file_monitoring/monitor_path_test.rb +153 -0
  121. data/test/file_utils/fileutil_mksymlink_test/dir1000/dir1500/test_file.1500 +1500 -0
  122. data/test/file_utils/fileutil_mksymlink_test/dir1000/dir1500/test_file.1500.0 +1500 -0
  123. data/test/file_utils/fileutil_mksymlink_test/dir1000/dir1500/test_file.1500.1 +1500 -0
  124. data/test/file_utils/fileutil_mksymlink_test/dir1000/test_file.1000 +1000 -0
  125. data/test/file_utils/fileutil_mksymlink_test/dir1000/test_file.1000.0 +1000 -0
  126. data/test/file_utils/fileutil_mksymlink_test/dir1000/test_file.1000.1 +1000 -0
  127. data/test/file_utils/fileutil_mksymlink_test/test_file.500 +500 -0
  128. data/test/file_utils/fileutil_mksymlink_test/test_file.500.0 +500 -0
  129. data/test/file_utils/fileutil_mksymlink_test/test_file.500.1 +500 -0
  130. data/test/file_utils/fileutil_mksymlink_test.rb +125 -0
  131. data/test/file_utils/time_modification_test.rb +132 -0
  132. data/test/params/params_spec.rb +280 -0
  133. data/test/params/params_test.rb +43 -0
  134. data/test/run_in_background/run_in_background_test.rb +122 -0
  135. data/test/run_in_background/test_app +57 -0
  136. metadata +272 -132
  137. data/lib/content_server/globals.rb +0 -10
@@ -0,0 +1,87 @@
1
+ require 'net/smtp'
2
+
3
+ module Email
4
+
5
+ def Email.send_raw_email(from, password, to, mail_text)
6
+ smtp = Net::SMTP.new('smtp.gmail.com', 587)
7
+ smtp.enable_starttls
8
+ smtp.start(from.split('@')[-1], from, password, :login) do
9
+ smtp.send_message(mail_text, from, to)
10
+ end
11
+ end
12
+
13
+ def Email.send_email(from, password, to, subject, body)
14
+ marker = (0...50).map{ ('a'..'z').to_a[rand(26)] }.join
15
+ parts = []
16
+ parts << <<EOF
17
+ From: #{from}
18
+ To: #{to}
19
+ Subject: #{subject}
20
+ MIME-Version: 1.0
21
+ Content-Type: multipart/mixed; boundary=#{marker}
22
+ --#{marker}
23
+ EOF
24
+
25
+ # Define the message action
26
+ parts << <<EOF
27
+ Content-Type: text/plain
28
+ Content-Transfer-Encoding:8bit
29
+
30
+ #{body}
31
+ --#{marker}
32
+ EOF
33
+
34
+ mailtext = parts.join('')
35
+ send_raw_email(from, password, to, mailtext)
36
+ end
37
+
38
+ def Email.send_attachments_email(from, password, to, subject, body, attachments)
39
+ # Read a file and encode it into base64 format
40
+ begin
41
+ encoded_attachments = []
42
+ attachments.each do |attachment|
43
+ file_content = File.read(attachment)
44
+ encoded_content = [file_content].pack("m") # base64
45
+ encoded_attachments << [attachment, encoded_content]
46
+ end
47
+ rescue
48
+ raise "Could not read file #{attachment}"
49
+ end
50
+
51
+ marker = (0...50).map{ ('a'..'z').to_a[rand(26)] }.join
52
+ parts = []
53
+ parts << <<EOF
54
+ From: #{from}
55
+ To: #{to}
56
+ Subject: #{subject}
57
+ MIME-Version: 1.0
58
+ Content-Type: multipart/mixed; boundary=#{marker}
59
+ --#{marker}
60
+ EOF
61
+
62
+ # Define the message action
63
+ parts << <<EOF
64
+ Content-Type: text/plain
65
+ Content-Transfer-Encoding:8bit
66
+
67
+ #{body}
68
+ --#{marker}
69
+ EOF
70
+
71
+ encoded_attachments.each do |attachment, encoded_content|
72
+ # Define the attachment section
73
+ parts << <<EOF
74
+ Content-Type: multipart/mixed; name=\"#{File.basename(attachment)}\"
75
+ Content-Transfer-Encoding:base64
76
+ Content-Disposition: attachment; filename="#{File.basename(attachment)}"
77
+
78
+ #{encoded_content}
79
+ --#{marker}--
80
+ EOF
81
+ end
82
+
83
+ mailtext = parts.join('')
84
+ send_raw_email(from, password, to, mailtext)
85
+ end
86
+
87
+ end
@@ -0,0 +1,3 @@
1
+ module SendEmail
2
+ VERSION = "1.1.0"
3
+ end
data/lib/email.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'email/email'
2
+
3
+ module Email
4
+ end
@@ -0,0 +1,68 @@
1
+ require 'net/ssh'
2
+ require 'net/sftp'
3
+
4
+ require 'log'
5
+ require 'params'
6
+
7
+ module FileCopy
8
+
9
+ # Creates ssh connection, assumes username and password
10
+ # or without password but with ssh keys.
11
+ def ssh_connect(username, password, server)
12
+ username = (username and username.length > 0) ? username : ENV['USER']
13
+ password = (password and password.length > 0) ? password : nil
14
+ port = 22 # 22 is a standart SSH port
15
+ raise "Undefined server" unless server
16
+ Log.debug1 "Trying to connect(ssh): #{username}, #{password}, #{server}, #{port}."
17
+ if (username and password)
18
+ Net::SSH.start(server, username,
19
+ :password => password,
20
+ :port => port)
21
+ elsif (username)
22
+ Net::SSH.start(server, username,
23
+ :port => port)
24
+ else
25
+ raise "Undefined username"
26
+ end
27
+ end
28
+ module_function :ssh_connect
29
+
30
+ # Simply copy map files using sftp server on dest_server.
31
+ # Note: stfp.upload support parallel uploads - default is 2.
32
+ # TODO(kolman): packing files, all, not all, determine by part of file.
33
+ def sftp_copy(username, password, server, files_map)
34
+ ssh = FileCopy.ssh_connect(username, password, server)
35
+ ssh.sftp.connect do |sftp|
36
+ uploads = files_map.map { |from,to|
37
+ remote_dir = File.dirname(to)
38
+ sftp_mkdir_recursive(sftp, File.dirname(to))
39
+ Log.debug1 "Copying #{from} to #{to}"
40
+ sftp.upload(from, to)
41
+ }
42
+ uploads.each { |u| u.wait }
43
+ Log.debug1 "Done."
44
+ end # ssh.sftp.connect
45
+ end # def initialize
46
+ module_function :sftp_copy
47
+
48
+ def sftp_mkdir_recursive(sftp, path)
49
+ dir_stat = nil
50
+ begin
51
+ Log.debug1 "Stat remote dir: #{path}."
52
+ dir_stat = sftp.stat!(path).directory?
53
+ Log.debug1 "Stat result #{dir_stat}."
54
+ rescue Net::SFTP::StatusException
55
+ end
56
+ if !dir_stat
57
+ Log.debug1 "Directory does not exists: #{path}."
58
+ sftp_mkdir_recursive sftp, File.dirname(path)
59
+ Log.debug1 "Making dir #{path}."
60
+ response = sftp.mkdir!(path)
61
+ Log.debug1 "Making dir ok:#{response.ok?}."
62
+ end
63
+ end
64
+ module_function :sftp_mkdir_recursive
65
+
66
+ end
67
+
68
+
@@ -0,0 +1,4 @@
1
+ module FileCopy
2
+ VERSION = "1.1.0"
3
+ end
4
+
data/lib/file_copy.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'file_copy/copy'
2
+
3
+ module FileCopy
4
+ end
@@ -0,0 +1,170 @@
1
+ require 'digest/sha1'
2
+ require 'pp'
3
+ require 'set'
4
+ require 'time'
5
+
6
+ require 'content_data'
7
+ require 'file_indexing/indexer_patterns'
8
+ require 'log'
9
+
10
+
11
+ module FileIndexing
12
+ ####################
13
+ # Index Agent
14
+ ####################
15
+
16
+ class IndexAgent
17
+ attr_reader :indexed_content, :failed_files
18
+
19
+ # Why are those lines needed?
20
+ LOCALTZ = Time.now.zone
21
+ ENV['TZ'] = 'UTC'
22
+
23
+ def initialize
24
+ @indexed_content = ContentData::ContentData.new
25
+ @failed_files = Set.new
26
+ end
27
+
28
+ # Calculate file checksum (SHA1)
29
+ def self.get_checksum(filename)
30
+ digest = Digest::SHA1.new
31
+ begin
32
+ File.open(filename, 'rb') { |f|
33
+ while buffer = f.read(65536) do
34
+ digest << buffer
35
+ end
36
+ }
37
+ Log.debug1("#{filename} sha1 #{digest.hexdigest.downcase}")
38
+ digest.hexdigest.downcase
39
+ rescue Errno::EACCES, Errno::ETXTBSY => exp
40
+ Log.warning("#{exp.message}")
41
+ false
42
+ end
43
+ end
44
+
45
+ def IndexAgent.get_content_checksum(content)
46
+ # Calculate checksum.
47
+ digest = Digest::SHA1.new
48
+ digest << content
49
+ digest.hexdigest.downcase
50
+ end
51
+
52
+ # get all files
53
+ # satisfying the pattern
54
+ def collect(pattern)
55
+ Dir.glob(pattern.to_s)
56
+ end
57
+
58
+ # TODO(kolman): Replace this with File.lstat(file).mtime when new version of Ruby comes out.
59
+ # http://bugs.ruby-lang.org/issues/6385
60
+ def IndexAgent.get_correct_mtime(file)
61
+ begin
62
+ File.open(file, 'r') { |f| f.mtime }
63
+ rescue Errno::EACCES => e
64
+ Log.warning("Could not open file #{file} to get mtime. #{e}")
65
+ return 0
66
+ end
67
+ end
68
+
69
+ # index device according to the pattern
70
+ # store the result
71
+ # does not adds automatically otherDB to stored result
72
+ # TODO device support
73
+ def index(patterns, otherDB = nil)
74
+ abort "#{self.class}: DB not empty. Current implementation permits only one running of index" \
75
+ unless @indexed_content.empty?
76
+ local_server_name = `hostname`.strip
77
+ permit_patterns = []
78
+ forbid_patterns = []
79
+ otherDB_updated = ContentData::ContentData.new
80
+ #otherDB_table = Hash.new # contains instances from given DB while full path name is a key and instance is a value
81
+ #otherDB_contents = Hash.new # given DB contents
82
+
83
+ # if there is a given DB then populate table with files
84
+ # that was already indexed on this server/device
85
+ if !otherDB.nil?
86
+ otherDB.each_instance { |checksum, size, content_mod_time, instance_mod_time, server, path|
87
+ if (server == local_server_name)
88
+ # add instance
89
+ otherDB_updated.add_instance(checksum, size, server, path, instance_mod_time)
90
+ end
91
+ }
92
+ end
93
+
94
+ permit_patterns = patterns.positive_patterns
95
+ forbid_patterns = patterns.negative_patterns
96
+
97
+ # add files found by positive patterns
98
+ files = Array.new
99
+ permit_patterns.each_index do |i|
100
+ files = files | (collect(permit_patterns[i]));
101
+ end
102
+
103
+ Log.debug1 "Files: #{files}."
104
+
105
+ # expand to absolute pathes
106
+ files.map! {|f| File.expand_path(f)}
107
+
108
+ # remove files found by negative patterns
109
+ forbid_patterns.each_index do |i|
110
+ forbid_files = Array.new(collect(forbid_patterns[i]));
111
+ forbid_files.each do |f|
112
+ files.delete(File.expand_path(f))
113
+ end
114
+ end
115
+
116
+ # create and add contents and instances
117
+ files.each do |file|
118
+ file_stats = File.lstat(file)
119
+ file_mtime = IndexAgent.get_correct_mtime(file)
120
+ device = file_stats.dev.to_s
121
+
122
+ # index only files
123
+ next if file_stats.directory?
124
+
125
+ # add files present in the given DB to the DB and remove these files
126
+ # from further processing (save checksum calculation)
127
+ file_match = false
128
+ otherDB_updated.each_instance { |checksum, size, content_mod_time, instance_mod_time, server, path|
129
+ if otherDB_updated.instance_exists(file, local_server_name, checksum)
130
+ if size == file_stats.size and instance_mod_time == file_mtime.to_i
131
+ @indexed_content.add_instance(checksum, size, server, file, instance_mod_time)
132
+ file_match = true
133
+ break
134
+ else
135
+ Log.warning("File (#{file}) size or modification file is different. size=#{size} actual size=#{file_stats.size}" + \
136
+ " instance_mod_time=#{Time.at(instance_mod_time)} actual=#{file_mtime}")
137
+ end
138
+ end
139
+ }
140
+ next if file_match
141
+ # calculate a checksum
142
+ unless (checksum = self.class.get_checksum(file))
143
+ Log.warning("Cheksum failure: " + file)
144
+ @failed_files.add(file)
145
+ next
146
+ end
147
+
148
+ @indexed_content.add_instance(checksum, file_stats.size, local_server_name,
149
+ File.expand_path(file), file_mtime.to_i)
150
+ end
151
+ end
152
+
153
+ def IndexAgent.create_shallow_instance(filename)
154
+ return nil unless File.exists?(filename)
155
+ file_stats = File.lstat(filename)
156
+ file_mtime = IndexAgent.get_correct_mtime(filename)
157
+ # return instance shallow representation (no server)
158
+ [file_stats.size,
159
+ "%s,%s,%s" % [`hostname`.strip , file_stats.dev.to_s , File.expand_path(filename)],
160
+ file_mtime.to_i]
161
+ end
162
+
163
+ def IndexAgent.global_path(filename)
164
+ server_name = `hostname`.strip
165
+ file_stats = File.lstat(filename)
166
+ return "%s,%s,%s" % [server_name, file_stats.dev.to_s,filename]
167
+ end
168
+ end
169
+ end
170
+
@@ -0,0 +1,72 @@
1
+ require 'log'
2
+ require 'params'
3
+
4
+ module FileIndexing
5
+
6
+ class IndexerPatterns
7
+ attr_reader :positive_patterns, :negative_patterns
8
+
9
+ # @param indexer_patterns_str [String]
10
+ def initialize (indexer_patterns = nil)
11
+ Log.debug1 "Initialize index patterns #{indexer_patterns}."
12
+ @positive_patterns = Array.new
13
+ @negative_patterns = Array.new
14
+ # TODO add a test (including empty collections)
15
+ if indexer_patterns
16
+ indexer_patterns.positive_patterns.each do |pattern|
17
+ add_pattern(pattern)
18
+ end
19
+ indexer_patterns.negative_patterns.each do |pattern|
20
+ add_pattern(pattern, false)
21
+ end
22
+ end
23
+ end
24
+
25
+ def serialize
26
+ # TODO add a test (including empty collections)
27
+ indexer_patterns = IndexerPatternsMessage.new
28
+ positive_patterns.each do |pattern|
29
+ indexer_patterns.positive_patterns << pattern
30
+ end
31
+ negative_patterns.each do |pattern|
32
+ indexer_patterns.negative_patterns << pattern
33
+ end
34
+ indexer_patterns
35
+ end
36
+
37
+ # @param pattern [String]
38
+ # @param is_positive [true]
39
+ # @param is_positive [false]
40
+ def add_pattern(pattern, is_positive = true)
41
+ pattern.gsub!(/\\/,'/')
42
+ if (is_positive)
43
+ @positive_patterns << pattern
44
+ else
45
+ @negative_patterns << pattern
46
+ end
47
+ end
48
+
49
+ def parse_from_file(file)
50
+ input_patterns = IO.readlines(file)
51
+ begin
52
+ Log.debug1 "Error loading patterns=%s" % file
53
+ raise IOError("Error loading patterns=%s" % file)
54
+ end unless not input_patterns.nil?
55
+
56
+ input_patterns.each do |pattern|
57
+ if (m = /^\s*([+-]):(.*)/.match(pattern))
58
+ add_pattern(m[2], m[1].eql?('+') ? true : false)
59
+ elsif (not /^\s*[\/\/|#]/.match(pattern)) # not a comment
60
+ Log.debug1 "pattern in incorrect format: #{pattern}"
61
+ raise RuntimeError("pattern in incorrect format: #{pattern}")
62
+ end
63
+ end
64
+ end
65
+
66
+ def size
67
+ return @positive_patterns.size
68
+ end
69
+ end
70
+
71
+ end
72
+
@@ -0,0 +1,3 @@
1
+ module FileIndexing
2
+ VERSION = "1.1.0"
3
+ end
@@ -0,0 +1,9 @@
1
+ require 'content_data'
2
+
3
+ require 'file_indexing/index_agent'
4
+ require 'file_indexing/indexer_patterns'
5
+
6
+ # Data structure for an abstract layer over files.
7
+ # Each binary sequence is a content, each file is content instance.
8
+ module FileIndexing
9
+ end
@@ -0,0 +1,105 @@
1
+ require 'algorithms'
2
+ require 'fileutils'
3
+ require 'log4r'
4
+ require 'params'
5
+ require 'content_server/server'
6
+ require 'file_monitoring/monitor_path'
7
+
8
+ module FileMonitoring
9
+ # Manages file monitoring of number of file system locations
10
+ class FileMonitoring
11
+
12
+ def initialize ()
13
+ @content_data_cache = Set.new
14
+ $local_content_data_lock.synchronize {
15
+ $local_content_data.each_instance(){
16
+ |_, _, _, _, _, file_path|
17
+ # save files to cache
18
+ Log.info("File in cache: #{file_path.clone}")
19
+ @content_data_cache.add(file_path.clone)
20
+ }
21
+ }
22
+ end
23
+
24
+
25
+ # Set event queue used for communication between different proceses.
26
+ # @param queue [Queue]
27
+ def set_event_queue(queue)
28
+ @event_queue = queue
29
+ end
30
+
31
+ # The main method. Loops on all paths, each time span and monitors them.
32
+ #
33
+ # =Algorithm:
34
+ # There is a loop that performs at every iteration:
35
+ # 1.Pull entry with a minimal time of check from queue
36
+ # 2.Recursively check path taken from entry for changes
37
+ # a.Notify subscribed processes on changes
38
+ # 3.Push entry to the queue with new time of next check
39
+ #
40
+ # This methods controlled by <tt>monitoring_paths</tt> configuration parameter,
41
+ # that provides path and file monitoring configuration data
42
+ def monitor_files
43
+ conf_array = Params['monitoring_paths']
44
+ # Directories states stored in the priority queue,
45
+ # where the key (priority) is a time when it should be checked next time.
46
+ # Priority queue means that all entries arranged by key (time to check) in increasing order.
47
+ pq = Containers::PriorityQueue.new
48
+ conf_array.each { |elem|
49
+ priority = (Time.now + elem['scan_period']).to_i
50
+ dir_stat = DirStat.new(File.expand_path(elem['path']), elem['stable_state'], @content_data_cache, FileStatEnum::NON_EXISTING)
51
+ dir_stat.set_event_queue(@event_queue) if @event_queue
52
+ Log.debug1("File monitoring started for: #{elem}")
53
+ pq.push([priority, elem, dir_stat], -priority)
54
+ }
55
+
56
+ #init log4r
57
+ monitoring_log_path = Params['default_monitoring_log_path']
58
+ Log.debug1 'File monitoring log: ' + Params['default_monitoring_log_path']
59
+ monitoring_log_dir = File.dirname(monitoring_log_path)
60
+ FileUtils.mkdir_p(monitoring_log_dir) unless File.exists?(monitoring_log_dir)
61
+
62
+ @log4r = Log4r::Logger.new 'BBFS monitoring log'
63
+ @log4r.trace = true
64
+ formatter = Log4r::PatternFormatter.new(:pattern => "[%d] [%m]")
65
+ #file setup
66
+ file_config = {
67
+ "filename" => Params['default_monitoring_log_path'],
68
+ "maxsize" => Params['log_rotation_size'],
69
+ "trunc" => true
70
+ }
71
+ file_outputter = Log4r::RollingFileOutputter.new("monitor_log", file_config)
72
+ file_outputter.level = Log4r::INFO
73
+ file_outputter.formatter = formatter
74
+ @log4r.outputters << file_outputter
75
+ FileStat.set_log(@log4r)
76
+
77
+ while true do
78
+ # pull entry that should be checked next,
79
+ # according to it's scan_period
80
+ time, conf, dir_stat = pq.pop
81
+ # time remains to wait before directory should be checked
82
+ time_span = time - Time.now.to_i
83
+ if (time_span > 0)
84
+ sleep(time_span)
85
+ end
86
+
87
+ unless $testing_memory_active
88
+ dir_stat.monitor
89
+ else
90
+ $testing_memory_log.info("Start monitor at :#{Time.now}")
91
+ puts "Start monitor at :#{Time.now}"
92
+ dir_stat.monitor
93
+ $testing_memory_log.info("End monitor at :#{Time.now}")
94
+ puts "End monitor at :#{Time.now}"
95
+ end
96
+
97
+ # push entry with new a next time it should be checked as a priority key
98
+ priority = (Time.now + conf['scan_period']).to_i
99
+ pq.push([priority, conf, dir_stat], -priority)
100
+ end
101
+ end
102
+ end
103
+
104
+ end
105
+