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,236 @@
1
+ #require 'net/sftp'
2
+ #require 'net/ssh'
3
+ require 'log4r'
4
+ require 'log'
5
+ require 'params'
6
+ require 'content_server'
7
+ require 'content_server/content_server' # specific content server impl
8
+ require 'content_server/backup_server' # specific backup server impl
9
+ require 'content_data'
10
+ require 'email'
11
+ require 'file_utils/file_generator/file_generator'
12
+ require 'validations'
13
+
14
+ # Testing server. Assumes that content and backup servers are running.
15
+ # The server runs 24-7, generates/deletes files and validates content at backup periodically.
16
+ module TestingServer
17
+ # TODO get latest ContentData object directly from Content/BackupServer
18
+ # Then need changes in Content/BackupServers API
19
+ # TODO split to Backup/ContentTestingServers separate classes ?
20
+ # TODO split long methods
21
+ # TODO Tests
22
+ # TODO No default config taken by Params
23
+ # TODO Additional testing scenarios (remove/rename/change)
24
+
25
+ # Messages types
26
+ :GET_INDEX # get index from remote master
27
+ :PUT_INDEX # message contains requested index from master
28
+ # TODO in thus implementation validation called automatically on master side
29
+ # with receiving GET_INDEX message
30
+ # More flexible will be separating it to two separate operations:
31
+ # GET_INDEX and VALIDATE
32
+ #:VALIDATE # validate index on master
33
+ :PUT_VALIDATION # message contains validation result from master
34
+
35
+ Params.path('testing_log_path', nil, 'Testing server log path.')
36
+
37
+ # init process vars
38
+ $objects_counters = {}
39
+ $objects_counters["Time"] = Time.now.to_i
40
+
41
+ def init_log4r
42
+ #init log4r
43
+ log_path = Params['testing_log_path']
44
+ unless log_path
45
+ raise("pls specify testing log path through param:'testing_log_path'")
46
+ end
47
+ log_dir = File.dirname(log_path)
48
+ FileUtils.mkdir_p(log_dir) unless File.exists?(log_dir)
49
+
50
+ $log4r = Log4r::Logger.new 'BBFS testing server log'
51
+ $log4r.trace = true
52
+ formatter = Log4r::PatternFormatter.new(:pattern => "[%d] [%m]")
53
+ #file setup
54
+ file_config = {
55
+ "filename" => Params['testing_log_path'],
56
+ "maxsize" => Params['log_rotation_size'],
57
+ "trunc" => true
58
+ }
59
+ file_outputter = Log4r::RollingFileOutputter.new("testing_log", file_config)
60
+ file_outputter.level = Log4r::INFO
61
+ file_outputter.formatter = formatter
62
+ $log4r.outputters << file_outputter
63
+ end
64
+
65
+ def run_content_testing_server
66
+ Log.info('Testing server started')
67
+ init_log4r
68
+ $log4r.info 'Testing server started'
69
+ all_threads = [];
70
+ messages = Queue.new
71
+
72
+ all_threads << Thread.new do
73
+ ContentServer.run_content_server
74
+ end
75
+
76
+ all_threads << Thread.new do
77
+ fg = FileGenerator::FileGenerator.new
78
+ fg.run
79
+ end
80
+
81
+ receive_msg_proc = lambda do |addr_info, message|
82
+ $log4r.info("message received: #{message}")
83
+ messages.push(message)
84
+ end
85
+ tcp = Networking::TCPServer.new(Params['testing_server_port'], receive_msg_proc)
86
+
87
+ all_threads << tcp.tcp_thread
88
+
89
+ while(true) do
90
+ msg_type, validation_timestamp = messages.pop
91
+ if msg_type == :GET_INDEX
92
+ cur_index = ContentData::ContentData.new
93
+ cur_index.from_file(Params['local_content_data_path'])
94
+ tcp.send_obj([:PUT_INDEX, validation_timestamp, cur_index])
95
+ $log4r.info "PUT_INDEX sent with timestamp #{validation_timestamp}"
96
+ is_index_ok = cur_index.validate
97
+ tcp.send_obj([:PUT_VALIDATION, validation_timestamp, is_index_ok])
98
+ $log4r.info "PUT_VALIDATION sent with timestamp #{validation_timestamp}"
99
+ end
100
+ end
101
+ end
102
+ module_function :run_content_testing_server
103
+
104
+ def run_backup_testing_server
105
+ Log.info('Testing server started')
106
+ init_log4r
107
+ $log4r.info 'Testing server started'
108
+ all_threads = [];
109
+ messages = Queue.new
110
+ # used for synchronization between servers
111
+ validation_timestamp = Time.now.to_i
112
+ # holds boolean whether all contents according to this timestamp that should be backed are backed and OK
113
+ is_cur_synch_ok = nil
114
+ # holds boolean whether all already backuped files are OK
115
+ is_backup_ok = nil
116
+ # holds boolean whether master is valid. receive from master
117
+ is_master_ok = nil
118
+ # number of contents must be backuped this synch
119
+ # with current scenarios this number expected to grow
120
+ # used to check that file_generator is actually running
121
+ numb_backuped_contents = 0
122
+
123
+ all_threads << Thread.new do
124
+ ContentServer.run_backup_server
125
+ end
126
+
127
+ receive_msg_proc = lambda do |message|
128
+ $log4r.info("message received: #{message}")
129
+ messages.push(message)
130
+ end
131
+ tcp = Networking::TCPClient.new(Params['content_server_hostname'],
132
+ Params['testing_server_port'], receive_msg_proc)
133
+ all_threads << tcp.tcp_thread
134
+
135
+ # used to request index from master per validation interval of time
136
+ all_threads << Thread.new do
137
+ while(true) do
138
+ sleep Params['validation_interval']
139
+ validation_timestamp = Time.now.to_i
140
+ tcp.send_obj([:GET_INDEX, validation_timestamp])
141
+ $log4r.info "GET_INDEX sent with timestamp #{validation_timestamp}"
142
+ end
143
+ end
144
+
145
+ # gets messages from master via queue
146
+ # handles them according to type
147
+ while(true) do
148
+ msg_type, response_validation_timestamp, msg_body = messages.pop
149
+ $log4r.info "#{msg_type} : #{validation_timestamp} : #{msg_body.class}"
150
+ unless (validation_timestamp == response_validation_timestamp)
151
+ # TODO problem of servers synch. What should be done here?
152
+ $log4r.warning "Timestamps differs: requested #{validation_timestamp} : received #{response_validation_timestamp}"
153
+ end
154
+
155
+ case msg_type
156
+ when :PUT_INDEX
157
+ # index of already backuped contents
158
+ backuped_index = ContentData::ContentData.new
159
+ backuped_index.from_file Params['local_content_data_path']
160
+ # index contains only master current contents
161
+ # that must be backuped according to backup_time_requirement parameter
162
+ index_must_be_backuped = ContentData::ContentData.new(msg_body)
163
+ # we backup contents, so content mtime used to determine contents should be validated
164
+ index_must_be_backuped.each_content do |checksum, size, mtime|
165
+ if (validation_timestamp - mtime < Params['backup_time_requirement'])
166
+ index_must_be_backuped.remove_content checksum
167
+ end
168
+ end
169
+ is_cur_synch_ok =
170
+ Validations::IndexValidations.validate_remote_index index_must_be_backuped, backuped_index
171
+ is_backup_ok = backuped_index.validate
172
+ numb_backuped_contents = index_must_be_backuped.contents_size
173
+ when :PUT_VALIDATION
174
+ is_master_ok = msg_body
175
+ else
176
+ $log4r.error "Incorrect message received: #{msg_type}"
177
+ end
178
+
179
+ unless (is_master_ok.nil? || is_cur_synch_ok.nil? || is_backup_ok.nil?)
180
+ send_email is_master_ok, is_cur_synch_ok, is_backup_ok, numb_backuped_contents
181
+ is_master_ok = nil
182
+ is_cur_synch_ok = nil
183
+ is_backup_ok = nil
184
+ numb_backuped_contents = 0
185
+ end
186
+ end
187
+ end
188
+
189
+
190
+ def generate_mem_report
191
+ # Generate memory report
192
+ current_objects_counters = {}
193
+ time = Time.now
194
+ current_objects_counters['Time'] = time.to_i
195
+ count = ObjectSpace.each_object(String).count
196
+ current_objects_counters['String'] = count
197
+ count = ObjectSpace.each_object(ContentData::ContentData).count
198
+ current_objects_counters['ContentData'] = count
199
+ dir_count = ObjectSpace.each_object(FileMonitoring::DirStat).count
200
+ current_objects_counters['DirStat'] = dir_count
201
+ file_count = ObjectSpace.each_object(FileMonitoring::FileStat).count
202
+ current_objects_counters['FileStat'] = file_count-dir_count
203
+
204
+ # Generate report and update global counters
205
+ report = ""
206
+ current_objects_counters.each_key { |type|
207
+ $objects_counters[type] = 0 unless $objects_counters[type]
208
+ diff = current_objects_counters[type] - $objects_counters[type]
209
+ report += "Type:#{type} raised in:#{diff} \n"
210
+ $objects_counters[type] = current_objects_counters[type]
211
+ }
212
+ final_report = "Memory report at Time:#{time}:\n#{report}\n"
213
+ $log4r.info(final_report)
214
+ final_report
215
+ end
216
+ def send_email(is_master_ok, is_cur_synch_ok, is_backup_ok, numb_backuped_contents)
217
+
218
+ msg =<<EOF
219
+ Master index ok: #{is_master_ok}
220
+ Backup index ok: #{is_backup_ok}
221
+ Backup includes all master files upto -#{Params['backup_time_requirement']} sec: #{is_cur_synch_ok}
222
+ Number of contents must be back-up: #{numb_backuped_contents}
223
+ #{generate_mem_report}
224
+ EOF
225
+ Email.send_email(Params['from_email'],
226
+ Params['from_email_password'],
227
+ Params['to_email'],
228
+ 'Testing server update',
229
+ msg)
230
+ end
231
+
232
+ module_function :send_email, :run_backup_testing_server, :init_log4r, :generate_mem_report
233
+
234
+ end # module TestingServer
235
+
236
+
@@ -0,0 +1,3 @@
1
+ module TestingServer
2
+ VERSION = "1.1.0"
3
+ end
@@ -0,0 +1,12 @@
1
+ require 'testing_server/testing_server'
2
+
3
+ module TestingServer
4
+ Params.integer('testing_server_port', 4445, 'Remote port to synchronization between testing servers')
5
+ #Params.integer('email_delay_in_seconds', 60*60*6, 'Number of seconds before sending email again.')
6
+ Params.integer('validation_interval', 60*60*6, 'Number of seconds between validations')
7
+ Params.integer('backup_time_requirement', 60*60,
8
+ 'Max diff in seconds between timestamps of file indexation on master ' +
9
+ 'and its content indexation on backup.' +
10
+ ' NOTE Machines must have time synchronization.' +
11
+ ' NOTE This requirement must be set sufficient, i.e. enough to finish copy file process')
12
+ end # module TestingServer
@@ -0,0 +1,106 @@
1
+ require 'params'
2
+ require 'log'
3
+ require 'content_data'
4
+ require 'file_indexing/index_agent'
5
+
6
+ # TODO additional params?
7
+ # TODO are params names good enough?
8
+ module Validations
9
+ class IndexValidations
10
+
11
+ # TODO should it be renamed cause it can validate any indexes, not specially remote, one against another.
12
+
13
+ # Validates remote index against local file system.
14
+ # Remote index defined valid when every remote content has at least one valid local instance.
15
+ #
16
+ # There are two levels of validation, controlled by instance_check_level system parameter:
17
+ # * shallow - quick, tests instance for file existence and attributes.
18
+ # * deep - can take more time, in addition to shallow recalculates hash sum.
19
+ # For more infoemation see <tt>ContentData</tt> documentation.
20
+ # @param [ContentData] remote_index it's contents should be validate against local index
21
+ # @param [ContentData] local_index contains local contents and instances used for validation
22
+ # @param [Hash] params hash of parameters of validation, can be used to return additional data
23
+ #
24
+ # Supported key/value combinations:
25
+ # * key is <tt>:failed</tt> value is <tt>ContentData</tt> used to return failed instances
26
+ # @return [Boolean] true when every remote content has at least one valid local instance, false otherwise
27
+ # @raise [ArgumentError] when instance_check_level is incorrect
28
+ def IndexValidations.validate_remote_index(remote_index, local_index, params = nil)
29
+ raise ArgumentError 'remote_index must be defined' if remote_index.nil?
30
+ raise ArgumentError 'local index must be defined' if local_index.nil?
31
+
32
+ # used to answer whether specific param was set
33
+ param_exists = Proc.new do |param|
34
+ !(params.nil? || params[param].nil?)
35
+ end
36
+
37
+ # used to process method parameters centrally
38
+ # TODO consider more convenient form of parameters
39
+ # TODO code duplication with ContentData::validate
40
+ process_params = Proc.new do |checksum, content_mtime, size, instance_mtime, server, path|
41
+ if param_exists.call(:failed)
42
+ params[:failed].add_instance(checksum, size, server, path, instance_mtime)
43
+ end
44
+ end
45
+
46
+ # result variable
47
+ is_valid = true
48
+ # contains contents absent or without valid instances on local system
49
+ # and corresponding local instances
50
+ failed = ContentData::ContentData.new
51
+ # contains checksums of contains absent in local
52
+ absent_checksums = Array.new
53
+
54
+ # contains local instances corresponding to given remote index contents
55
+ local_index_to_check = ContentData::ContentData.new
56
+
57
+ # check whether remote contents exist locally
58
+ remote_index.each_content do |checksum|
59
+ unless local_index.content_exists checksum
60
+ is_valid = false
61
+ absent_checksums << checksum
62
+ end
63
+ end
64
+
65
+ # add instances of contents that should be check, i.e. exist in local
66
+ local_index.each_instance do |checksum, size, content_mtime, instance_mtime, server, path|
67
+ if remote_index.content_exists checksum
68
+ local_index_to_check.add_instance checksum, size, server, path, instance_mtime
69
+ end
70
+ end
71
+
72
+
73
+ # validate against local file system
74
+ is_valid = local_index_to_check.validate(:failed => failed) && is_valid
75
+
76
+ # contains contents that have at least one valid local instance,
77
+ # then also corresponding remote content defined valid
78
+ contents_with_succeeded_instances = ContentData.remove_instances failed, local_index
79
+
80
+ # write summary to log
81
+ # TODO should be controlled from params?
82
+ absent_checksums.each do |checksum|
83
+ Log.warning "Content #{checksum} is absent in the local file system"
84
+ end
85
+ failed.each_content do |checksum|
86
+ if !contents_with_succeeded_instances.content_exists checksum
87
+ # if checked content have no valid local instances
88
+ # then content defined invalid
89
+ Log.warning "Content #{checksum} is invalid in the local file system"
90
+ end
91
+ end
92
+
93
+ # if needed process output params
94
+ unless params.nil? || params.empty?
95
+ remote_index.each_instance do |checksum, size, content_mtime, instance_mtime, server, path|
96
+ unless contents_with_succeeded_instances.content_exists checksum
97
+ process_params.call checksum, content_mtime, size, instance_mtime, server, path
98
+ end
99
+ end
100
+ end
101
+
102
+ is_valid
103
+ end
104
+
105
+ end # class IndexValidations
106
+ end # module Validations
@@ -0,0 +1,3 @@
1
+ module Validations
2
+ VERSION = "1.1.0"
3
+ end
@@ -0,0 +1,4 @@
1
+ require 'validations/index_validations'
2
+
3
+ module Validations
4
+ end
@@ -0,0 +1,113 @@
1
+ require 'rspec'
2
+ require 'file_indexing/index_agent'
3
+ require 'params'
4
+ require_relative '../../lib/content_data.rb'
5
+
6
+ module ContentData
7
+ module Spec
8
+ describe 'Index validation' do
9
+ before :all do
10
+ @size = 100
11
+ @path = '/dir1/dir2/file'
12
+ @path2 = '/dir3/dir4/file'
13
+ @mod_time = 123456
14
+ @checksum = 'abcde987654321'
15
+ @checksum2 = '987654321abcde'
16
+ @server = 'server_1'
17
+ end
18
+
19
+ before :each do
20
+ @index = ContentData.new
21
+ @index.add_instance @checksum, @size, @server, @path, @mod_time
22
+ @index.add_instance @checksum2, @size, @server, @path2, @mod_time
23
+ end
24
+
25
+ context 'with shallow check' do
26
+ before :all do
27
+ Params['instance_check_level'] = 'shallow'
28
+ end
29
+
30
+ before :each do
31
+ File.stub(:exists?).and_return(true)
32
+ File.stub(:size).and_return(@size)
33
+ File.stub(:mtime).and_return(@mod_time)
34
+ end
35
+
36
+ it 'succeeds when files exist and their attributes the same as in the index' do
37
+ @index.validate().should be_true
38
+ end
39
+
40
+ it 'fails when there is a file that doesn\'t exist' do
41
+ File.stub(:exists?).with(@path).and_return(false)
42
+ @index.validate().should be_false
43
+ end
44
+
45
+ it 'fails when there is a file with size different from indexed' do
46
+ File.stub(:size).with(@path).and_return(@size + 10)
47
+ @index.validate().should be_false
48
+ end
49
+
50
+ it 'fails when there is a file with modification time different from indexed' do
51
+ modified_mtime = @mod_time + 10
52
+ File.stub(:mtime).with(@path).and_return(modified_mtime)
53
+ @index.validate().should be_false
54
+ end
55
+ end
56
+
57
+ context 'with deep check (shallow check assumed succeeded)' do
58
+ before :all do
59
+ Params['instance_check_level'] = 'deep'
60
+ end
61
+
62
+ before :each do
63
+ FileIndexing::IndexAgent.stub(:get_checksum).with(@path).and_return(@checksum)
64
+ FileIndexing::IndexAgent.stub(:get_checksum).with(@path2).and_return(@checksum2)
65
+ @index.stub(:shallow_check).and_return(true)
66
+ end
67
+
68
+ it 'succeeds when for all files checksums are the same as indexed' do
69
+ @index.validate().should be_true
70
+ end
71
+
72
+ it 'fails when there is a file with checksum different from indexed' do
73
+ FileIndexing::IndexAgent.stub(:get_checksum).with(@path2).and_return(@checksum2 + 'a')
74
+ @index.validate().should be_false
75
+ end
76
+ end
77
+
78
+ context 'validation params' do
79
+ before :all do
80
+ Params['instance_check_level'] = 'shallow'
81
+ end
82
+
83
+ before :each do
84
+ File.stub(:exists?).and_return(true)
85
+ File.stub(:size).and_return(@size)
86
+ File.stub(:mtime).and_return(@mod_time)
87
+ end
88
+
89
+ it ':failed param returns index of absent or invalid instances' do
90
+ # one instance that absent,
91
+ absent_checksum = '123'
92
+ absent_path = @path2 + '1'
93
+ @index.add_instance absent_checksum, @size, @server, absent_path, @mod_time
94
+ File.stub(:exists?).with(absent_path).and_return(false)
95
+
96
+ # another instance with different content was changed
97
+ File.stub(:mtime).with(@path2).and_return(@mod_time + 10)
98
+
99
+ failed = ContentData.new
100
+ @index.validate(:failed => failed).should be_false
101
+ # should be two failed contents, with one instance per content
102
+ failed.contents_size.should eq(2)
103
+ failed.content_exists(absent_checksum).should be_true
104
+ failed.content_exists(@checksum2).should be_true
105
+ failed.checksum_instances_size(absent_checksum).should eq(1)
106
+ failed.checksum_instances_size(@checksum2).should eq(1)
107
+ failed.instance_exists(absent_path, @server, absent_checksum).should be_true
108
+ failed.instance_exists(@path2, @server, @checksum2).should be_true
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,54 @@
1
+ require 'rspec'
2
+
3
+ require_relative '../../lib/file_copy/copy.rb'
4
+
5
+ module FileCopy
6
+ module Spec
7
+
8
+ describe 'FileCopy::ssh_connect' do
9
+ it 'should raise error when username not specified' do
10
+ ENV.stub(:[]).with(any_args()).and_return(nil)
11
+ expect { FileCopy::ssh_connect(nil, nil, 'a server') }.to raise_error "Undefined username"
12
+ end
13
+
14
+ it 'should raise error when server not specified' do
15
+ expect { FileCopy::ssh_connect('kuku', nil, nil) }.to raise_error "Undefined server"
16
+ end
17
+
18
+ it 'should try to connect if username is set explicitly' do
19
+ Net::SSH.should_receive(:start).with(any_args())
20
+ FileCopy::ssh_connect('kuku', nil, 'a server')
21
+ end
22
+ it 'should try to connect if username is set via ENV variable' do
23
+ Net::SSH.should_receive(:start).with(any_args())
24
+ ENV.stub(:[]).with("USER").and_return('kuku')
25
+ FileCopy::ssh_connect(nil, nil, 'a server')
26
+ end
27
+ end
28
+
29
+ # TODO(kolman): Bad test, should rewrite and understand how to write test correctly.
30
+ describe 'FileCopy::sftp_copy' do
31
+ it 'call upload with correct files' do
32
+ ssh_connection = double('Net::SSH::Connection')
33
+ sftp_session = double('Net::SFTP::Session')
34
+ uploader = double('Operations::Upload')
35
+ sftp_attributes = double('Attributes')
36
+
37
+ # Stubbing sftp.
38
+ FileCopy.stub(:ssh_connect).and_return(ssh_connection)
39
+ ssh_connection.stub(:sftp).and_return(sftp_session)
40
+ sftp_session.stub(:connect).and_yield(sftp_session)
41
+ sftp_session.stub(:stat!).and_return(sftp_attributes)
42
+ sftp_attributes.stub(:directory?).and_return(true)
43
+ uploader.stub(:wait).and_return(true, true)
44
+
45
+ # Test file uploaded
46
+ sftp_session.should_receive(:upload).with('a', 'b').and_return(uploader)
47
+ sftp_session.should_receive(:upload).with('c', 'd').and_return(uploader)
48
+ FileCopy::sftp_copy(nil, nil, nil, { 'a' => 'b', 'c' => 'd' })
49
+ end
50
+ end
51
+
52
+ end
53
+ end
54
+
@@ -0,0 +1,53 @@
1
+ require 'rspec'
2
+ require 'tempfile'
3
+
4
+ require_relative '../../lib/file_indexing/index_agent.rb'
5
+
6
+ module FileCopy
7
+ module Spec
8
+
9
+ describe 'checksum' do
10
+ it 'should generate correct checksum' do
11
+ # The test does not checks the problem the problem is when reading from File
12
+ # class which handles read(num) different from read()
13
+ content = ''
14
+ 100000.times { content << 'abagadavazahatikalamansapazkareshet' }
15
+ content_checksum = FileIndexing::IndexAgent.get_content_checksum(content)
16
+
17
+ stream = StringIO.new(content)
18
+ File.stub(:open).and_yield(stream)
19
+ file_checksum = FileIndexing::IndexAgent.get_checksum('kuku')
20
+
21
+ content_checksum.should == file_checksum
22
+ content_checksum.should == '381e99eb0e2dfcaf45c9a367a04a4197ef3039a6'
23
+ end
24
+
25
+ it 'should generate correct checksum for temp file' do
26
+ # A hack to get tmp file name
27
+ tmp_file = Tempfile.new('foo')
28
+ path = tmp_file .path
29
+ tmp_file .close()
30
+
31
+ # Open file in binary mode.
32
+ file = File.open(path, 'wb')
33
+ 100000.times { file.write('abagadavazahatikalamansapazkareshet') }
34
+ file.close()
35
+
36
+ file_checksum = FileIndexing::IndexAgent.get_checksum(path)
37
+ file_checksum.should == '381e99eb0e2dfcaf45c9a367a04a4197ef3039a6'
38
+
39
+ File.open(path, 'rb') { |f|
40
+ content = f.read()
41
+ content_checksum = FileIndexing::IndexAgent.get_content_checksum(content)
42
+ content_checksum.should == '381e99eb0e2dfcaf45c9a367a04a4197ef3039a6'
43
+ file_checksum.should == content_checksum
44
+ }
45
+
46
+ # Delete tmp file.
47
+ tmp_file.unlink
48
+ end
49
+
50
+ end
51
+ end
52
+ end
53
+
@@ -0,0 +1,95 @@
1
+ require 'log'
2
+ require 'rspec'
3
+ require 'socket'
4
+ require 'stringio'
5
+
6
+ require_relative '../../lib/networking/tcp'
7
+
8
+ # Uncomment to debug spec.
9
+ Params['log_write_to_console'] = true
10
+ Params['log_debug_level'] = 0
11
+ Log.init
12
+
13
+ module Networking
14
+ module Spec
15
+
16
+ describe 'TCPClient' do
17
+ it 'should warn when destination host+port are bad' do
18
+ data = 'kuku!!!'
19
+ stream = StringIO.new
20
+ stream.close()
21
+ ::TCPSocket.stub(:new).and_return(stream)
22
+ Log.should_receive(:warning).with('Socket not opened for writing, skipping send.')
23
+
24
+ # Send data first.
25
+ tcp_client = TCPClient.new('kuku', 5555)
26
+ # Send has to fail.
27
+ tcp_client.send_obj(data).should be(false)
28
+ end
29
+
30
+ it 'should send data and server should receive callback function' do
31
+ info = 'info'
32
+ data = 'kuku!!!'
33
+ stream = StringIO.new
34
+ ::Socket.stub(:tcp_server_loop).and_yield(stream, info)
35
+ ::TCPSocket.stub(:new).and_return(stream)
36
+
37
+ # Send data first.
38
+ tcp_client = TCPClient.new('kuku', 5555)
39
+ # Send has to be successful.
40
+ tcp_client.send_obj(data).should be(21)
41
+
42
+ # Note this is very important so that reading the stream from beginning.
43
+ stream.rewind
44
+
45
+ func = lambda { |info, data| Log.info("info, data: #{info}, #{data}") }
46
+ # Check data is received.
47
+ func.should_receive(:call).with(info, data)
48
+
49
+ tcp_server = TCPServer.new(5555, func)
50
+ # Wait on server thread.
51
+ tcp_server.tcp_thread.join
52
+ end
53
+
54
+ # TODO(kolman): Don't work, missing client send_obj/open_socket execution in
55
+ # the correct place.
56
+ it 'should connect and receive callback from server' do
57
+ info = 'info'
58
+ data = 'kuku!!!'
59
+ stream = StringIO.new
60
+ ::Socket.stub(:tcp_server_loop).once.and_yield(stream, info)
61
+ ::TCPSocket.stub(:new).and_return(stream)
62
+
63
+ tcp_server = nil
64
+ new_clb = lambda { |i|
65
+ Log.info("#2 - After after @sockets is filled. Send has to be successful.")
66
+ tcp_server.send_obj(data).should eq({info => 21})
67
+
68
+ stream.rewind
69
+
70
+ func = lambda { |d|
71
+ Log.info("#6, After client initialized, it should send object.")
72
+ Log.info("data: #{d}")
73
+ # Validate received data.
74
+ d.should eq(data)
75
+ # Exit tcp client reading loop thread.
76
+ Thread.exit
77
+ }
78
+
79
+ Log.info("#4 - Create client and wait for read data.")
80
+ tcp_client = TCPClient.new('kuku', 5555, func)
81
+ tcp_client.tcp_thread.abort_on_exception = true
82
+ tcp_client.tcp_thread.join()
83
+ # We can finish now. Exit tcp server listening loop.
84
+ Thread.exit
85
+ }
86
+
87
+ Log.info("#1 - Create server, send data and wait.")
88
+ tcp_server = TCPServer.new(5555, nil, new_clb)
89
+ tcp_server.tcp_thread.abort_on_exception = true
90
+ tcp_server.tcp_thread.join()
91
+ end
92
+ end
93
+ end
94
+ end
95
+