content_server 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (137) hide show
  1. data/bin/backup_server +8 -20
  2. data/bin/content_server +8 -20
  3. data/bin/testing_memory +60 -0
  4. data/bin/testing_server +57 -0
  5. data/ext/run_in_background/mkrf_conf.rb +34 -0
  6. data/lib/content_data/content_data.rb +613 -0
  7. data/lib/content_data/version.rb +3 -0
  8. data/lib/content_data.rb +6 -0
  9. data/lib/content_server/backup_server.rb +65 -86
  10. data/lib/content_server/content_server.rb +47 -77
  11. data/lib/content_server/file_streamer.rb +27 -33
  12. data/lib/content_server/queue_copy.rb +154 -49
  13. data/lib/content_server/queue_indexer.rb +19 -11
  14. data/lib/content_server/remote_content.rb +41 -23
  15. data/lib/content_server/server.rb +91 -0
  16. data/lib/content_server/version.rb +1 -1
  17. data/lib/content_server.rb +0 -15
  18. data/lib/email/email.rb +87 -0
  19. data/lib/email/version.rb +3 -0
  20. data/lib/email.rb +4 -0
  21. data/lib/file_copy/copy.rb +68 -0
  22. data/lib/file_copy/version.rb +4 -0
  23. data/lib/file_copy.rb +4 -0
  24. data/lib/file_indexing/index_agent.rb +170 -0
  25. data/lib/file_indexing/indexer_patterns.rb +72 -0
  26. data/lib/file_indexing/version.rb +3 -0
  27. data/lib/file_indexing.rb +9 -0
  28. data/lib/file_monitoring/file_monitoring.rb +105 -0
  29. data/lib/file_monitoring/monitor_path.rb +304 -0
  30. data/lib/file_monitoring/version.rb +3 -0
  31. data/lib/file_monitoring.rb +29 -0
  32. data/lib/file_utils/file_generator/README +97 -0
  33. data/lib/file_utils/file_generator/file_generator.rb +156 -0
  34. data/lib/file_utils/file_utils.rb +260 -0
  35. data/lib/file_utils/version.rb +3 -0
  36. data/lib/file_utils.rb +4 -0
  37. data/lib/log/version.rb +3 -0
  38. data/lib/log.rb +188 -0
  39. data/lib/networking/tcp.rb +213 -0
  40. data/lib/networking/version.rb +3 -0
  41. data/lib/networking.rb +4 -0
  42. data/lib/params/version.rb +3 -0
  43. data/lib/params.rb +419 -0
  44. data/lib/process_monitoring/monitoring.rb +85 -0
  45. data/lib/process_monitoring/monitoring_info.rb +79 -0
  46. data/lib/process_monitoring/send_email.rb +40 -0
  47. data/lib/process_monitoring/thread_safe_hash.rb +77 -0
  48. data/lib/process_monitoring/version.rb +3 -0
  49. data/lib/process_monitoring.rb +6 -0
  50. data/lib/run_in_background/version.rb +3 -0
  51. data/lib/run_in_background.rb +432 -0
  52. data/lib/testing_memory/testing_memory.rb +187 -0
  53. data/lib/testing_server/testing_server.rb +236 -0
  54. data/lib/testing_server/version.rb +3 -0
  55. data/lib/testing_server.rb +12 -0
  56. data/lib/validations/index_validations.rb +106 -0
  57. data/lib/validations/version.rb +3 -0
  58. data/lib/validations.rb +4 -0
  59. data/spec/content_data/validations_spec.rb +113 -0
  60. data/spec/file_copy/copy_spec.rb +54 -0
  61. data/spec/file_indexing/index_agent_spec.rb +53 -0
  62. data/spec/networking/tcp_spec.rb +95 -0
  63. data/spec/validations/index_validations_spec.rb +77 -0
  64. data/test/content_data/content_data_test.rb +290 -0
  65. data/test/file_generator/file_generator_spec.rb +84 -0
  66. data/test/file_indexing/index_agent_test/New.txt +0 -0
  67. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/bin/libexslt.dll +0 -0
  68. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/bin/libxslt.dll +0 -0
  69. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/bin/xsltproc.exe +0 -0
  70. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libexslt/exslt.h +102 -0
  71. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libexslt/exsltconfig.h +73 -0
  72. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libexslt/exsltexports.h +140 -0
  73. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libexslt/libexslt.h +29 -0
  74. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/attributes.h +38 -0
  75. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/documents.h +93 -0
  76. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/extensions.h +262 -0
  77. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/extra.h +80 -0
  78. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/functions.h +78 -0
  79. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/imports.h +75 -0
  80. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/keys.h +53 -0
  81. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/libxslt.h +30 -0
  82. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/namespaces.h +68 -0
  83. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/numbersInternals.h +69 -0
  84. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/pattern.h +81 -0
  85. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/preproc.h +43 -0
  86. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/security.h +104 -0
  87. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/templates.h +77 -0
  88. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/transform.h +207 -0
  89. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/trio.h +216 -0
  90. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/triodef.h +220 -0
  91. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/variables.h +91 -0
  92. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/win32config.h +101 -0
  93. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xslt.h +103 -0
  94. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xsltInternals.h +1967 -0
  95. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xsltconfig.h +172 -0
  96. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xsltexports.h +142 -0
  97. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xsltlocale.h +57 -0
  98. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xsltutils.h +309 -0
  99. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xsltwin32config.h +105 -0
  100. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/lib/libexslt.lib +0 -0
  101. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/lib/libexslt_a.lib +0 -0
  102. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/lib/libxslt.lib +0 -0
  103. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/lib/libxslt_a.lib +0 -0
  104. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/readme.txt +22 -0
  105. data/test/file_indexing/index_agent_test/patterns.input +3 -0
  106. data/test/file_indexing/index_agent_test.rb +51 -0
  107. data/test/file_monitoring/file_monitoring_test/conf.yml +4 -0
  108. data/test/file_monitoring/file_monitoring_test/conf_win32.yml +5 -0
  109. data/test/file_monitoring/file_monitoring_test/log +56 -0
  110. data/test/file_monitoring/file_monitoring_test.rb +0 -0
  111. data/test/file_monitoring/monitor_path_test/dir1000/test_file.1000 +1000 -0
  112. data/test/file_monitoring/monitor_path_test/dir1000/test_file.1000.0 +1000 -0
  113. data/test/file_monitoring/monitor_path_test/dir1000/test_file.1000.1 +1000 -0
  114. data/test/file_monitoring/monitor_path_test/dir1500/test_file.1500 +1500 -0
  115. data/test/file_monitoring/monitor_path_test/dir1500/test_file.1500.0 +1500 -0
  116. data/test/file_monitoring/monitor_path_test/dir1500/test_file.1500.1 +1500 -0
  117. data/test/file_monitoring/monitor_path_test/test_file.500 +500 -0
  118. data/test/file_monitoring/monitor_path_test/test_file.500.0 +500 -0
  119. data/test/file_monitoring/monitor_path_test/test_file.500.1 +500 -0
  120. data/test/file_monitoring/monitor_path_test.rb +153 -0
  121. data/test/file_utils/fileutil_mksymlink_test/dir1000/dir1500/test_file.1500 +1500 -0
  122. data/test/file_utils/fileutil_mksymlink_test/dir1000/dir1500/test_file.1500.0 +1500 -0
  123. data/test/file_utils/fileutil_mksymlink_test/dir1000/dir1500/test_file.1500.1 +1500 -0
  124. data/test/file_utils/fileutil_mksymlink_test/dir1000/test_file.1000 +1000 -0
  125. data/test/file_utils/fileutil_mksymlink_test/dir1000/test_file.1000.0 +1000 -0
  126. data/test/file_utils/fileutil_mksymlink_test/dir1000/test_file.1000.1 +1000 -0
  127. data/test/file_utils/fileutil_mksymlink_test/test_file.500 +500 -0
  128. data/test/file_utils/fileutil_mksymlink_test/test_file.500.0 +500 -0
  129. data/test/file_utils/fileutil_mksymlink_test/test_file.500.1 +500 -0
  130. data/test/file_utils/fileutil_mksymlink_test.rb +125 -0
  131. data/test/file_utils/time_modification_test.rb +132 -0
  132. data/test/params/params_spec.rb +280 -0
  133. data/test/params/params_test.rb +43 -0
  134. data/test/run_in_background/run_in_background_test.rb +122 -0
  135. data/test/run_in_background/test_app +57 -0
  136. metadata +272 -132
  137. data/lib/content_server/globals.rb +0 -10
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
+