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,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
+