content_server 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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
+