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.
- data/bin/backup_server +8 -20
- data/bin/content_server +8 -20
- data/bin/testing_memory +60 -0
- data/bin/testing_server +57 -0
- data/ext/run_in_background/mkrf_conf.rb +34 -0
- data/lib/content_data/content_data.rb +613 -0
- data/lib/content_data/version.rb +3 -0
- data/lib/content_data.rb +6 -0
- data/lib/content_server/backup_server.rb +65 -86
- data/lib/content_server/content_server.rb +47 -77
- data/lib/content_server/file_streamer.rb +27 -33
- data/lib/content_server/queue_copy.rb +154 -49
- data/lib/content_server/queue_indexer.rb +19 -11
- data/lib/content_server/remote_content.rb +41 -23
- data/lib/content_server/server.rb +91 -0
- data/lib/content_server/version.rb +1 -1
- data/lib/content_server.rb +0 -15
- data/lib/email/email.rb +87 -0
- data/lib/email/version.rb +3 -0
- data/lib/email.rb +4 -0
- data/lib/file_copy/copy.rb +68 -0
- data/lib/file_copy/version.rb +4 -0
- data/lib/file_copy.rb +4 -0
- data/lib/file_indexing/index_agent.rb +170 -0
- data/lib/file_indexing/indexer_patterns.rb +72 -0
- data/lib/file_indexing/version.rb +3 -0
- data/lib/file_indexing.rb +9 -0
- data/lib/file_monitoring/file_monitoring.rb +105 -0
- data/lib/file_monitoring/monitor_path.rb +304 -0
- data/lib/file_monitoring/version.rb +3 -0
- data/lib/file_monitoring.rb +29 -0
- data/lib/file_utils/file_generator/README +97 -0
- data/lib/file_utils/file_generator/file_generator.rb +156 -0
- data/lib/file_utils/file_utils.rb +260 -0
- data/lib/file_utils/version.rb +3 -0
- data/lib/file_utils.rb +4 -0
- data/lib/log/version.rb +3 -0
- data/lib/log.rb +188 -0
- data/lib/networking/tcp.rb +213 -0
- data/lib/networking/version.rb +3 -0
- data/lib/networking.rb +4 -0
- data/lib/params/version.rb +3 -0
- data/lib/params.rb +419 -0
- data/lib/process_monitoring/monitoring.rb +85 -0
- data/lib/process_monitoring/monitoring_info.rb +79 -0
- data/lib/process_monitoring/send_email.rb +40 -0
- data/lib/process_monitoring/thread_safe_hash.rb +77 -0
- data/lib/process_monitoring/version.rb +3 -0
- data/lib/process_monitoring.rb +6 -0
- data/lib/run_in_background/version.rb +3 -0
- data/lib/run_in_background.rb +432 -0
- data/lib/testing_memory/testing_memory.rb +187 -0
- data/lib/testing_server/testing_server.rb +236 -0
- data/lib/testing_server/version.rb +3 -0
- data/lib/testing_server.rb +12 -0
- data/lib/validations/index_validations.rb +106 -0
- data/lib/validations/version.rb +3 -0
- data/lib/validations.rb +4 -0
- data/spec/content_data/validations_spec.rb +113 -0
- data/spec/file_copy/copy_spec.rb +54 -0
- data/spec/file_indexing/index_agent_spec.rb +53 -0
- data/spec/networking/tcp_spec.rb +95 -0
- data/spec/validations/index_validations_spec.rb +77 -0
- data/test/content_data/content_data_test.rb +290 -0
- data/test/file_generator/file_generator_spec.rb +84 -0
- data/test/file_indexing/index_agent_test/New.txt +0 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/bin/libexslt.dll +0 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/bin/libxslt.dll +0 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/bin/xsltproc.exe +0 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libexslt/exslt.h +102 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libexslt/exsltconfig.h +73 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libexslt/exsltexports.h +140 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libexslt/libexslt.h +29 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/attributes.h +38 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/documents.h +93 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/extensions.h +262 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/extra.h +80 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/functions.h +78 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/imports.h +75 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/keys.h +53 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/libxslt.h +30 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/namespaces.h +68 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/numbersInternals.h +69 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/pattern.h +81 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/preproc.h +43 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/security.h +104 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/templates.h +77 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/transform.h +207 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/trio.h +216 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/triodef.h +220 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/variables.h +91 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/win32config.h +101 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xslt.h +103 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xsltInternals.h +1967 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xsltconfig.h +172 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xsltexports.h +142 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xsltlocale.h +57 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xsltutils.h +309 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xsltwin32config.h +105 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/lib/libexslt.lib +0 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/lib/libexslt_a.lib +0 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/lib/libxslt.lib +0 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/lib/libxslt_a.lib +0 -0
- data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/readme.txt +22 -0
- data/test/file_indexing/index_agent_test/patterns.input +3 -0
- data/test/file_indexing/index_agent_test.rb +51 -0
- data/test/file_monitoring/file_monitoring_test/conf.yml +4 -0
- data/test/file_monitoring/file_monitoring_test/conf_win32.yml +5 -0
- data/test/file_monitoring/file_monitoring_test/log +56 -0
- data/test/file_monitoring/file_monitoring_test.rb +0 -0
- data/test/file_monitoring/monitor_path_test/dir1000/test_file.1000 +1000 -0
- data/test/file_monitoring/monitor_path_test/dir1000/test_file.1000.0 +1000 -0
- data/test/file_monitoring/monitor_path_test/dir1000/test_file.1000.1 +1000 -0
- data/test/file_monitoring/monitor_path_test/dir1500/test_file.1500 +1500 -0
- data/test/file_monitoring/monitor_path_test/dir1500/test_file.1500.0 +1500 -0
- data/test/file_monitoring/monitor_path_test/dir1500/test_file.1500.1 +1500 -0
- data/test/file_monitoring/monitor_path_test/test_file.500 +500 -0
- data/test/file_monitoring/monitor_path_test/test_file.500.0 +500 -0
- data/test/file_monitoring/monitor_path_test/test_file.500.1 +500 -0
- data/test/file_monitoring/monitor_path_test.rb +153 -0
- data/test/file_utils/fileutil_mksymlink_test/dir1000/dir1500/test_file.1500 +1500 -0
- data/test/file_utils/fileutil_mksymlink_test/dir1000/dir1500/test_file.1500.0 +1500 -0
- data/test/file_utils/fileutil_mksymlink_test/dir1000/dir1500/test_file.1500.1 +1500 -0
- data/test/file_utils/fileutil_mksymlink_test/dir1000/test_file.1000 +1000 -0
- data/test/file_utils/fileutil_mksymlink_test/dir1000/test_file.1000.0 +1000 -0
- data/test/file_utils/fileutil_mksymlink_test/dir1000/test_file.1000.1 +1000 -0
- data/test/file_utils/fileutil_mksymlink_test/test_file.500 +500 -0
- data/test/file_utils/fileutil_mksymlink_test/test_file.500.0 +500 -0
- data/test/file_utils/fileutil_mksymlink_test/test_file.500.1 +500 -0
- data/test/file_utils/fileutil_mksymlink_test.rb +125 -0
- data/test/file_utils/time_modification_test.rb +132 -0
- data/test/params/params_spec.rb +280 -0
- data/test/params/params_test.rb +43 -0
- data/test/run_in_background/run_in_background_test.rb +122 -0
- data/test/run_in_background/test_app +57 -0
- metadata +272 -132
- data/lib/content_server/globals.rb +0 -10
data/lib/params.rb
ADDED
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
# Author: Yaron Dror (yaron.dror.bb@gmail.com)
|
|
2
|
+
# Description: The file contains 'Params' module implementation.
|
|
3
|
+
# Notes:
|
|
4
|
+
# module.init should be called if user wants to override defined parameters by file or command line.
|
|
5
|
+
# Parameter can be defined only once.
|
|
6
|
+
# Parameters have to be defined before they are accessed. see examples below.
|
|
7
|
+
#
|
|
8
|
+
# Examples of definitions:
|
|
9
|
+
# Params.string('parameter_str', 'this is a string' ,'description_for_string')
|
|
10
|
+
# Params.path('parameter_path', '/Users/username/example/ect' ,'description_for_directory')
|
|
11
|
+
# Params.integer('parameter_int',1 , 'description_for_integer')
|
|
12
|
+
# Params.float('parameter_float',2.6 , 'description_for_float')
|
|
13
|
+
# Params.boolean('parameter_true', true, 'description_for_true')
|
|
14
|
+
# Params.boolean('parameter_false',false , 'description_for_false')
|
|
15
|
+
# Params.complex('parameter_complex', [a,b,{b=>c}], 'description for dict or list of strings.')
|
|
16
|
+
# Note. Parameters have to be defined before they are accessed.
|
|
17
|
+
#
|
|
18
|
+
# Examples of usages (get\set access is through the [] operator).
|
|
19
|
+
# local_var_of_type_string = Params['parameter_str']
|
|
20
|
+
# puts local_var_of_type_string # Will produce --> this is a string
|
|
21
|
+
# Params['parameter_float'] = 3.8
|
|
22
|
+
# puts Params['parameter_float'] # Will produce --> 3.8
|
|
23
|
+
# Params['parameter_float'] = 3
|
|
24
|
+
# puts Params['parameter_float'] # Will produce --> 3.0 (note the casting)
|
|
25
|
+
# Note. only after definition, the [] operator will work. Else an error is raised.
|
|
26
|
+
# Params['new_param'] = true # will raise an error, since the param was not defined yet.
|
|
27
|
+
# Params.boolean 'new_param', true, 'this is correct' # this is the definition.
|
|
28
|
+
# Params['new_param'] = false # Will set new value.
|
|
29
|
+
# puts Params['new_param'] # Will produce --> false
|
|
30
|
+
#
|
|
31
|
+
# Type check.
|
|
32
|
+
# A type check is forced both when overriding with file or command line and in [] usage.
|
|
33
|
+
# if parameter was defined as a Float using Params.float method (e.g. 2.6) and user
|
|
34
|
+
# provided an integer when overriding or when using [] operator then the integer will
|
|
35
|
+
# be casted to float.
|
|
36
|
+
#
|
|
37
|
+
# Params.Init - override parameters.
|
|
38
|
+
# implementation of the init sequence allows the override of
|
|
39
|
+
# defined parameters with new values through input file and\or command line args.
|
|
40
|
+
# Note that only defined parameters can be overridden. If new parameter is parsed
|
|
41
|
+
# through file\command line, then an error will be raised.
|
|
42
|
+
# Input config file override:
|
|
43
|
+
# Default configuration input file path is: '~/.bbfs/conf/<executable name>.conf'
|
|
44
|
+
# This path can be overridden by the command line arguments (see ahead).
|
|
45
|
+
# If path and file exist then the parameters in the file will override the defined
|
|
46
|
+
# parameters. File parameters format per line:<param_name>: <param value>
|
|
47
|
+
# Note: Space char after the colon is mandatory
|
|
48
|
+
# Command line arguments override:
|
|
49
|
+
# General format per argument is:--<param_name>=<param_value>
|
|
50
|
+
# those parameters will override the defined parameters and the file parameters.
|
|
51
|
+
# Override input config file:
|
|
52
|
+
# User can override the input file by using:--conf_file=<new_file_path>
|
|
53
|
+
#
|
|
54
|
+
# More examples in bbfs/examples/params/rb
|
|
55
|
+
|
|
56
|
+
require 'optparse'
|
|
57
|
+
require 'stringio'
|
|
58
|
+
require 'yaml'
|
|
59
|
+
|
|
60
|
+
module Params
|
|
61
|
+
|
|
62
|
+
# Represents a parameter.
|
|
63
|
+
class Param
|
|
64
|
+
attr_accessor :name
|
|
65
|
+
attr_accessor :value
|
|
66
|
+
attr_accessor :desc
|
|
67
|
+
attr_accessor :type
|
|
68
|
+
|
|
69
|
+
# value_type_check method:
|
|
70
|
+
# 1. Check if member:'type' is one of:Integer, Float, String or Boolean.
|
|
71
|
+
# 2. input parameter:'value' class type is valid to override this parameter.
|
|
72
|
+
# 3. Return value. The value to override with correct type. A cast from integer to Float will
|
|
73
|
+
# be made for Float parameters which are set with integer values.
|
|
74
|
+
# 4. Check will be skipped for nil value.
|
|
75
|
+
def value_type_check(value)
|
|
76
|
+
if value.nil?
|
|
77
|
+
return value
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
case( @type )
|
|
81
|
+
when 'Integer' then
|
|
82
|
+
if not @value.nil?
|
|
83
|
+
if not ((value.class.eql? Integer) or
|
|
84
|
+
(value.class.eql? Fixnum))
|
|
85
|
+
raise "Parameter:'#{@name}' type:'Integer' but value type to override " \
|
|
86
|
+
"is:'#{value.class}'."
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
when 'Float' then
|
|
90
|
+
if not @value.nil?
|
|
91
|
+
if not value.class.eql? Float
|
|
92
|
+
if not ((value.class.eql? Integer) or
|
|
93
|
+
(value.class.eql? Fixnum))
|
|
94
|
+
raise("Parameter:'#{@name}' type:'Float' but value type to override " \
|
|
95
|
+
"is:'#{value.class}'.")
|
|
96
|
+
else
|
|
97
|
+
return value.to_f
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
when 'String' then
|
|
102
|
+
when 'Path' then
|
|
103
|
+
# TODO(kolman): Override the type check with regexp of path in Linux and/or Windows
|
|
104
|
+
if not @value.nil?
|
|
105
|
+
if not value.class.eql? String
|
|
106
|
+
raise("Parameter:'#{@name}' type:'String' but value type to override " \
|
|
107
|
+
"is:'#{value.class}'.")
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
when 'Boolean' then
|
|
111
|
+
if not @value.nil?
|
|
112
|
+
if not((value.class.eql? TrueClass) or (value.class.eql? FalseClass))
|
|
113
|
+
raise("Parameter:'#{@name}' type:'Boolean' but value type to override " \
|
|
114
|
+
"is:'#{value.class}'.")
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
when 'Complex' then
|
|
118
|
+
unless @value.nil?
|
|
119
|
+
unless (value.class.eql? Hash) or (value.class.eql? Array)
|
|
120
|
+
raise("Parameter:'#{@name}' type:'Complex' but value type to override " \
|
|
121
|
+
"is:'#{value.class}'.")
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
else
|
|
125
|
+
raise("Parameter:'#{@name}' type:'#{@value.class}' but parameter " \
|
|
126
|
+
"type to override:'#{value.class}' is not supported. " + \
|
|
127
|
+
"Supported types are:Integer, Float, String or Boolean.")
|
|
128
|
+
end
|
|
129
|
+
return value
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# supported types are: String, Integer, Float, Boolean, Path or Complex
|
|
133
|
+
def initialize(name, value, type, desc)
|
|
134
|
+
@name = name
|
|
135
|
+
@type = type
|
|
136
|
+
@desc = desc
|
|
137
|
+
@value = value_type_check value
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
@params_data_base = Hash.new # The parameters data structure.
|
|
142
|
+
@init_info_messages = []
|
|
143
|
+
@show_help_and_exit = false
|
|
144
|
+
|
|
145
|
+
def Params.get_init_info_messages
|
|
146
|
+
return @init_info_messages
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def Params.get_init_warning_messages
|
|
150
|
+
return @init_warning_messages
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def Params.raise_error_if_param_does_not_exist(name)
|
|
154
|
+
if not @params_data_base[name]
|
|
155
|
+
raise("before using parameter:'#{name}', it should first be defined through Param module methods:" \
|
|
156
|
+
"Params.string, Params.path, Params.integer, Params.float, Params.complex, or Params.boolean.")
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def Params.raise_error_if_param_exists(name)
|
|
161
|
+
if @params_data_base[name]
|
|
162
|
+
raise("Parameter:'#{name}', can only be defined once.")
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# Read param value by other modules.
|
|
167
|
+
# Note that this operator should only be used, after parameter has been defined through
|
|
168
|
+
# one of Param module methods: Params.string, Params.integer,
|
|
169
|
+
# Params.float or Params.boolean."
|
|
170
|
+
def Params.[](name)
|
|
171
|
+
raise_error_if_param_does_not_exist(name)
|
|
172
|
+
@params_data_base[name].value
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def Params.each(&block)
|
|
176
|
+
@params_data_base.each(&block)
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
# Write param value by other modules.
|
|
180
|
+
# Note that this operator should only be used, after parameter has been defined through
|
|
181
|
+
# one of Param module methods: Params.string, Params.integer,
|
|
182
|
+
# Params.float or Params.boolean."
|
|
183
|
+
def Params.[]=(name, value)
|
|
184
|
+
raise_error_if_param_does_not_exist(name)
|
|
185
|
+
set_value = @params_data_base[name].value_type_check(value)
|
|
186
|
+
@params_data_base[name].value = set_value
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
#override parameter should only be called by Params module methods.
|
|
190
|
+
def Params.override_param(name, value)
|
|
191
|
+
existing_param = @params_data_base[name]
|
|
192
|
+
if existing_param.nil?
|
|
193
|
+
raise("Parameter:'#{name}' has not been defined and can not be overridden. " \
|
|
194
|
+
"It should first be defined through Param module methods:" \
|
|
195
|
+
"Params.string, Params.path, Params.integer, Params.float, Params.complex, or Params.boolean.")
|
|
196
|
+
end
|
|
197
|
+
if value.nil?
|
|
198
|
+
existing_param.value = nil
|
|
199
|
+
elsif existing_param.type.eql?('String')
|
|
200
|
+
existing_param.value = value.to_s
|
|
201
|
+
elsif existing_param.type.eql?('Path')
|
|
202
|
+
existing_param.value = File.expand_path(value.to_s)
|
|
203
|
+
elsif existing_param.type.eql?('Complex')
|
|
204
|
+
if value.class.eql?(Hash) || value.class.eql?(Array)
|
|
205
|
+
existing_param.value = value
|
|
206
|
+
else
|
|
207
|
+
existing_param.value = YAML::load(StringIO.new(value.to_s))
|
|
208
|
+
end
|
|
209
|
+
else
|
|
210
|
+
set_value = existing_param.value_type_check(value)
|
|
211
|
+
existing_param.value = set_value
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# Define new parameter of type Integer.
|
|
216
|
+
def Params.integer(name, value, description)
|
|
217
|
+
raise_error_if_param_exists(name)
|
|
218
|
+
@params_data_base[name] = Param.new(name, value, 'Integer', description)
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
# Define new parameter of type Float.
|
|
222
|
+
def Params.float(name, value, description)
|
|
223
|
+
raise_error_if_param_exists(name)
|
|
224
|
+
@params_data_base[name] = Param.new(name, value, 'Float', description)
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
# Define new parameter of type String.
|
|
228
|
+
def Params.string(name, value, description)
|
|
229
|
+
raise_error_if_param_exists(name)
|
|
230
|
+
@params_data_base[name] = Param.new(name, value, 'String', description)
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
# Define new parameter of type path (the only difference with string is that the path expends '~' to
|
|
234
|
+
# full user directory).
|
|
235
|
+
def Params.path(name, value, description)
|
|
236
|
+
raise_error_if_param_exists(name)
|
|
237
|
+
value = File.expand_path(value) unless value.nil?
|
|
238
|
+
@params_data_base[name] = Param.new(name, value, 'Path', description)
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def Params.complex(name, value, description)
|
|
242
|
+
raise_error_if_param_exists(name)
|
|
243
|
+
@params_data_base[name] = Param.new(name, value, 'Complex', description)
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
# Define new parameter of type Boolean.
|
|
247
|
+
def Params.boolean(name, value, description)
|
|
248
|
+
raise_error_if_param_exists(name)
|
|
249
|
+
@params_data_base[name] = Param.new(name, value, 'Boolean', description)
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
# Initializes the project parameters.
|
|
253
|
+
# Precedence is: Defined params, file and command line is highest.
|
|
254
|
+
def Params.init(args)
|
|
255
|
+
#define default configuration file
|
|
256
|
+
Params['conf_file'] = "~/.bbfs/etc/config_#{executable_name}.yml"
|
|
257
|
+
|
|
258
|
+
@init_info_messages = []
|
|
259
|
+
@init_warning_messages = []
|
|
260
|
+
|
|
261
|
+
#parse command line argument and set configuration file if provided by user
|
|
262
|
+
results = parse_command_line_arguments(args)
|
|
263
|
+
if results['conf_file']
|
|
264
|
+
Params['conf_file'] = File.expand_path(results['conf_file'])
|
|
265
|
+
if !File.exist?(Params['conf_file']) or File.directory?(Params['conf_file'])
|
|
266
|
+
raise("Param:'conf_file' value:'#{Params['conf_file']}' is a file name which does not exist" +
|
|
267
|
+
" or a directory name")
|
|
268
|
+
end
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
Params['conf_file'] = File.expand_path(Params['conf_file'])
|
|
272
|
+
|
|
273
|
+
#load yml params if path is provided and exists
|
|
274
|
+
if File.exist?(Params['conf_file'])
|
|
275
|
+
@init_info_messages << "Loading parameters from configuration file:'#{Params['conf_file']}'"
|
|
276
|
+
if not read_yml_params(File.open(Params['conf_file'], 'r'))
|
|
277
|
+
raise("Bad configuration file #{Params['conf_file']}.")
|
|
278
|
+
end
|
|
279
|
+
else
|
|
280
|
+
@init_warning_messages << "Configuration file path:'#{Params['conf_file']}' does not exist. " + \
|
|
281
|
+
"Skipping loading file parameters."
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
#override command line argument
|
|
285
|
+
results.keys.each do |result_name|
|
|
286
|
+
override_param(result_name, results[result_name])
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
# Prints help and parameters if needed.
|
|
290
|
+
if @show_help_and_exit
|
|
291
|
+
# Print parameters + description and exit.
|
|
292
|
+
puts "Full list of parameters:"
|
|
293
|
+
Params.each do |name, param|
|
|
294
|
+
puts "--#{name}, #{param.type}, default:#{param.value}\n\t#{param.desc}"
|
|
295
|
+
end
|
|
296
|
+
exit
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
# Add parameters to log init messages (used by Log.init if param:print_params_to_stdout is true)
|
|
300
|
+
@init_info_messages << 'Initialized executable parameters:'
|
|
301
|
+
@init_info_messages << '---------------------------------'
|
|
302
|
+
counter=0
|
|
303
|
+
@params_data_base.values.each do |param|
|
|
304
|
+
counter += 1
|
|
305
|
+
@init_info_messages << "Param ##{counter}: #{param.name}=#{param.value}"
|
|
306
|
+
end
|
|
307
|
+
@init_info_messages << '---------------------------------'
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
# Load yml params and override default values.
|
|
311
|
+
# raise exception if a loaded yml param does not exist. or if types mismatch occurs.
|
|
312
|
+
def Params.read_yml_params(yml_input_io)
|
|
313
|
+
proj_params = YAML::load(yml_input_io)
|
|
314
|
+
return false unless proj_params.is_a?(Hash)
|
|
315
|
+
proj_params.keys.each do |param_name|
|
|
316
|
+
override_param(param_name, proj_params[param_name])
|
|
317
|
+
end
|
|
318
|
+
true
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
# Parse command line arguments
|
|
322
|
+
def Params.parse_command_line_arguments(args)
|
|
323
|
+
results = Hash.new # Hash to store parsing results.
|
|
324
|
+
options = Hash.new # Hash of parsing options from Params.
|
|
325
|
+
|
|
326
|
+
# Define options switch for parsing
|
|
327
|
+
# Define List of options see example on
|
|
328
|
+
# http://ruby.about.com/od/advancedruby/a/optionparser2.htm
|
|
329
|
+
opts = OptionParser.new do |opts|
|
|
330
|
+
@params_data_base.values.each do |param|
|
|
331
|
+
tmp_name_long = "--#{param.name} #{param.name.upcase}" # Define a command with single mandatory parameter
|
|
332
|
+
tmp_value = param.desc + " Default value:" + param.value.to_s # Description and Default value
|
|
333
|
+
|
|
334
|
+
# Define type of the mandatory value
|
|
335
|
+
# It can be integer, float or String(for all other types).
|
|
336
|
+
case(param.type)
|
|
337
|
+
when 'Integer' then value_type = Integer
|
|
338
|
+
when 'Float' then value_type = Float
|
|
339
|
+
else value_type = String
|
|
340
|
+
end
|
|
341
|
+
# Switches definition - according to what
|
|
342
|
+
# was pre-defined in the Params
|
|
343
|
+
opts.on(tmp_name_long, value_type, tmp_value) do |result|
|
|
344
|
+
if result.to_s.upcase.eql? 'TRUE'
|
|
345
|
+
results[param.name] = true
|
|
346
|
+
elsif result.to_s.upcase.eql? 'FALSE'
|
|
347
|
+
results[param.name] = false
|
|
348
|
+
else
|
|
349
|
+
results[param.name] = result
|
|
350
|
+
end
|
|
351
|
+
end
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
# Define introduction text for help command
|
|
355
|
+
opts.banner =
|
|
356
|
+
"Usage: content_serve [options] or \n" +
|
|
357
|
+
" : backup_server [options] \n\n" +
|
|
358
|
+
"Description: This application for backuping files and folders\n" +
|
|
359
|
+
"There is two application: \n" +
|
|
360
|
+
"backup_server is server run on machine where files is backuped,\n" +
|
|
361
|
+
"content_server is application that run on machine from where files is copied.\n\n" +
|
|
362
|
+
"Before run applications:" +
|
|
363
|
+
"Before running backup_server and content server you need to prepare two configuration files\n" +
|
|
364
|
+
"Create configuration file for content server which should be located at ~/.bbfs/etc/file_monitoring.yml\n" +
|
|
365
|
+
"the content of the file is:
|
|
366
|
+
------- begin of file_monitoring.yml --------
|
|
367
|
+
paths:
|
|
368
|
+
- path: ~/.bbfs/test_files # <=== replace with your local dir.
|
|
369
|
+
scan_period: 1
|
|
370
|
+
stable_state: 5
|
|
371
|
+
------- end of file_monitoring.yml --------\n" +
|
|
372
|
+
"Create configuration file for backup server which should be located at \n" +
|
|
373
|
+
"~/.bbfs/etc/backup_file_monitoring.yml\n" +
|
|
374
|
+
"File content:
|
|
375
|
+
------- begin of backup_file_monitoring.yml --------
|
|
376
|
+
paths:
|
|
377
|
+
- path: ~/.bbfs/backup_data # <=== replace with your local dir.
|
|
378
|
+
scan_period: 1
|
|
379
|
+
stable_state: 5
|
|
380
|
+
------- end of backup_file_monitoring.yml --------\n\n" +
|
|
381
|
+
"Explanation about file_monitoring.yml and backup_file_monitoring.yml configuration files:
|
|
382
|
+
|
|
383
|
+
\"path:\" - say to program which folder to scan recursively in order to find new/changed files and folders.
|
|
384
|
+
\"scan_period:\" - how much time in seconds passed before two consecutive scans for files and directories.
|
|
385
|
+
\"stable_state:\" - how many scan_period passed until the file is considered stable.\n\n" +
|
|
386
|
+
"List of options:"
|
|
387
|
+
|
|
388
|
+
|
|
389
|
+
# Define help command for available options
|
|
390
|
+
# executing --help will printout all pre-defined switch options
|
|
391
|
+
opts.on_tail("-h", "--help", "Show this message") do
|
|
392
|
+
@show_help_and_exit = true
|
|
393
|
+
end
|
|
394
|
+
|
|
395
|
+
opts.parse(args) # Parse command line
|
|
396
|
+
end
|
|
397
|
+
return results
|
|
398
|
+
end # end of Parse function
|
|
399
|
+
|
|
400
|
+
def Params.to_simple_hash
|
|
401
|
+
@params_data_base.map { |param|
|
|
402
|
+
param.value
|
|
403
|
+
}
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
#Auxiliary method to retrieve the executable name
|
|
407
|
+
def Params.executable_name
|
|
408
|
+
/([a-zA-Z0-9\-_\.]+):\d+/ =~ caller[caller.size-1]
|
|
409
|
+
return $1
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
Params.path('conf_file', nil, 'Configuration file path.')
|
|
413
|
+
Params.boolean('print_params_to_stdout', false, 'print_params_to_stdout or not during Params.init')
|
|
414
|
+
|
|
415
|
+
private_class_method :parse_command_line_arguments, \
|
|
416
|
+
:raise_error_if_param_exists, :raise_error_if_param_does_not_exist, \
|
|
417
|
+
:read_yml_params, :override_param, :executable_name
|
|
418
|
+
end
|
|
419
|
+
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
require 'thread'
|
|
2
|
+
|
|
3
|
+
require 'log'
|
|
4
|
+
require 'params'
|
|
5
|
+
|
|
6
|
+
require 'process_monitoring/send_email'
|
|
7
|
+
|
|
8
|
+
# This module purpose it to alert the user on different behaviour such as no space left
|
|
9
|
+
# or other error cases. The module will send email to the user to notify him on those cases.
|
|
10
|
+
module Monitoring
|
|
11
|
+
Params.float('monitoring_sleep_time_in_seconds', 10,
|
|
12
|
+
'Represents the monitoring sleeping time in seconds to check data')
|
|
13
|
+
Params.float('send_email_duration_4_monitoring_state', 60*60, # Once per hour.
|
|
14
|
+
'Represents the duration in seconds to send email monitoring state')
|
|
15
|
+
|
|
16
|
+
# Username and Password for gmail account to send monitoting emails.
|
|
17
|
+
Params.string('gmail_username', nil, 'Backup server gmail username.')
|
|
18
|
+
Params.string('gmail_password', nil, 'Backup server gmail password.')
|
|
19
|
+
|
|
20
|
+
class Monitoring
|
|
21
|
+
attr_reader :thread
|
|
22
|
+
def initialize(process_variables)
|
|
23
|
+
@thread = 'dummy'
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
=begin
|
|
27
|
+
class Monitoring < Log::Consumer
|
|
28
|
+
attr_reader :thread
|
|
29
|
+
def initialize(process_variables)
|
|
30
|
+
super(false)
|
|
31
|
+
@passed_time_dur = 0
|
|
32
|
+
@process_variables = process_variables
|
|
33
|
+
@thread = Thread.new do
|
|
34
|
+
loop do
|
|
35
|
+
Log.debug3 'Sleeping in process monitoring.'
|
|
36
|
+
sleep(Params['monitoring_sleep_time_in_seconds'])
|
|
37
|
+
Log.debug3 'Awake in process monitoring.'
|
|
38
|
+
@passed_time_dur += Params['monitoring_sleep_time_in_seconds']
|
|
39
|
+
Log.debug3 'handle_logs in process monitoring.'
|
|
40
|
+
handle_logs()
|
|
41
|
+
Log.debug3 'handle_monitoring_state in process monitoring.'
|
|
42
|
+
handle_monitoring_state()
|
|
43
|
+
@process_variables.inc('monitoring_loop_count')
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
# For debug purposes.
|
|
47
|
+
@thread.abort_on_exception = true
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
# To keep thread safe state all methods should be private and executed only from @thread
|
|
52
|
+
def send_email(subject, body)
|
|
53
|
+
SendEmail.send_email({
|
|
54
|
+
:to => Params['gmail_username'],
|
|
55
|
+
:from => Params['gmail_username'],
|
|
56
|
+
:password => Params['gmail_password'],
|
|
57
|
+
:body => body,
|
|
58
|
+
:subject => subject,
|
|
59
|
+
})
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Override logs consumer handler.
|
|
63
|
+
def handle_logs
|
|
64
|
+
while log_msg = @consumer_queue.pop(non_block=true) do
|
|
65
|
+
send_log_email(log_msg) if Log.is_error(log_msg)
|
|
66
|
+
end rescue ThreadError # Rescue when queue is empty.
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def handle_monitoring_state
|
|
70
|
+
if @passed_time_dur > Params['send_email_duration_4_monitoring_state']
|
|
71
|
+
send_email('BBFS Current Monitoring State notification', get_monitoring_state_body())
|
|
72
|
+
@passed_time_dur = 0
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def get_monitoring_state_body
|
|
77
|
+
# TODO(slava): Implement the following function.
|
|
78
|
+
# MonitoringInfo::MonitoringInfo.get_html(@process_variables)
|
|
79
|
+
"server_name: #{@process_variables.get('server_name')}\n" +
|
|
80
|
+
"num_files_received: #{@process_variables.get('num_files_received')}\n" +
|
|
81
|
+
"monitoring_loop_count: #{@process_variables.get('monitoring_loop_count')}"
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
=end
|
|
85
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
require 'eventmachine'
|
|
2
|
+
require 'json'
|
|
3
|
+
require 'net/http'
|
|
4
|
+
require 'thin'
|
|
5
|
+
require 'sinatra'
|
|
6
|
+
|
|
7
|
+
require 'content_server/server'
|
|
8
|
+
require 'params'
|
|
9
|
+
|
|
10
|
+
# Set up event machine to exit on ctrl+c.
|
|
11
|
+
EventMachine.schedule do
|
|
12
|
+
trap("INT") do
|
|
13
|
+
puts "Caught SIGINT"
|
|
14
|
+
# EventMachine.stop # this is useless
|
|
15
|
+
exit # exit # this stops the EventMachine
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# This module export process info to http port, that way the user may access with the
|
|
20
|
+
# browser to the process to see what is happening inside, what is it's state and parameters.
|
|
21
|
+
module MonitoringInfo
|
|
22
|
+
|
|
23
|
+
Params.integer('process_monitoring_web_port', 5555,
|
|
24
|
+
'The port from which monitoring data will be served as http.')
|
|
25
|
+
|
|
26
|
+
class MonitoringInfo
|
|
27
|
+
attr_reader :thread
|
|
28
|
+
|
|
29
|
+
def initialize()
|
|
30
|
+
@web_interface = Sinatra.new {
|
|
31
|
+
set :bind, '0.0.0.0'
|
|
32
|
+
get('/') { MonitoringInfo.get_json($process_vars.clone) }
|
|
33
|
+
}
|
|
34
|
+
@web_interface.set(:port, Params['process_monitoring_web_port'])
|
|
35
|
+
@thread = Thread.new do
|
|
36
|
+
@web_interface.run!
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def self.get_json(hash)
|
|
41
|
+
return '' if !hash.is_a?(Hash)
|
|
42
|
+
|
|
43
|
+
entries = []
|
|
44
|
+
hash.each do |key, value|
|
|
45
|
+
entries << "{#{key}:#{value}}"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
return entries.join(" , ")
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def self.get_html (hash, opts = {})
|
|
52
|
+
return if !hash.is_a?(Hash)
|
|
53
|
+
|
|
54
|
+
indent_level = opts.fetch(:indent_level) { 0 }
|
|
55
|
+
|
|
56
|
+
out = " " * indent_level + "<ul>\n"
|
|
57
|
+
|
|
58
|
+
hash.each do |key, value|
|
|
59
|
+
out += " " * (indent_level + 2) + "<li><strong>#{key}:</strong>"
|
|
60
|
+
|
|
61
|
+
if value.is_a?(Hash)
|
|
62
|
+
out += "\n" + get_html(value, :indent_level => indent_level + 2) + " " * (indent_level + 2) + "</li>\n"
|
|
63
|
+
else
|
|
64
|
+
out += " <span>#{value}</span></li>\n"
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
out += " " * indent_level + "</ul>\n"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def self.get_remote_monitoring_info(host, port)
|
|
72
|
+
begin
|
|
73
|
+
JSON.parse(Net::HTTP.get(URI("http://#{host}:#{port}/")))
|
|
74
|
+
rescue Errno::ECONNREFUSED => e
|
|
75
|
+
''
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require 'net/smtp'
|
|
2
|
+
|
|
3
|
+
require 'log'
|
|
4
|
+
require 'params'
|
|
5
|
+
|
|
6
|
+
module SendEmail
|
|
7
|
+
Params.boolean('enable_monitoring_emails', false, 'Whether to send emails for process monitoring events.')
|
|
8
|
+
|
|
9
|
+
#class SendEmail
|
|
10
|
+
def SendEmail.send_email(opts={})
|
|
11
|
+
opts[:to] ||= '' # Required.
|
|
12
|
+
opts[:from] ||= '' # Required.
|
|
13
|
+
opts[:from_alias] ||= 'BBFS Monitoring'
|
|
14
|
+
opts[:subject] ||= 'BBFS Notification subject'
|
|
15
|
+
opts[:body] ||= 'BBFS Body'
|
|
16
|
+
opts[:password] ||= '' # Required.
|
|
17
|
+
|
|
18
|
+
msg = "From: #{opts[:from_alias]} <#{opts[:from]}>\n" \
|
|
19
|
+
"To: <#{opts[:to]}>\n" \
|
|
20
|
+
"Subject: #{opts[:subject]}\n" \
|
|
21
|
+
"#{opts[:body]}"
|
|
22
|
+
|
|
23
|
+
email_log_message = "Send actual email: #{Params['enable_monitoring_emails']}.\n" \
|
|
24
|
+
"to: #{opts[:to]}\n" \
|
|
25
|
+
"msg:#{msg}"
|
|
26
|
+
if Params['enable_monitoring_emails']
|
|
27
|
+
Log.debug1(email_log_message)
|
|
28
|
+
smtp = Net::SMTP.new('smtp.gmail.com', 587)
|
|
29
|
+
smtp.enable_starttls
|
|
30
|
+
smtp.start('bbfs.com', opts[:from], opts[:password], :login) do
|
|
31
|
+
smtp.send_message(msg, opts[:from], opts[:to])
|
|
32
|
+
end
|
|
33
|
+
else
|
|
34
|
+
Log.info(email_log_message)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
#end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Simple thread safe hash.
|
|
2
|
+
module ThreadSafeHash
|
|
3
|
+
class ThreadSafeHash
|
|
4
|
+
def initialize()
|
|
5
|
+
@hash_data = Hash.new()
|
|
6
|
+
@mutex = Mutex.new
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def inc(key)
|
|
10
|
+
@mutex.synchronize do
|
|
11
|
+
value = @hash_data[key]
|
|
12
|
+
if value.nil?
|
|
13
|
+
@hash_data[key] = 1
|
|
14
|
+
else
|
|
15
|
+
@hash_data[key] = value + 1
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def dec(key)
|
|
21
|
+
@mutex.synchronize do
|
|
22
|
+
value = @hash_data[key]
|
|
23
|
+
if value.nil?
|
|
24
|
+
@hash_data[key] = -1
|
|
25
|
+
else
|
|
26
|
+
@hash_data[key] = value - 1
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def get(key)
|
|
32
|
+
@mutex.synchronize do
|
|
33
|
+
@hash_data[key]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def set(key, value)
|
|
38
|
+
@mutex.synchronize do
|
|
39
|
+
@hash_data[key] = value
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def clone
|
|
44
|
+
@mutex.synchronize do
|
|
45
|
+
@hash_data.clone
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
class ThreadSafeHashMonitored < ThreadSafeHash
|
|
51
|
+
def initialize(monitored)
|
|
52
|
+
super()
|
|
53
|
+
@monitored = monitored
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def inc(key)
|
|
57
|
+
super if @monitored
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def dec(key)
|
|
61
|
+
super if @monitored
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def get(key)
|
|
65
|
+
super if @monitored
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def set(key, value)
|
|
69
|
+
super if @monitored
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def clone
|
|
73
|
+
super if @monitored
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|