content_server 1.0.3 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/backup_server +11 -0
- data/bin/content_server +11 -0
- data/lib/content_server.rb +1 -2
- data/lib/content_server/backup_server.rb +75 -91
- data/lib/content_server/content_server.rb +66 -76
- data/lib/content_server/file_streamer.rb +29 -8
- data/lib/content_server/globals.rb +10 -0
- data/lib/content_server/queue_copy.rb +32 -36
- data/lib/content_server/queue_indexer.rb +50 -71
- data/lib/content_server/remote_content.rb +0 -1
- data/lib/content_server/version.rb +1 -1
- metadata +35 -34
data/bin/backup_server
CHANGED
@@ -25,12 +25,23 @@ rescue SystemExit, SignalException => exc
|
|
25
25
|
# TODO (genadyp) do we need to trap signals by types?
|
26
26
|
puts("Interrupt or Exit happened in #{Params['service_name']} server: #{exc.class}, " +
|
27
27
|
"stopping process.\nBacktrace:\n#{exc.backtrace.join("\n")}")
|
28
|
+
puts("Force writing local content data to #{Params['local_content_data_path']}.")
|
29
|
+
ContentServer::local_dynamic_content_data.last_content_data.to_file(ContentServer::tmp_content_data_file)
|
30
|
+
sleep(0.1) # Added to prevent mv access issue
|
31
|
+
::FileUtils.mv(ContentServer::tmp_content_data_file, Params['local_content_data_path'])
|
32
|
+
|
33
|
+
|
28
34
|
Log.error("Interrupt or Exit happened in #{Params['service_name']} server: #{exc.class}, " +
|
29
35
|
"stopping process.\nBacktrace:\n#{exc.backtrace.join("\n")}")
|
30
36
|
Log.flush
|
31
37
|
exit
|
32
38
|
rescue Exception => exc
|
33
39
|
puts("Exception happened in #{Params['service_name']} server: #{exc.class}:#{exc.message}\nBacktrace:\n#{exc.backtrace.join("\n")}")
|
40
|
+
puts("Force writing local content data to #{Params['local_content_data_path']}.")
|
41
|
+
ContentServer::local_dynamic_content_data.last_content_data.to_file(ContentServer::tmp_content_data_file)
|
42
|
+
sleep(0.1) # Added to prevent mv access issue
|
43
|
+
::FileUtils.mv(ContentServer::tmp_content_data_file, Params['local_content_data_path'])
|
44
|
+
|
34
45
|
Log.error("Exception happened in #{Params['service_name']} server: #{exc.class}:#{exc.message}\nBacktrace:\n#{exc.backtrace.join("\n")}")
|
35
46
|
if retries > 0
|
36
47
|
Log.debug1("Restarting (retries:#{retries}).")
|
data/bin/content_server
CHANGED
@@ -20,14 +20,25 @@ begin
|
|
20
20
|
RunInBackground.run { ContentServer.run_content_server }
|
21
21
|
rescue SystemExit, SignalException => exc
|
22
22
|
# TODO (genadyp) do we need to trap signals by types?
|
23
|
+
#force dump of content data to file
|
23
24
|
puts("Interrupt or Exit happened in #{Params['service_name']} server: #{exc.class}, " +
|
24
25
|
"stopping process.\nBacktrace:\n#{exc.backtrace.join("\n")}")
|
26
|
+
puts("Force writing local content data to #{Params['local_content_data_path']}.")
|
27
|
+
ContentServer::local_dynamic_content_data.last_content_data.to_file(ContentServer::tmp_content_data_file)
|
28
|
+
sleep(0.1) # Added to prevent mv access issue
|
29
|
+
::FileUtils.mv(ContentServer::tmp_content_data_file, Params['local_content_data_path'])
|
30
|
+
|
25
31
|
Log.error("Interrupt or Exit happened in #{Params['service_name']} server: #{exc.class}, " +
|
26
32
|
"stopping process.\nBacktrace:\n#{exc.backtrace.join("\n")}")
|
27
33
|
Log.flush
|
28
34
|
exit
|
29
35
|
rescue Exception => exc
|
30
36
|
puts("Exception happened in #{Params['service_name']} server: #{exc.class}:#{exc.message}\nBacktrace:\n#{exc.backtrace.join("\n")}")
|
37
|
+
puts("Force writing local content data to #{Params['local_content_data_path']}.")
|
38
|
+
ContentServer::local_dynamic_content_data.last_content_data.to_file(ContentServer::tmp_content_data_file)
|
39
|
+
sleep(0.1) # Added to prevent mv access issue
|
40
|
+
::FileUtils.mv(ContentServer::tmp_content_data_file, Params['local_content_data_path'])
|
41
|
+
|
31
42
|
Log.error("Exception happened in #{Params['service_name']} server: #{exc.class}:#{exc.message}\nBacktrace:\n#{exc.backtrace.join("\n")}")
|
32
43
|
if retries > 0
|
33
44
|
Log.debug1("Restarting (retries:#{retries}).")
|
data/lib/content_server.rb
CHANGED
@@ -7,8 +7,7 @@ module ContentServer
|
|
7
7
|
|
8
8
|
# Monitoring
|
9
9
|
Params.boolean('enable_monitoring', false, 'Whether to enable process monitoring or not.')
|
10
|
-
Params.
|
11
|
-
Params.integer('process_vars_delay', 10, 'pulling time of variables')
|
10
|
+
Params.integer('process_vars_delay', 3, 'pulling time of variables')
|
12
11
|
|
13
12
|
# Handling thread exceptions.
|
14
13
|
Params.boolean('abort_on_exception', true, 'Any exception in any thread will abort the run.')
|
@@ -9,10 +9,10 @@ require 'content_server/queue_copy'
|
|
9
9
|
require 'content_server/remote_content'
|
10
10
|
require 'file_indexing'
|
11
11
|
require 'file_monitoring'
|
12
|
+
require 'content_server/globals'
|
12
13
|
require 'log'
|
13
14
|
require 'networking/tcp'
|
14
15
|
require 'params'
|
15
|
-
require 'process_monitoring/thread_safe_hash'
|
16
16
|
require 'process_monitoring/monitoring'
|
17
17
|
require 'process_monitoring/monitoring_info'
|
18
18
|
|
@@ -23,8 +23,18 @@ module ContentServer
|
|
23
23
|
Params.string('content_server_hostname', nil, 'IP or DNS of backup server.')
|
24
24
|
Params.integer('content_server_data_port', 3333, 'Port to copy content data from.')
|
25
25
|
Params.integer('content_server_files_port', 4444, 'Listening port in backup server for files')
|
26
|
-
|
27
26
|
Params.integer('backup_check_delay', 5, 'Delay in seconds between two content vs backup checks.')
|
27
|
+
Params.complex('backup_destination_folder',
|
28
|
+
[{'path'=>File.expand_path(''), 'scan_period'=>300, 'stable_state'=>1}],
|
29
|
+
'Backup server destination folder, default is the relative local folder.')
|
30
|
+
|
31
|
+
def self.tmp_content_data_file
|
32
|
+
@@tmp_content_data_file
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.local_dynamic_content_data
|
36
|
+
@@local_dynamic_content_data
|
37
|
+
end
|
28
38
|
|
29
39
|
def run_backup_server
|
30
40
|
Log.info('Start backup server')
|
@@ -34,22 +44,34 @@ module ContentServer
|
|
34
44
|
# create general tmp dir
|
35
45
|
FileUtils.mkdir_p(Params['tmp_path']) unless File.directory?(Params['tmp_path'])
|
36
46
|
# init tmp content data file
|
37
|
-
tmp_content_data_file = Params['tmp_path']
|
47
|
+
@@tmp_content_data_file = File.join(Params['tmp_path'], 'backup.data')
|
38
48
|
|
39
49
|
if Params['enable_monitoring']
|
40
50
|
Log.info("Initializing monitoring of process params on port:#{Params['process_monitoring_web_port']}")
|
41
|
-
|
42
|
-
Params['process_vars'].set('server_name', 'backup_server')
|
51
|
+
::ContentServer::Globals.process_vars.set('server_name', 'backup_server')
|
43
52
|
end
|
44
53
|
|
45
54
|
# # # # # # # # # # # #
|
46
|
-
# Initialize/
|
55
|
+
# Initialize/start monitoring and destination folder
|
56
|
+
Params['backup_destination_folder'][0]['path']=File.expand_path(Params['backup_destination_folder'][0]['path'])
|
57
|
+
Log.info("backup_destination_folder is:#{Params['backup_destination_folder'][0]['path']}")
|
58
|
+
#adding destination folder to monitoring paths
|
59
|
+
Params['monitoring_paths'] << Params['backup_destination_folder'][0]
|
47
60
|
Log.info('Start monitoring following directories:')
|
48
|
-
Params['monitoring_paths'].each {|path|
|
61
|
+
Params['monitoring_paths'].each { |path|
|
49
62
|
Log.info(" Path:'#{path['path']}'")
|
50
63
|
}
|
64
|
+
|
65
|
+
# Read here for initial content data that exist from previous system run
|
66
|
+
initial_content_data = ContentData::ContentData.new
|
67
|
+
content_data_path = Params['local_content_data_path']
|
68
|
+
initial_content_data.from_file(content_data_path) if File.exists?(content_data_path)
|
69
|
+
# Update local dynamic content with existing content
|
70
|
+
@@local_dynamic_content_data = ContentData::DynamicContentData.new
|
71
|
+
@@local_dynamic_content_data.update(initial_content_data)
|
72
|
+
|
51
73
|
monitoring_events = Queue.new
|
52
|
-
fm = FileMonitoring::FileMonitoring.new
|
74
|
+
fm = FileMonitoring::FileMonitoring.new(@@local_dynamic_content_data)
|
53
75
|
fm.set_event_queue(monitoring_events)
|
54
76
|
# Start monitoring and writing changes to queue
|
55
77
|
all_threads << Thread.new do
|
@@ -59,30 +81,10 @@ module ContentServer
|
|
59
81
|
# # # # # # # # # # # # # #
|
60
82
|
# Initialize/Start local indexer
|
61
83
|
Log.debug1('Start indexer')
|
62
|
-
|
63
|
-
queue_indexer = QueueIndexer.new(monitoring_events,
|
64
|
-
local_server_content_data_queue,
|
65
|
-
Params['local_content_data_path'])
|
84
|
+
queue_indexer = QueueIndexer.new(monitoring_events, @@local_dynamic_content_data)
|
66
85
|
# Start indexing on demand and write changes to queue
|
67
86
|
all_threads << queue_indexer.run
|
68
87
|
|
69
|
-
# # # # # # # # # # # # # # # # # # # # # # # # # # #
|
70
|
-
# Initialize/Start backup server content data sender
|
71
|
-
Log.debug1('Start backup server content data sender')
|
72
|
-
local_dynamic_content_data = ContentData::DynamicContentData.new
|
73
|
-
#content_data_sender = ContentDataSender.new(
|
74
|
-
# Params['remote_server'],
|
75
|
-
# Params['remote_listening_port'])
|
76
|
-
# Start sending to backup server
|
77
|
-
all_threads << Thread.new do
|
78
|
-
while true do
|
79
|
-
Log.debug1 'Waiting on local server content data queue.'
|
80
|
-
cd = local_server_content_data_queue.pop
|
81
|
-
# content_data_sender.send_content_data(cd)
|
82
|
-
local_dynamic_content_data.update(cd)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
88
|
# # # # # # # # # # # # # # # # # # # # # # # #
|
87
89
|
# Start dump local content data to file thread
|
88
90
|
Log.debug1('Start dump local content data to file thread')
|
@@ -91,26 +93,24 @@ module ContentServer
|
|
91
93
|
while true do
|
92
94
|
if last_data_flush_time.nil? || last_data_flush_time + Params['data_flush_delay'] < Time.now.to_i
|
93
95
|
Log.info "Writing local content data to #{Params['local_content_data_path']}."
|
94
|
-
local_dynamic_content_data.last_content_data.to_file(tmp_content_data_file)
|
96
|
+
@@local_dynamic_content_data.last_content_data.to_file(@@tmp_content_data_file)
|
95
97
|
sleep(0.1) # Added to prevent mv access issue
|
96
|
-
::FileUtils.mv(tmp_content_data_file, Params['local_content_data_path'])
|
98
|
+
::FileUtils.mv(@@tmp_content_data_file, Params['local_content_data_path'])
|
97
99
|
last_data_flush_time = Time.now.to_i
|
98
100
|
end
|
99
101
|
sleep(1)
|
100
102
|
end
|
101
103
|
end
|
102
|
-
Params['backup_destination_folder'] = File.expand_path(Params['monitoring_paths'][0]['path'])
|
103
|
-
Log.info("backup_destination_folder is:#{Params['backup_destination_folder']}")
|
104
104
|
content_server_dynamic_content_data = ContentData::DynamicContentData.new
|
105
105
|
remote_content = ContentServer::RemoteContentClient.new(content_server_dynamic_content_data,
|
106
106
|
Params['content_server_hostname'],
|
107
107
|
Params['content_server_data_port'],
|
108
|
-
Params['backup_destination_folder'])
|
108
|
+
Params['backup_destination_folder'][0]['path'])
|
109
109
|
all_threads.concat(remote_content.run())
|
110
110
|
|
111
111
|
file_copy_client = FileCopyClient.new(Params['content_server_hostname'],
|
112
112
|
Params['content_server_files_port'],
|
113
|
-
local_dynamic_content_data)
|
113
|
+
@@local_dynamic_content_data)
|
114
114
|
all_threads.concat(file_copy_client.threads)
|
115
115
|
|
116
116
|
# Each
|
@@ -118,16 +118,17 @@ module ContentServer
|
|
118
118
|
all_threads << Thread.new do
|
119
119
|
loop do
|
120
120
|
sleep(Params['backup_check_delay'])
|
121
|
-
local_cd = local_dynamic_content_data.last_content_data()
|
121
|
+
local_cd = @@local_dynamic_content_data.last_content_data()
|
122
122
|
remote_cd = content_server_dynamic_content_data.last_content_data()
|
123
|
-
diff = ContentData
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
123
|
+
diff = ContentData.remove(local_cd, remote_cd)
|
124
|
+
|
125
|
+
Log.debug2("Backup content:\n#{local_cd}")
|
126
|
+
Log.debug2("Remote content:\n#{remote_cd}")
|
127
|
+
Log.debug2("Diff content:\n#{diff}")
|
128
|
+
|
129
|
+
unless diff.nil? || diff.empty?
|
130
|
+
Log.info('Start sync check. Backup and remote contents need a sync, requesting copy files:')
|
129
131
|
Log.info("Missing contents:\n#{diff}")
|
130
|
-
Log.info('Requesting copy files')
|
131
132
|
file_copy_client.request_copy(diff)
|
132
133
|
else
|
133
134
|
Log.info("Start sync check. Local and remote contents are equal. No sync required.")
|
@@ -140,57 +141,40 @@ module ContentServer
|
|
140
141
|
if Params['enable_monitoring']
|
141
142
|
monitoring_info = MonitoringInfo::MonitoringInfo.new()
|
142
143
|
all_threads << Thread.new do
|
143
|
-
last_data_flush_time = nil
|
144
144
|
mutex = Mutex.new
|
145
145
|
while true do
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
string_count = ObjectSpace.each_object(String).count
|
169
|
-
file_count = ObjectSpace.each_object(::FileMonitoring::FileStat).count
|
170
|
-
dir_count = ObjectSpace.each_object(::FileMonitoring::DirStat).count
|
171
|
-
content_count = ObjectSpace.each_object(::ContentData::ContentData).count
|
172
|
-
index_agent_count = ObjectSpace.each_object(::FileIndexing::IndexAgent).count
|
173
|
-
indexer_patterns_count = ObjectSpace.each_object(::FileIndexing::IndexerPatterns).count
|
174
|
-
end
|
175
|
-
#enable following line to see full list of object:count
|
176
|
-
#Params['process_vars'].set('Live objs full', obj_array)
|
177
|
-
Log.info("process_vars:Live objs cnt:#{total_obj_count}")
|
178
|
-
Log.info("process_vars:Live String obj cnt:#{string_count}")
|
179
|
-
Log.info("process_vars:Live File obj cnt:#{file_count}")
|
180
|
-
Log.info("process_vars:Live Dir obj cnt:#{dir_count}")
|
181
|
-
Log.info("process_vars:Live Content data obj cnt:#{content_count}")
|
182
|
-
Log.info("process_vars:Live index agent obj cnt:#{index_agent_count}")
|
183
|
-
Log.info("process_vars:Live indexer patterns obj cnt:#{indexer_patterns_count}")
|
184
|
-
Params['process_vars'].set('Live objs cnt', total_obj_count)
|
185
|
-
Params['process_vars'].set('Live String obj cnt', string_count)
|
186
|
-
Params['process_vars'].set('Live File obj cnt', file_count)
|
187
|
-
Params['process_vars'].set('Live Dir obj cnt', dir_count)
|
188
|
-
Params['process_vars'].set('Live Content data obj cnt', content_count)
|
189
|
-
Params['process_vars'].set('Live index agent obj cnt', index_agent_count)
|
190
|
-
Params['process_vars'].set('Live indexer patterns obj cnt', indexer_patterns_count)
|
191
|
-
last_data_flush_time = Time.now
|
146
|
+
sleep(Params['process_vars_delay'])
|
147
|
+
::ContentServer::Globals.process_vars.set('time', Time.now)
|
148
|
+
Log.debug3("process_vars:monitoring queue size:#{monitoring_events.size}")
|
149
|
+
::ContentServer::Globals.process_vars.set('monitoring queue', monitoring_events.size)
|
150
|
+
#enable following line to see full list of object:count
|
151
|
+
#obj_array = ''
|
152
|
+
total_obj_count = 0
|
153
|
+
string_count = 0
|
154
|
+
file_count = 0
|
155
|
+
dir_count = 0
|
156
|
+
content_count = 0
|
157
|
+
mutex.synchronize do
|
158
|
+
ObjectSpace.each_object(Class) {|obj|
|
159
|
+
obj_count_per_class = ObjectSpace.each_object(obj).count
|
160
|
+
#enable following line to see full list of object:count
|
161
|
+
#obj_array = "#{obj_array} * #{obj.name}:#{obj_count_per_class}"
|
162
|
+
total_obj_count = total_obj_count + obj_count_per_class
|
163
|
+
}
|
164
|
+
string_count = ObjectSpace.each_object(String).count
|
165
|
+
file_count = ObjectSpace.each_object(::FileMonitoring::FileStat).count
|
166
|
+
dir_count = ObjectSpace.each_object(::FileMonitoring::DirStat).count
|
167
|
+
content_count = ObjectSpace.each_object(::ContentData::ContentData).count
|
192
168
|
end
|
193
|
-
|
169
|
+
#enable following line to see full list of object:count
|
170
|
+
#::ContentServer::Globals.process_vars.set('Live objs full', obj_array)
|
171
|
+
Log.debug3("process_vars:Live objs cnt:#{total_obj_count}")
|
172
|
+
::ContentServer::Globals.process_vars.set('Live objs cnt', total_obj_count)
|
173
|
+
Log.debug3("process_vars:Live String obj cnt:#{string_count}")
|
174
|
+
Log.debug3("process_vars:Live File obj cnt:#{file_count}")
|
175
|
+
Log.debug3("process_vars:Live Dir obj cnt:#{dir_count}")
|
176
|
+
Log.debug3("process_vars:Live Content data obj cnt:#{content_count}")
|
177
|
+
::ContentServer::Globals.process_vars.set('Live String obj cnt', string_count)
|
194
178
|
end
|
195
179
|
end
|
196
180
|
end
|
@@ -9,32 +9,41 @@ require 'content_server/queue_copy'
|
|
9
9
|
require 'content_server/remote_content'
|
10
10
|
require 'file_indexing'
|
11
11
|
require 'file_monitoring'
|
12
|
+
require 'content_server/globals'
|
12
13
|
require 'log'
|
13
14
|
require 'networking/tcp'
|
14
15
|
require 'params'
|
15
|
-
require 'process_monitoring/thread_safe_hash'
|
16
16
|
require 'process_monitoring/monitoring_info'
|
17
17
|
|
18
18
|
# Content server. Monitors files, index local files, listen to backup server content,
|
19
19
|
# copy changes and new files to backup server.
|
20
20
|
module ContentServer
|
21
21
|
# Content server specific flags.
|
22
|
-
Params.integer('local_files_port', 4444, 'Remote port in backup server to copy files
|
23
|
-
Params.integer('local_content_data_port', 3333, 'Listen to incoming content data requests
|
22
|
+
Params.integer('local_files_port', 4444, 'Remote port in backup server to copy files')
|
23
|
+
Params.integer('local_content_data_port', 3333, 'Listen to incoming content data requests')
|
24
|
+
Params.string('local_server_name', `hostname`.strip, 'local server name')
|
24
25
|
Params.path('tmp_path', '~/.bbfs/tmp', 'tmp path for temporary files')
|
25
26
|
|
27
|
+
def self.tmp_content_data_file
|
28
|
+
@@tmp_content_data_file
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.local_dynamic_content_data
|
32
|
+
@@local_dynamic_content_data
|
33
|
+
end
|
34
|
+
|
26
35
|
def run_content_server
|
27
36
|
Log.info('Content server start')
|
28
37
|
all_threads = []
|
38
|
+
|
29
39
|
# create general tmp dir
|
30
40
|
FileUtils.mkdir_p(Params['tmp_path']) unless File.directory?(Params['tmp_path'])
|
31
41
|
# init tmp content data file
|
32
|
-
tmp_content_data_file = Params['tmp_path']
|
42
|
+
@@tmp_content_data_file = File.join(Params['tmp_path'], 'content.data')
|
33
43
|
|
34
44
|
if Params['enable_monitoring']
|
35
45
|
Log.info("Initializing monitoring of process params on port:#{Params['process_monitoring_web_port']}")
|
36
|
-
|
37
|
-
Params['process_vars'].set('server_name', 'content_server')
|
46
|
+
::ContentServer::Globals.process_vars.set('server_name', 'content_server')
|
38
47
|
end
|
39
48
|
|
40
49
|
# # # # # # # # # # # #
|
@@ -44,7 +53,17 @@ module ContentServer
|
|
44
53
|
Log.info(" Path:'#{path['path']}'")
|
45
54
|
}
|
46
55
|
monitoring_events = Queue.new
|
47
|
-
|
56
|
+
|
57
|
+
# Read here for initial content data that exist from previous system run
|
58
|
+
initial_content_data = ContentData::ContentData.new
|
59
|
+
content_data_path = Params['local_content_data_path']
|
60
|
+
initial_content_data.from_file(content_data_path) if File.exists?(content_data_path)
|
61
|
+
# Update local dynamic content with existing content
|
62
|
+
@@local_dynamic_content_data = ContentData::DynamicContentData.new
|
63
|
+
@@local_dynamic_content_data.update(initial_content_data)
|
64
|
+
|
65
|
+
#Start files monitor taking into consideration existing content data
|
66
|
+
fm = FileMonitoring::FileMonitoring.new(@@local_dynamic_content_data)
|
48
67
|
fm.set_event_queue(monitoring_events)
|
49
68
|
# Start monitoring and writing changes to queue
|
50
69
|
all_threads << Thread.new do
|
@@ -54,26 +73,10 @@ module ContentServer
|
|
54
73
|
# # # # # # # # # # # # # #
|
55
74
|
# Initialize/Start local indexer
|
56
75
|
Log.debug1('Start indexer')
|
57
|
-
|
58
|
-
queue_indexer = QueueIndexer.new(monitoring_events,
|
59
|
-
local_server_content_data_queue,
|
60
|
-
Params['local_content_data_path'])
|
76
|
+
queue_indexer = QueueIndexer.new(monitoring_events, @@local_dynamic_content_data)
|
61
77
|
# Start indexing on demand and write changes to queue
|
62
78
|
all_threads << queue_indexer.run
|
63
79
|
|
64
|
-
# # # # # # # # # # # # # # # # # # # # # #
|
65
|
-
# Initialize/Start content data comparator
|
66
|
-
Log.debug1('Start content data comparator')
|
67
|
-
local_dynamic_content_data = ContentData::DynamicContentData.new
|
68
|
-
all_threads << Thread.new do # TODO(kolman): Seems like redundant, check how to update dynamic directly.
|
69
|
-
while true do
|
70
|
-
# Note: This thread should be the only consumer of local_server_content_data_queue
|
71
|
-
Log.debug1 'Waiting on local server content data.'
|
72
|
-
local_server_content_data = local_server_content_data_queue.pop
|
73
|
-
local_dynamic_content_data.update(local_server_content_data)
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
80
|
# # # # # # # # # # # # # # # # # # # # # # # #
|
78
81
|
# Start dump local content data to file thread
|
79
82
|
Log.debug1('Start dump local content data to file thread')
|
@@ -82,16 +85,16 @@ module ContentServer
|
|
82
85
|
while true do
|
83
86
|
if last_data_flush_time.nil? || last_data_flush_time + Params['data_flush_delay'] < Time.now.to_i
|
84
87
|
Log.info "Writing local content data to #{Params['local_content_data_path']}."
|
85
|
-
local_dynamic_content_data.last_content_data.to_file(tmp_content_data_file)
|
88
|
+
@@local_dynamic_content_data.last_content_data.to_file(@@tmp_content_data_file)
|
86
89
|
sleep(0.1) # Added to prevent mv access issue
|
87
|
-
::FileUtils.mv(tmp_content_data_file, Params['local_content_data_path'])
|
90
|
+
::FileUtils.mv(@@tmp_content_data_file, Params['local_content_data_path'])
|
88
91
|
last_data_flush_time = Time.now.to_i
|
89
92
|
end
|
90
93
|
sleep(1)
|
91
94
|
end
|
92
95
|
end
|
93
96
|
|
94
|
-
remote_content_client = RemoteContentServer.new(local_dynamic_content_data,
|
97
|
+
remote_content_client = RemoteContentServer.new(@@local_dynamic_content_data,
|
95
98
|
Params['local_content_data_port'])
|
96
99
|
all_threads << remote_content_client.tcp_thread
|
97
100
|
|
@@ -110,56 +113,43 @@ module ContentServer
|
|
110
113
|
last_data_flush_time = nil
|
111
114
|
mutex = Mutex.new
|
112
115
|
while true do
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
string_count = ObjectSpace.each_object(String).count
|
138
|
-
file_count = ObjectSpace.each_object(::FileMonitoring::FileStat).count
|
139
|
-
dir_count = ObjectSpace.each_object(::FileMonitoring::DirStat).count
|
140
|
-
content_count = ObjectSpace.each_object(::ContentData::ContentData).count
|
141
|
-
index_agent_count = ObjectSpace.each_object(::FileIndexing::IndexAgent).count
|
142
|
-
indexer_patterns_count = ObjectSpace.each_object(::FileIndexing::IndexerPatterns).count
|
143
|
-
end
|
144
|
-
#enable following line to see full list of object:count
|
145
|
-
#Params['process_vars'].set('Live objs full', obj_array)
|
146
|
-
Log.info("process_vars:Live objs cnt:#{total_obj_count}")
|
147
|
-
Log.info("process_vars:Live String obj cnt:#{string_count}")
|
148
|
-
Log.info("process_vars:Live File obj cnt:#{file_count}")
|
149
|
-
Log.info("process_vars:Live Dir obj cnt:#{dir_count}")
|
150
|
-
Log.info("process_vars:Live Content data obj cnt:#{content_count}")
|
151
|
-
Log.info("process_vars:Live index agent obj cnt:#{index_agent_count}")
|
152
|
-
Log.info("process_vars:Live indexer patterns obj cnt:#{indexer_patterns_count}")
|
153
|
-
Params['process_vars'].set('Live objs cnt', total_obj_count)
|
154
|
-
Params['process_vars'].set('Live String obj cnt', string_count)
|
155
|
-
Params['process_vars'].set('Live File obj cnt', file_count)
|
156
|
-
Params['process_vars'].set('Live Dir obj cnt', dir_count)
|
157
|
-
Params['process_vars'].set('Live Content data obj cnt', content_count)
|
158
|
-
Params['process_vars'].set('Live index agent obj cnt', index_agent_count)
|
159
|
-
Params['process_vars'].set('Live indexer patterns obj cnt', indexer_patterns_count)
|
160
|
-
last_data_flush_time = Time.now
|
116
|
+
sleep(Params['process_vars_delay'])
|
117
|
+
::ContentServer::Globals.process_vars.set('time', Time.now)
|
118
|
+
Log.debug3("process_vars:monitoring queue size:#{monitoring_events.size}")
|
119
|
+
::ContentServer::Globals.process_vars.set('monitoring queue', monitoring_events.size)
|
120
|
+
Log.debug3("process_vars:copy files events queue size:#{copy_files_events.size}")
|
121
|
+
::ContentServer::Globals.process_vars.set('copy files events queue', copy_files_events.size)
|
122
|
+
#enable following line to see full list of object:count
|
123
|
+
#obj_array = ''
|
124
|
+
total_obj_count = 0
|
125
|
+
string_count = 0
|
126
|
+
file_count = 0
|
127
|
+
dir_count = 0
|
128
|
+
content_count = 0
|
129
|
+
mutex.synchronize do
|
130
|
+
ObjectSpace.each_object(Class) {|obj|
|
131
|
+
obj_count_per_class = ObjectSpace.each_object(obj).count
|
132
|
+
#enable following line to see full list of object:count
|
133
|
+
#obj_array = "#{obj_array} * #{obj.name}:#{obj_count_per_class}"
|
134
|
+
total_obj_count = total_obj_count + obj_count_per_class
|
135
|
+
}
|
136
|
+
string_count = ObjectSpace.each_object(String).count
|
137
|
+
file_count = ObjectSpace.each_object(::FileMonitoring::FileStat).count
|
138
|
+
dir_count = ObjectSpace.each_object(::FileMonitoring::DirStat).count
|
139
|
+
content_count = ObjectSpace.each_object(::ContentData::ContentData).count
|
161
140
|
end
|
162
|
-
|
141
|
+
#enable following line to see full list of object:count
|
142
|
+
#process_vars.set('Live objs full', obj_array)
|
143
|
+
Log.debug3("process_vars:Live objs cnt:#{total_obj_count}")
|
144
|
+
Log.debug3("process_vars:Live String obj cnt:#{string_count}")
|
145
|
+
Log.debug3("process_vars:Live File obj cnt:#{file_count}")
|
146
|
+
Log.debug3("process_vars:Live Dir obj cnt:#{dir_count}")
|
147
|
+
Log.debug3("process_vars:Live Content data obj cnt:#{content_count}")
|
148
|
+
::ContentServer::Globals.process_vars.set('Live objs cnt', total_obj_count)
|
149
|
+
::ContentServer::Globals.process_vars.set('Live String obj cnt', string_count)
|
150
|
+
::ContentServer::Globals.process_vars.set('Live File obj cnt', file_count)
|
151
|
+
::ContentServer::Globals.process_vars.set('Live Dir obj cnt', dir_count)
|
152
|
+
::ContentServer::Globals.process_vars.set('Live Content data obj cnt', content_count)
|
163
153
|
end
|
164
154
|
end
|
165
155
|
end
|
@@ -2,6 +2,7 @@ require 'tempfile'
|
|
2
2
|
require 'thread'
|
3
3
|
|
4
4
|
require 'file_indexing/index_agent'
|
5
|
+
require 'content_server/globals'
|
5
6
|
require 'log'
|
6
7
|
require 'params'
|
7
8
|
|
@@ -12,9 +13,6 @@ module ContentServer
|
|
12
13
|
'Max number of content bytes to send in one chunk.')
|
13
14
|
Params.integer('file_streaming_timeout', 5*60,
|
14
15
|
'If no action is taken on a file streamer, abort copy.')
|
15
|
-
Params.path('backup_destination_folder', '',
|
16
|
-
'Backup server destination folder, default is the relative local folder.')
|
17
|
-
|
18
16
|
class Stream
|
19
17
|
attr_reader :checksum, :path, :tmp_path, :file, :size
|
20
18
|
def initialize(checksum, path, file, size)
|
@@ -59,24 +57,40 @@ module ContentServer
|
|
59
57
|
|
60
58
|
def copy_another_chuck(checksum)
|
61
59
|
@stream_queue << [:COPY_CHUNK, checksum]
|
60
|
+
if Params['enable_monitoring']
|
61
|
+
::ContentServer::Globals.process_vars.set('File Streamer queue', @stream_queue.size)
|
62
|
+
end
|
62
63
|
end
|
63
64
|
|
64
65
|
def start_streaming(checksum, path)
|
65
66
|
@stream_queue << [:NEW_STREAM, [checksum, path]]
|
67
|
+
if Params['enable_monitoring']
|
68
|
+
::ContentServer::Globals.process_vars.set('File Streamer queue', @stream_queue.size)
|
69
|
+
end
|
66
70
|
end
|
67
71
|
|
68
72
|
def abort_streaming(checksum)
|
69
73
|
@stream_queue << [:ABORT_STREAM, checksum]
|
74
|
+
if Params['enable_monitoring']
|
75
|
+
::ContentServer::Globals.process_vars.set('File Streamer queue', @stream_queue.size)
|
76
|
+
end
|
70
77
|
end
|
71
78
|
|
72
79
|
def reset_streaming(checksum, new_offset)
|
73
80
|
@stream_queue << [:RESET_STREAM, [checksum, new_offset]]
|
81
|
+
if Params['enable_monitoring']
|
82
|
+
::ContentServer::Globals.process_vars.set('File Streamer queue', @stream_queue.size)
|
83
|
+
end
|
74
84
|
end
|
75
85
|
|
76
86
|
def run
|
77
87
|
return Thread.new do
|
78
88
|
loop {
|
79
|
-
|
89
|
+
stream_pop = @stream_queue.pop
|
90
|
+
if Params['enable_monitoring']
|
91
|
+
::ContentServer::Globals.process_vars.set('File Streamer queue', @stream_queue.size)
|
92
|
+
end
|
93
|
+
checksum = handle(stream_pop)
|
80
94
|
}
|
81
95
|
end
|
82
96
|
end
|
@@ -87,6 +101,9 @@ module ContentServer
|
|
87
101
|
checksum, path = content
|
88
102
|
reset_stream(checksum, path, 0)
|
89
103
|
@stream_queue << [:COPY_CHUNK, checksum] if @streams.key?(checksum)
|
104
|
+
if Params['enable_monitoring']
|
105
|
+
::ContentServer::Globals.process_vars.set('File Streamer queue', @stream_queue.size)
|
106
|
+
end
|
90
107
|
elsif type == :ABORT_STREAM
|
91
108
|
checksum = content
|
92
109
|
Stream.close_delete_stream(checksum, @streams)
|
@@ -94,6 +111,9 @@ module ContentServer
|
|
94
111
|
checksum, new_offset = content
|
95
112
|
reset_stream(checksum, nil, new_offset)
|
96
113
|
@stream_queue << [:COPY_CHUNK, checksum] if @streams.key?(checksum)
|
114
|
+
if Params['enable_monitoring']
|
115
|
+
::ContentServer::Globals.process_vars.set('File Streamer queue', @stream_queue.size)
|
116
|
+
end
|
97
117
|
elsif type == :COPY_CHUNK
|
98
118
|
checksum = content
|
99
119
|
if @streams.key?(checksum)
|
@@ -191,11 +211,12 @@ module ContentServer
|
|
191
211
|
|
192
212
|
# open new stream
|
193
213
|
def handle_new_stream(file_checksum, file_size)
|
214
|
+
Log.info("enter handle_new_stream")
|
194
215
|
# final destination path
|
195
216
|
tmp_path = FileReceiver.destination_filename(
|
196
|
-
File.join(Params['backup_destination_folder'], 'tmp'),
|
217
|
+
File.join(Params['backup_destination_folder'][0]['path'], 'tmp'),
|
197
218
|
file_checksum)
|
198
|
-
path = FileReceiver.destination_filename(Params['backup_destination_folder'],
|
219
|
+
path = FileReceiver.destination_filename(Params['backup_destination_folder'][0]['path'],
|
199
220
|
file_checksum)
|
200
221
|
if File.exists?(path)
|
201
222
|
Log.warning("File already exists (#{path}) not writing.")
|
@@ -204,7 +225,7 @@ module ContentServer
|
|
204
225
|
# The file will be moved from tmp location once the transfer will be done
|
205
226
|
# system will use the checksum and some more unique key for tmp file name
|
206
227
|
FileUtils.makedirs(File.dirname(tmp_path)) unless File.directory?(File.dirname(tmp_path))
|
207
|
-
tmp_file =
|
228
|
+
tmp_file = File.new(tmp_path, 'wb')
|
208
229
|
@streams[file_checksum] = Stream.new(file_checksum, tmp_path, tmp_file, file_size)
|
209
230
|
end
|
210
231
|
end
|
@@ -234,7 +255,7 @@ module ContentServer
|
|
234
255
|
# Should always be true, unless file creation failed.
|
235
256
|
if @streams.key?(file_checksum)
|
236
257
|
# Make the directory if does not exists.
|
237
|
-
path = FileReceiver.destination_filename(Params['backup_destination_folder'],
|
258
|
+
path = FileReceiver.destination_filename(Params['backup_destination_folder'][0]['path'],
|
238
259
|
file_checksum)
|
239
260
|
Log.debug1("Moving tmp file #{@streams[file_checksum].path} to #{path}")
|
240
261
|
Log.debug1("Creating directory: #{path}")
|
@@ -2,6 +2,7 @@ require 'thread'
|
|
2
2
|
|
3
3
|
require 'content_server/file_streamer'
|
4
4
|
require 'file_indexing/index_agent'
|
5
|
+
require 'content_server/globals'
|
5
6
|
require 'log'
|
6
7
|
require 'networking/tcp'
|
7
8
|
require 'params'
|
@@ -55,12 +56,11 @@ module ContentServer
|
|
55
56
|
if message_type == :COPY_MESSAGE
|
56
57
|
Log.debug1 "Copy files event: #{message_content}"
|
57
58
|
# Prepare source,dest map for copy.
|
58
|
-
message_content.
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
@backup_tcp.send_obj([:ACK_MESSAGE, [instance.checksum, Time.now.to_i]])
|
59
|
+
message_content.each_instance { |checksum, size, content_mod_time, instance_mod_time, server, path|
|
60
|
+
if !@copy_prepare.key?(checksum) || !@copy_prepare[checksum][1]
|
61
|
+
@copy_prepare[checksum] = [path, false]
|
62
|
+
Log.debug1("Sending ack for: #{checksum}")
|
63
|
+
@backup_tcp.send_obj([:ACK_MESSAGE, [checksum, Time.now.to_i]])
|
64
64
|
end
|
65
65
|
}
|
66
66
|
elsif message_type == :ACK_MESSAGE
|
@@ -72,19 +72,23 @@ module ContentServer
|
|
72
72
|
"now: #{Time.now.to_i}")
|
73
73
|
|
74
74
|
# Copy file if ack (does not exists on backup and not too much time passed)
|
75
|
-
if ack
|
76
|
-
if
|
77
|
-
|
75
|
+
if ack
|
76
|
+
if (Time.now.to_i - timestamp < Params['ack_timeout'])
|
77
|
+
if !@copy_prepare.key?(checksum) || @copy_prepare[checksum][1]
|
78
|
+
Log.warning("File was aborted, copied, or started copy just now: #{checksum}")
|
79
|
+
else
|
80
|
+
path = @copy_prepare[checksum][0]
|
81
|
+
Log.info "Streaming to backup server. content: #{checksum} path:#{path}."
|
82
|
+
@file_streamer.start_streaming(checksum, path)
|
83
|
+
# Ack received, setting prepare to true
|
84
|
+
@copy_prepare[checksum][1] = true
|
85
|
+
end
|
78
86
|
else
|
79
|
-
|
80
|
-
|
81
|
-
@file_streamer.start_streaming(checksum, path)
|
82
|
-
# Ack received, setting prepare to true
|
83
|
-
@copy_prepare[checksum][1] = true
|
87
|
+
Log.debug1("Ack timed out span: #{Time.now.to_i - timestamp} > " \
|
88
|
+
"timeout: #{Params['ack_timeout']}")
|
84
89
|
end
|
85
90
|
else
|
86
|
-
Log.debug1(
|
87
|
-
"timeout: #{Params['ack_timeout']}")
|
91
|
+
Log.debug1('Ack is false');
|
88
92
|
end
|
89
93
|
elsif message_type == :COPY_CHUNK_FROM_REMOTE
|
90
94
|
checksum = message_content
|
@@ -122,7 +126,6 @@ module ContentServer
|
|
122
126
|
class FileCopyClient
|
123
127
|
def initialize(host, port, dynamic_content_data)
|
124
128
|
@local_queue = Queue.new
|
125
|
-
start_process_var_monitoring
|
126
129
|
@dynamic_content_data = dynamic_content_data
|
127
130
|
@tcp_client = Networking::TCPClient.new(host, port, method(:handle_message))
|
128
131
|
@file_receiver = FileReceiver.new(method(:done_copy),
|
@@ -130,6 +133,10 @@ module ContentServer
|
|
130
133
|
method(:reset_copy))
|
131
134
|
@local_thread = Thread.new do
|
132
135
|
loop do
|
136
|
+
pop_queue = @local_queue.pop
|
137
|
+
if Params['enable_monitoring']
|
138
|
+
::ContentServer::Globals.process_vars.set('File Copy Client queue', @local_queue.size)
|
139
|
+
end
|
133
140
|
handle(@local_queue.pop)
|
134
141
|
end
|
135
142
|
end
|
@@ -137,22 +144,6 @@ module ContentServer
|
|
137
144
|
Log.debug3("initialize FileCopyClient host:#{host} port:#{port}")
|
138
145
|
end
|
139
146
|
|
140
|
-
def start_process_var_monitoring
|
141
|
-
if Params['enable_monitoring']
|
142
|
-
@process_var_thread = Thread.new do
|
143
|
-
last_data_flush_time = nil
|
144
|
-
while true do
|
145
|
-
if last_data_flush_time.nil? || last_data_flush_time + Params['process_vars_delay'] < Time.now
|
146
|
-
Log.info("process_vars:FileCopyClient queue size:#{@local_queue.size}")
|
147
|
-
Params['process_vars'].set('File Copy Client queue', @local_queue.size)
|
148
|
-
last_data_flush_time = Time.now
|
149
|
-
end
|
150
|
-
sleep(0.3)
|
151
|
-
end
|
152
|
-
end
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
147
|
def threads
|
157
148
|
ret = [@local_thread]
|
158
149
|
ret << @tcp_client.tcp_thread if @tcp_client != nil
|
@@ -172,13 +163,18 @@ module ContentServer
|
|
172
163
|
end
|
173
164
|
|
174
165
|
def done_copy(local_file_checksum, local_path)
|
175
|
-
Params['
|
166
|
+
if Params['enable_monitoring']
|
167
|
+
::ContentServer::Globals.process_vars.inc('num_files_received')
|
168
|
+
end
|
176
169
|
Log.debug1("Done copy file: #{local_path}, #{local_file_checksum}")
|
177
170
|
end
|
178
171
|
|
179
172
|
def handle_message(message)
|
180
173
|
Log.debug3('QueueFileReceiver handle message')
|
181
174
|
@local_queue.push(message)
|
175
|
+
if Params['enable_monitoring']
|
176
|
+
::ContentServer::Globals.process_vars.set('File Copy Client queue', @local_queue.size)
|
177
|
+
end
|
182
178
|
end
|
183
179
|
|
184
180
|
# This is a function which receives the messages (file or ack) and return answer in case
|
@@ -186,8 +182,8 @@ module ContentServer
|
|
186
182
|
def handle(message)
|
187
183
|
message_type, message_content = message
|
188
184
|
if message_type == :SEND_COPY_MESSAGE
|
189
|
-
Log.debug1("Requesting
|
190
|
-
Log.debug2("
|
185
|
+
Log.debug1("Requesting files to copy.")
|
186
|
+
Log.debug2("Files requested: #{message_content.to_s}")
|
191
187
|
bytes_written = @tcp_client.send_obj([:COPY_MESSAGE, message_content])
|
192
188
|
Log.debug2("Sending copy message succeeded? bytes_written: #{bytes_written}.")
|
193
189
|
elsif message_type == :COPY_CHUNK
|
@@ -1,110 +1,89 @@
|
|
1
1
|
require 'file_indexing/index_agent'
|
2
2
|
require 'file_indexing/indexer_patterns'
|
3
|
+
require 'content_server/globals'
|
3
4
|
require 'log'
|
4
5
|
require 'params'
|
5
6
|
|
6
7
|
module ContentServer
|
7
8
|
|
8
|
-
|
9
9
|
# Simple indexer, gets inputs events (files to index) and outputs
|
10
10
|
# content data updates into output queue.
|
11
11
|
class QueueIndexer
|
12
12
|
|
13
|
-
def initialize(input_queue,
|
13
|
+
def initialize(input_queue, local_dynamic_content_data)
|
14
14
|
@input_queue = input_queue
|
15
|
-
@
|
16
|
-
@content_data_path = content_data_path
|
15
|
+
@local_dynamic_content_data = local_dynamic_content_data
|
17
16
|
end
|
18
17
|
|
18
|
+
# index files and add to copy queue
|
19
|
+
# delete directory with it's sub files
|
20
|
+
# delete file
|
19
21
|
def run
|
20
|
-
server_content_data = ContentData::ContentData.new
|
21
|
-
# Shallow check content data files.
|
22
|
-
tmp_content_data = ContentData::ContentData.new
|
23
|
-
tmp_content_data.from_file(@content_data_path) if File.exists?(@content_data_path)
|
24
|
-
tmp_content_data.instances.each_value do |instance|
|
25
|
-
# Skipp instances (files) which did not pass the shallow check.
|
26
|
-
Log.debug1('Shallow checking content data:')
|
27
|
-
if shallow_check(instance)
|
28
|
-
Log.debug1("exists: #{instance.full_path}")
|
29
|
-
server_content_data.add_content(tmp_content_data.contents[instance.checksum])
|
30
|
-
server_content_data.add_instance(instance)
|
31
|
-
else
|
32
|
-
Log.debug1("changed: #{instance.full_path}")
|
33
|
-
# Add non existing and changed files to index queue.
|
34
|
-
@input_queue.push([FileMonitoring::FileStatEnum::STABLE, instance.full_path])
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
22
|
# Start indexing on demand and write changes to queue
|
39
23
|
thread = Thread.new do
|
40
24
|
while true do
|
41
25
|
Log.debug1 'Waiting on index input queue.'
|
42
|
-
(state, is_dir, path) = @input_queue.pop
|
43
|
-
Log.debug1 "index event: state:#{state}, dir?#{is_dir}, path:#{path}."
|
44
|
-
|
45
|
-
# index files and add to copy queue
|
46
|
-
# delete directory with it's sub files
|
47
|
-
# delete file
|
26
|
+
(state, is_dir, path, mtime, size) = @input_queue.pop
|
27
|
+
Log.debug1 "index event: state:#{state}, dir?#{is_dir}, path:#{path}, mtime:#{mtime}, size:#{size}."
|
48
28
|
if state == FileMonitoring::FileStatEnum::STABLE && !is_dir
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
29
|
+
# Calculating checksum
|
30
|
+
instance_stats = @local_dynamic_content_data.stats_by_location([Params['local_server_name'], path])
|
31
|
+
Log.debug1("instance !#{instance_stats}! mtime: #{mtime.to_i}, size: #{size}")
|
32
|
+
if instance_stats.nil? || mtime.to_i != instance_stats[1] || size != instance_stats[0]
|
33
|
+
Log.info "Indexing file:'#{path}'."
|
34
|
+
checksum = calc_SHA1(path)
|
35
|
+
if Params['enable_monitoring']
|
36
|
+
::ContentServer::Globals.process_vars.inc('indexed_files')
|
37
|
+
end
|
38
|
+
Log.debug1("Index info:checksum:#{checksum} size:#{size} time:#{mtime.to_i}")
|
39
|
+
Log.debug1('Adding index to content data. put in queue for dynamic update.')
|
40
|
+
@local_dynamic_content_data.add_instance(checksum, size, Params['local_server_name'], path, mtime.to_i)
|
41
|
+
else
|
42
|
+
Log.info("Skip file #{path} indexing (shallow check passed)")
|
60
43
|
end
|
61
44
|
elsif ((state == FileMonitoring::FileStatEnum::NON_EXISTING ||
|
62
45
|
state == FileMonitoring::FileStatEnum::CHANGED) && !is_dir)
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
if server_content_data.instances.key?(key)
|
68
|
-
instance_to_remove = server_content_data.instances[key]
|
69
|
-
# Remove file from content data only if it does not pass the shallow check, i.e.,
|
70
|
-
# content has changed/removed.
|
71
|
-
if !shallow_check(instance_to_remove)
|
72
|
-
content_to_remove = server_content_data.contents[instance_to_remove.checksum]
|
73
|
-
# Remove the deleted instance.
|
74
|
-
content_data_to_remove = ContentData::ContentData.new
|
75
|
-
content_data_to_remove.add_content(content_to_remove)
|
76
|
-
content_data_to_remove.add_instance(instance_to_remove)
|
77
|
-
# Remove the file.
|
78
|
-
server_content_data = ContentData::ContentData.remove_instances(
|
79
|
-
content_data_to_remove, server_content_data)
|
80
|
-
end
|
81
|
-
end
|
46
|
+
Log.debug2("NonExisting/Changed (file): #{path}")
|
47
|
+
# Remove file but only when non-existing.
|
48
|
+
Log.debug1("File to remove: #{path}")
|
49
|
+
@local_dynamic_content_data.remove_instance([Params['local_server_name'],path])
|
82
50
|
elsif state == FileMonitoring::FileStatEnum::NON_EXISTING && is_dir
|
83
|
-
Log.
|
51
|
+
Log.debug2("NonExisting/Changed (dir): #{path}")
|
84
52
|
# Remove directory but only when non-existing.
|
85
53
|
Log.debug1("Directory to remove: #{path}")
|
86
|
-
|
87
|
-
server_content_data = ContentData::ContentData.remove_directory(
|
88
|
-
server_content_data, global_dir)
|
54
|
+
@local_dynamic_content_data.remove_directory(path, Params['local_server_name'])
|
89
55
|
else
|
90
56
|
Log.debug1("This case should not be handled: #{state}, #{is_dir}, #{path}.")
|
91
57
|
end
|
92
|
-
|
93
|
-
Log.debug1 'Adding server content data to queue.'
|
94
|
-
@output_queue.push(ContentData::ContentData.new(server_content_data))
|
95
58
|
end # while true do
|
96
59
|
end # Thread.new do
|
97
60
|
thread
|
98
61
|
end # def run
|
99
62
|
|
63
|
+
# Opens file and calculates SHA1 of it's content, returns SHA1
|
64
|
+
def calc_SHA1(path)
|
65
|
+
begin
|
66
|
+
digest = Digest::SHA1.new
|
67
|
+
File.open(path, 'rb') { |f|
|
68
|
+
while buffer = f.read(65536) do
|
69
|
+
digest << buffer
|
70
|
+
end
|
71
|
+
}
|
72
|
+
rescue
|
73
|
+
Log.warning("Monitored path'#{path}' does not exist. Probably file changed")
|
74
|
+
end
|
75
|
+
return digest.hexdigest.downcase
|
76
|
+
end
|
77
|
+
|
78
|
+
# Remove when not needed.
|
100
79
|
# Check file existence, check it's size and modification date.
|
101
80
|
# If something wrong reindex the file and update content data.
|
102
|
-
def shallow_check(
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
end
|
81
|
+
#def shallow_check(file_name, file_size, file_mod_time)
|
82
|
+
# shallow_instance = FileIndexing::IndexAgent.create_shallow_instance(file_name)
|
83
|
+
# return false unless shallow_instance
|
84
|
+
# return (shallow_instance[0] == file_size &&
|
85
|
+
# shallow_instance[2] == file_mod_time)
|
86
|
+
#end
|
108
87
|
|
109
88
|
end # class QueueIndexer
|
110
89
|
end
|
@@ -25,7 +25,6 @@ module ContentServer
|
|
25
25
|
def receive_content(message)
|
26
26
|
Log.debug1("Backup server received Remote content data:#{message.to_s}")
|
27
27
|
Log.info("Backup server received Remote content data")
|
28
|
-
ref = @dynamic_content_data.last_content_data
|
29
28
|
@dynamic_content_data.update(message)
|
30
29
|
@last_fetch_timestamp = Time.now.to_i
|
31
30
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: content_server
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-06-
|
12
|
+
date: 2013-06-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: content_data
|
@@ -18,7 +18,7 @@ dependencies:
|
|
18
18
|
requirements:
|
19
19
|
- - '='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 1.0
|
21
|
+
version: 1.1.0
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
24
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - '='
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 1.0
|
29
|
+
version: 1.1.0
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: file_indexing
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -34,7 +34,7 @@ dependencies:
|
|
34
34
|
requirements:
|
35
35
|
- - '='
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version: 1.0
|
37
|
+
version: 1.1.0
|
38
38
|
type: :runtime
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -42,7 +42,7 @@ dependencies:
|
|
42
42
|
requirements:
|
43
43
|
- - '='
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version: 1.0
|
45
|
+
version: 1.1.0
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
47
|
name: file_monitoring
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -50,7 +50,7 @@ dependencies:
|
|
50
50
|
requirements:
|
51
51
|
- - '='
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: 1.0
|
53
|
+
version: 1.1.0
|
54
54
|
type: :runtime
|
55
55
|
prerelease: false
|
56
56
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -58,7 +58,7 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - '='
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 1.0
|
61
|
+
version: 1.1.0
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
63
|
name: log
|
64
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -66,7 +66,7 @@ dependencies:
|
|
66
66
|
requirements:
|
67
67
|
- - '='
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: 1.0
|
69
|
+
version: 1.1.0
|
70
70
|
type: :runtime
|
71
71
|
prerelease: false
|
72
72
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -74,7 +74,7 @@ dependencies:
|
|
74
74
|
requirements:
|
75
75
|
- - '='
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
version: 1.0
|
77
|
+
version: 1.1.0
|
78
78
|
- !ruby/object:Gem::Dependency
|
79
79
|
name: networking
|
80
80
|
requirement: !ruby/object:Gem::Requirement
|
@@ -82,7 +82,7 @@ dependencies:
|
|
82
82
|
requirements:
|
83
83
|
- - '='
|
84
84
|
- !ruby/object:Gem::Version
|
85
|
-
version: 1.0
|
85
|
+
version: 1.1.0
|
86
86
|
type: :runtime
|
87
87
|
prerelease: false
|
88
88
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -90,7 +90,7 @@ dependencies:
|
|
90
90
|
requirements:
|
91
91
|
- - '='
|
92
92
|
- !ruby/object:Gem::Version
|
93
|
-
version: 1.0
|
93
|
+
version: 1.1.0
|
94
94
|
- !ruby/object:Gem::Dependency
|
95
95
|
name: params
|
96
96
|
requirement: !ruby/object:Gem::Requirement
|
@@ -98,7 +98,7 @@ dependencies:
|
|
98
98
|
requirements:
|
99
99
|
- - '='
|
100
100
|
- !ruby/object:Gem::Version
|
101
|
-
version: 1.0
|
101
|
+
version: 1.1.0
|
102
102
|
type: :runtime
|
103
103
|
prerelease: false
|
104
104
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -106,7 +106,7 @@ dependencies:
|
|
106
106
|
requirements:
|
107
107
|
- - '='
|
108
108
|
- !ruby/object:Gem::Version
|
109
|
-
version: 1.0
|
109
|
+
version: 1.1.0
|
110
110
|
- !ruby/object:Gem::Dependency
|
111
111
|
name: process_monitoring
|
112
112
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,7 +114,7 @@ dependencies:
|
|
114
114
|
requirements:
|
115
115
|
- - '='
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: 1.0
|
117
|
+
version: 1.1.0
|
118
118
|
type: :runtime
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -122,7 +122,7 @@ dependencies:
|
|
122
122
|
requirements:
|
123
123
|
- - '='
|
124
124
|
- !ruby/object:Gem::Version
|
125
|
-
version: 1.0
|
125
|
+
version: 1.1.0
|
126
126
|
- !ruby/object:Gem::Dependency
|
127
127
|
name: rake
|
128
128
|
requirement: !ruby/object:Gem::Requirement
|
@@ -146,7 +146,7 @@ dependencies:
|
|
146
146
|
requirements:
|
147
147
|
- - '='
|
148
148
|
- !ruby/object:Gem::Version
|
149
|
-
version: 1.0
|
149
|
+
version: 1.1.0
|
150
150
|
type: :runtime
|
151
151
|
prerelease: false
|
152
152
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -154,7 +154,7 @@ dependencies:
|
|
154
154
|
requirements:
|
155
155
|
- - '='
|
156
156
|
- !ruby/object:Gem::Version
|
157
|
-
version: 1.0
|
157
|
+
version: 1.1.0
|
158
158
|
- !ruby/object:Gem::Dependency
|
159
159
|
name: content_data
|
160
160
|
requirement: !ruby/object:Gem::Requirement
|
@@ -162,7 +162,7 @@ dependencies:
|
|
162
162
|
requirements:
|
163
163
|
- - '='
|
164
164
|
- !ruby/object:Gem::Version
|
165
|
-
version: 1.0
|
165
|
+
version: 1.1.0
|
166
166
|
type: :runtime
|
167
167
|
prerelease: false
|
168
168
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -170,7 +170,7 @@ dependencies:
|
|
170
170
|
requirements:
|
171
171
|
- - '='
|
172
172
|
- !ruby/object:Gem::Version
|
173
|
-
version: 1.0
|
173
|
+
version: 1.1.0
|
174
174
|
- !ruby/object:Gem::Dependency
|
175
175
|
name: file_indexing
|
176
176
|
requirement: !ruby/object:Gem::Requirement
|
@@ -178,7 +178,7 @@ dependencies:
|
|
178
178
|
requirements:
|
179
179
|
- - '='
|
180
180
|
- !ruby/object:Gem::Version
|
181
|
-
version: 1.0
|
181
|
+
version: 1.1.0
|
182
182
|
type: :runtime
|
183
183
|
prerelease: false
|
184
184
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -186,7 +186,7 @@ dependencies:
|
|
186
186
|
requirements:
|
187
187
|
- - '='
|
188
188
|
- !ruby/object:Gem::Version
|
189
|
-
version: 1.0
|
189
|
+
version: 1.1.0
|
190
190
|
- !ruby/object:Gem::Dependency
|
191
191
|
name: file_monitoring
|
192
192
|
requirement: !ruby/object:Gem::Requirement
|
@@ -194,7 +194,7 @@ dependencies:
|
|
194
194
|
requirements:
|
195
195
|
- - '='
|
196
196
|
- !ruby/object:Gem::Version
|
197
|
-
version: 1.0
|
197
|
+
version: 1.1.0
|
198
198
|
type: :runtime
|
199
199
|
prerelease: false
|
200
200
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -202,7 +202,7 @@ dependencies:
|
|
202
202
|
requirements:
|
203
203
|
- - '='
|
204
204
|
- !ruby/object:Gem::Version
|
205
|
-
version: 1.0
|
205
|
+
version: 1.1.0
|
206
206
|
- !ruby/object:Gem::Dependency
|
207
207
|
name: log
|
208
208
|
requirement: !ruby/object:Gem::Requirement
|
@@ -210,7 +210,7 @@ dependencies:
|
|
210
210
|
requirements:
|
211
211
|
- - '='
|
212
212
|
- !ruby/object:Gem::Version
|
213
|
-
version: 1.0
|
213
|
+
version: 1.1.0
|
214
214
|
type: :runtime
|
215
215
|
prerelease: false
|
216
216
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -218,7 +218,7 @@ dependencies:
|
|
218
218
|
requirements:
|
219
219
|
- - '='
|
220
220
|
- !ruby/object:Gem::Version
|
221
|
-
version: 1.0
|
221
|
+
version: 1.1.0
|
222
222
|
- !ruby/object:Gem::Dependency
|
223
223
|
name: networking
|
224
224
|
requirement: !ruby/object:Gem::Requirement
|
@@ -226,7 +226,7 @@ dependencies:
|
|
226
226
|
requirements:
|
227
227
|
- - '='
|
228
228
|
- !ruby/object:Gem::Version
|
229
|
-
version: 1.0
|
229
|
+
version: 1.1.0
|
230
230
|
type: :runtime
|
231
231
|
prerelease: false
|
232
232
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -234,7 +234,7 @@ dependencies:
|
|
234
234
|
requirements:
|
235
235
|
- - '='
|
236
236
|
- !ruby/object:Gem::Version
|
237
|
-
version: 1.0
|
237
|
+
version: 1.1.0
|
238
238
|
- !ruby/object:Gem::Dependency
|
239
239
|
name: params
|
240
240
|
requirement: !ruby/object:Gem::Requirement
|
@@ -242,7 +242,7 @@ dependencies:
|
|
242
242
|
requirements:
|
243
243
|
- - '='
|
244
244
|
- !ruby/object:Gem::Version
|
245
|
-
version: 1.0
|
245
|
+
version: 1.1.0
|
246
246
|
type: :runtime
|
247
247
|
prerelease: false
|
248
248
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -250,7 +250,7 @@ dependencies:
|
|
250
250
|
requirements:
|
251
251
|
- - '='
|
252
252
|
- !ruby/object:Gem::Version
|
253
|
-
version: 1.0
|
253
|
+
version: 1.1.0
|
254
254
|
- !ruby/object:Gem::Dependency
|
255
255
|
name: process_monitoring
|
256
256
|
requirement: !ruby/object:Gem::Requirement
|
@@ -258,7 +258,7 @@ dependencies:
|
|
258
258
|
requirements:
|
259
259
|
- - '='
|
260
260
|
- !ruby/object:Gem::Version
|
261
|
-
version: 1.0
|
261
|
+
version: 1.1.0
|
262
262
|
type: :runtime
|
263
263
|
prerelease: false
|
264
264
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -266,7 +266,7 @@ dependencies:
|
|
266
266
|
requirements:
|
267
267
|
- - '='
|
268
268
|
- !ruby/object:Gem::Version
|
269
|
-
version: 1.0
|
269
|
+
version: 1.1.0
|
270
270
|
- !ruby/object:Gem::Dependency
|
271
271
|
name: rake
|
272
272
|
requirement: !ruby/object:Gem::Requirement
|
@@ -290,7 +290,7 @@ dependencies:
|
|
290
290
|
requirements:
|
291
291
|
- - '='
|
292
292
|
- !ruby/object:Gem::Version
|
293
|
-
version: 1.0
|
293
|
+
version: 1.1.0
|
294
294
|
type: :runtime
|
295
295
|
prerelease: false
|
296
296
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -298,7 +298,7 @@ dependencies:
|
|
298
298
|
requirements:
|
299
299
|
- - '='
|
300
300
|
- !ruby/object:Gem::Version
|
301
|
-
version: 1.0
|
301
|
+
version: 1.1.0
|
302
302
|
description: Monitor and Index a directory and back it up to backup server.
|
303
303
|
email: bbfsdev@gmail.com
|
304
304
|
executables:
|
@@ -310,6 +310,7 @@ files:
|
|
310
310
|
- lib/content_server.rb
|
311
311
|
- lib/content_server/file_streamer.rb
|
312
312
|
- lib/content_server/queue_copy.rb
|
313
|
+
- lib/content_server/globals.rb
|
313
314
|
- lib/content_server/content_server.rb
|
314
315
|
- lib/content_server/content_receiver.rb
|
315
316
|
- lib/content_server/remote_content.rb
|