content_server 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (137) hide show
  1. data/bin/backup_server +8 -20
  2. data/bin/content_server +8 -20
  3. data/bin/testing_memory +60 -0
  4. data/bin/testing_server +57 -0
  5. data/ext/run_in_background/mkrf_conf.rb +34 -0
  6. data/lib/content_data/content_data.rb +613 -0
  7. data/lib/content_data/version.rb +3 -0
  8. data/lib/content_data.rb +6 -0
  9. data/lib/content_server/backup_server.rb +65 -86
  10. data/lib/content_server/content_server.rb +47 -77
  11. data/lib/content_server/file_streamer.rb +27 -33
  12. data/lib/content_server/queue_copy.rb +154 -49
  13. data/lib/content_server/queue_indexer.rb +19 -11
  14. data/lib/content_server/remote_content.rb +41 -23
  15. data/lib/content_server/server.rb +91 -0
  16. data/lib/content_server/version.rb +1 -1
  17. data/lib/content_server.rb +0 -15
  18. data/lib/email/email.rb +87 -0
  19. data/lib/email/version.rb +3 -0
  20. data/lib/email.rb +4 -0
  21. data/lib/file_copy/copy.rb +68 -0
  22. data/lib/file_copy/version.rb +4 -0
  23. data/lib/file_copy.rb +4 -0
  24. data/lib/file_indexing/index_agent.rb +170 -0
  25. data/lib/file_indexing/indexer_patterns.rb +72 -0
  26. data/lib/file_indexing/version.rb +3 -0
  27. data/lib/file_indexing.rb +9 -0
  28. data/lib/file_monitoring/file_monitoring.rb +105 -0
  29. data/lib/file_monitoring/monitor_path.rb +304 -0
  30. data/lib/file_monitoring/version.rb +3 -0
  31. data/lib/file_monitoring.rb +29 -0
  32. data/lib/file_utils/file_generator/README +97 -0
  33. data/lib/file_utils/file_generator/file_generator.rb +156 -0
  34. data/lib/file_utils/file_utils.rb +260 -0
  35. data/lib/file_utils/version.rb +3 -0
  36. data/lib/file_utils.rb +4 -0
  37. data/lib/log/version.rb +3 -0
  38. data/lib/log.rb +188 -0
  39. data/lib/networking/tcp.rb +213 -0
  40. data/lib/networking/version.rb +3 -0
  41. data/lib/networking.rb +4 -0
  42. data/lib/params/version.rb +3 -0
  43. data/lib/params.rb +419 -0
  44. data/lib/process_monitoring/monitoring.rb +85 -0
  45. data/lib/process_monitoring/monitoring_info.rb +79 -0
  46. data/lib/process_monitoring/send_email.rb +40 -0
  47. data/lib/process_monitoring/thread_safe_hash.rb +77 -0
  48. data/lib/process_monitoring/version.rb +3 -0
  49. data/lib/process_monitoring.rb +6 -0
  50. data/lib/run_in_background/version.rb +3 -0
  51. data/lib/run_in_background.rb +432 -0
  52. data/lib/testing_memory/testing_memory.rb +187 -0
  53. data/lib/testing_server/testing_server.rb +236 -0
  54. data/lib/testing_server/version.rb +3 -0
  55. data/lib/testing_server.rb +12 -0
  56. data/lib/validations/index_validations.rb +106 -0
  57. data/lib/validations/version.rb +3 -0
  58. data/lib/validations.rb +4 -0
  59. data/spec/content_data/validations_spec.rb +113 -0
  60. data/spec/file_copy/copy_spec.rb +54 -0
  61. data/spec/file_indexing/index_agent_spec.rb +53 -0
  62. data/spec/networking/tcp_spec.rb +95 -0
  63. data/spec/validations/index_validations_spec.rb +77 -0
  64. data/test/content_data/content_data_test.rb +290 -0
  65. data/test/file_generator/file_generator_spec.rb +84 -0
  66. data/test/file_indexing/index_agent_test/New.txt +0 -0
  67. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/bin/libexslt.dll +0 -0
  68. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/bin/libxslt.dll +0 -0
  69. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/bin/xsltproc.exe +0 -0
  70. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libexslt/exslt.h +102 -0
  71. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libexslt/exsltconfig.h +73 -0
  72. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libexslt/exsltexports.h +140 -0
  73. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libexslt/libexslt.h +29 -0
  74. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/attributes.h +38 -0
  75. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/documents.h +93 -0
  76. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/extensions.h +262 -0
  77. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/extra.h +80 -0
  78. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/functions.h +78 -0
  79. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/imports.h +75 -0
  80. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/keys.h +53 -0
  81. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/libxslt.h +30 -0
  82. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/namespaces.h +68 -0
  83. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/numbersInternals.h +69 -0
  84. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/pattern.h +81 -0
  85. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/preproc.h +43 -0
  86. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/security.h +104 -0
  87. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/templates.h +77 -0
  88. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/transform.h +207 -0
  89. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/trio.h +216 -0
  90. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/triodef.h +220 -0
  91. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/variables.h +91 -0
  92. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/win32config.h +101 -0
  93. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xslt.h +103 -0
  94. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xsltInternals.h +1967 -0
  95. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xsltconfig.h +172 -0
  96. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xsltexports.h +142 -0
  97. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xsltlocale.h +57 -0
  98. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xsltutils.h +309 -0
  99. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/include/libxslt/xsltwin32config.h +105 -0
  100. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/lib/libexslt.lib +0 -0
  101. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/lib/libexslt_a.lib +0 -0
  102. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/lib/libxslt.lib +0 -0
  103. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/lib/libxslt_a.lib +0 -0
  104. data/test/file_indexing/index_agent_test/libxslt-1.1.26.win32/readme.txt +22 -0
  105. data/test/file_indexing/index_agent_test/patterns.input +3 -0
  106. data/test/file_indexing/index_agent_test.rb +51 -0
  107. data/test/file_monitoring/file_monitoring_test/conf.yml +4 -0
  108. data/test/file_monitoring/file_monitoring_test/conf_win32.yml +5 -0
  109. data/test/file_monitoring/file_monitoring_test/log +56 -0
  110. data/test/file_monitoring/file_monitoring_test.rb +0 -0
  111. data/test/file_monitoring/monitor_path_test/dir1000/test_file.1000 +1000 -0
  112. data/test/file_monitoring/monitor_path_test/dir1000/test_file.1000.0 +1000 -0
  113. data/test/file_monitoring/monitor_path_test/dir1000/test_file.1000.1 +1000 -0
  114. data/test/file_monitoring/monitor_path_test/dir1500/test_file.1500 +1500 -0
  115. data/test/file_monitoring/monitor_path_test/dir1500/test_file.1500.0 +1500 -0
  116. data/test/file_monitoring/monitor_path_test/dir1500/test_file.1500.1 +1500 -0
  117. data/test/file_monitoring/monitor_path_test/test_file.500 +500 -0
  118. data/test/file_monitoring/monitor_path_test/test_file.500.0 +500 -0
  119. data/test/file_monitoring/monitor_path_test/test_file.500.1 +500 -0
  120. data/test/file_monitoring/monitor_path_test.rb +153 -0
  121. data/test/file_utils/fileutil_mksymlink_test/dir1000/dir1500/test_file.1500 +1500 -0
  122. data/test/file_utils/fileutil_mksymlink_test/dir1000/dir1500/test_file.1500.0 +1500 -0
  123. data/test/file_utils/fileutil_mksymlink_test/dir1000/dir1500/test_file.1500.1 +1500 -0
  124. data/test/file_utils/fileutil_mksymlink_test/dir1000/test_file.1000 +1000 -0
  125. data/test/file_utils/fileutil_mksymlink_test/dir1000/test_file.1000.0 +1000 -0
  126. data/test/file_utils/fileutil_mksymlink_test/dir1000/test_file.1000.1 +1000 -0
  127. data/test/file_utils/fileutil_mksymlink_test/test_file.500 +500 -0
  128. data/test/file_utils/fileutil_mksymlink_test/test_file.500.0 +500 -0
  129. data/test/file_utils/fileutil_mksymlink_test/test_file.500.1 +500 -0
  130. data/test/file_utils/fileutil_mksymlink_test.rb +125 -0
  131. data/test/file_utils/time_modification_test.rb +132 -0
  132. data/test/params/params_spec.rb +280 -0
  133. data/test/params/params_test.rb +43 -0
  134. data/test/run_in_background/run_in_background_test.rb +122 -0
  135. data/test/run_in_background/test_app +57 -0
  136. metadata +272 -132
  137. data/lib/content_server/globals.rb +0 -10
@@ -0,0 +1,3 @@
1
+ module ProcessMonitoring
2
+ VERSION = "1.1.0"
3
+ end
@@ -0,0 +1,6 @@
1
+ require 'process_monitoring/monitoring'
2
+ require 'process_monitoring/monitoring_info'
3
+ require 'process_monitoring/thread_safe_hash'
4
+
5
+ module ProcessMonitoring
6
+ end
@@ -0,0 +1,3 @@
1
+ module RunInBackground
2
+ VERSION = "1.1.0"
3
+ end
@@ -0,0 +1,432 @@
1
+ # Author: Genady Petelko (nukegluk@gmail.com)
2
+ # Description: The file contains implementation of 'RunInBackground' module.
3
+
4
+ require 'params'
5
+ require 'log'
6
+
7
+ # This library provides a basic cross-platform functionality to run arbitrary ruby scripts
8
+ # in background and control them. <br>Supported platforms: Windows, Linux, Mac
9
+ # NOTE UAC (User Account Control) should be disabled to use library on Windows 7:
10
+ # * Click on the Windows Icon
11
+ # * Click on the Control Panel
12
+ # * Type in UAC in the search box (up-right corner of your window)
13
+ # * Click on "Change User Account Control settings"
14
+ # * Drag the slider down to either "Notify me when programs try to make changes to my computer"
15
+ # or to disable it completely
16
+ # * Reboot your computer when you're ready
17
+ # == General Limitations:
18
+ # * Only ruby scripts can be run in background.
19
+ # * No multiple instances with the same name.
20
+ # == Notes:
21
+ # * Linux/Mac specific methods have _linux suffix
22
+ # * Windows specific methods have _windows suffix
23
+ # * While enhancing windows code, take care that paths are in windows format,
24
+ # <br>e.i. with "\\" file separator while ruby by default uses a "/"
25
+ # * Additional functionality such as restart, reload, etc. will be added on demand
26
+ # * Remains support to provide platform specific options for start.
27
+ # <br>For more information regarding such options
28
+ # see documentation for win32-sevice (Windows), daemons (Linux/Mac)
29
+ # == Linux Notes:
30
+ # * <tt>pid_dir</tt> parameter contains absolute path to directory where pid files will be stored.
31
+ # <br>If directory doesn't exists then it will be created.
32
+ # <br>User should have a read/write permissions to this location.
33
+ # <br>Default location: <tt>$HOME/.bbfs/pids</tt>
34
+ # * User should check that default pid directory is free from pid files of "killed" daemons.
35
+ # <br>It may happen, for example, when system finished in abnormal way then pid files were
36
+ # not deleted by daemons library.
37
+ # <br>In such case incorrect results can be received, for example for <tt>exists?</tt> method
38
+ # <br>One of the suggested methods can be before starting a daemon to check with <tt>exists?</tt>
39
+ # method whether daemon already exists and with <tt>running?</tt> method does it running.
40
+ module RunInBackground
41
+ Params.string('bg_command', nil, 'Server\'s command. Commands are: start, delete and nil for' \
42
+ ' not running in background.')
43
+ Params.string('service_name', File.basename($0), 'Background service name.')
44
+
45
+ # Maximal time in seconds to wait until OS will finish a requested operation,
46
+ # e.g. daemon start/delete.
47
+ TIMEOUT = 20
48
+
49
+ if RUBY_PLATFORM =~ /linux/ or RUBY_PLATFORM =~ /darwin/
50
+ begin
51
+ require 'daemons'
52
+ require 'fileutils'
53
+ rescue LoadError
54
+ require 'rubygems'
55
+ require 'daemons'
56
+ require 'fileutils'
57
+ end
58
+
59
+ OS = :LINUX
60
+ Params.string('pid_dir', File.expand_path(File.join(Dir.home, '.bbfs', 'pids')),
61
+ 'Absolute path to directory, where pid files will be stored. ' + \
62
+ 'User should have a read/write permissions to this location. ' + \
63
+ 'If absent then it will be created. ' + \
64
+ 'It\'s actual only for Linux/Mac. ' + \
65
+ 'For more information see documentation on daemons module. ' +\
66
+ 'Default location is: $HOME/.bbfs/pids')
67
+
68
+ if Dir.exists? Params['pid_dir']
69
+ unless File.directory? Params['pid_dir']
70
+ raise IOError.new("pid directory #{Params['pid_dir']} should be a directory")
71
+ end
72
+ unless File.readable?(Params['pid_dir']) && File.writable?(Params['pid_dir'])
73
+ raise IOError.new("you should have read/write permissions to pid dir: #{Params['pid_dir']}")
74
+ end
75
+ else
76
+ ::FileUtils.mkdir_p Params['pid_dir']
77
+ end
78
+ elsif RUBY_PLATFORM =~ /mingw/ or RUBY_PLATFORM =~ /ms/ or RUBY_PLATFORM =~ /win/
79
+ require 'rbconfig'
80
+ begin
81
+ require 'win32/service'
82
+ require 'win32/daemon'
83
+ rescue LoadError
84
+ require 'rubygems'
85
+ require 'win32/service'
86
+ require 'win32/daemon'
87
+ end
88
+ include Win32
89
+
90
+ OS = :WINDOWS
91
+ # Get ruby interpreter path. Need it to run ruby binary.
92
+ # <br>TODO check whether this code works with Windows Ruby Version Management (e.g. Pik)
93
+ RUBY_INTERPRETER_PATH = File.join(Config::CONFIG["bindir"],
94
+ Config::CONFIG["RUBY_INSTALL_NAME"] +
95
+ Config::CONFIG["EXEEXT"]).tr!('/','\\')
96
+
97
+ # Path has to be absolute cause Win32-Service demands it.
98
+ wrapper = File.join(File.dirname(__FILE__), "..", "bin", File.basename(__FILE__, ".rb"), "daemon_wrapper")
99
+ # Wrapper script, that can receive commands from Windows Service Control and run user script,
100
+ # <br> provided as it's argument
101
+ WRAPPER_SCRIPT = File.expand_path(wrapper).tr!('/','\\')
102
+ else
103
+ raise "Unsupported platform #{RUBY_PLATFORM}"
104
+ end
105
+
106
+ # Start a service/daemon.
107
+ # <br>It important to delete it after usage.
108
+ # ==== Arguments
109
+ # * <tt>binary_path</tt> - absolute path to the script that should be run in background
110
+ # NOTE for Linux script should be executable and with UNIX end-of-lines (LF).
111
+ # * <tt>binary_args</tt> - Array (not nil) of script's command line arguments
112
+ # * <tt>name</tt> - service/daemon name.
113
+ # NOTE should be unique
114
+ # * <tt>opts_specific</tt> - Hash of platform specific options (only for more specific usage)
115
+ # For more information regarding such options see documentation for
116
+ # win32-sevice (Windows), daemons (Linux/Mac)
117
+ # ==== Example (LINUX)
118
+ # <tt> RunInBackground.start "/home/user/test_app", [], "daemon_test", {:monitor => true}</tt>
119
+ def RunInBackground.start binary_path, binary_args, name, opts_specific = {}
120
+ Log.debug1("executable that should be run as daemon/service: #{binary_path}")
121
+ Log.debug1("arguments: #{binary_args}")
122
+ Log.debug1("specific options: #{opts_specific}")
123
+
124
+ if binary_path == nil or binary_args == nil or name == nil
125
+ Log.error("binary path, binary args, name arguments must be defined")
126
+ raise ArgumentError.new("binary path, binary args, name arguments must be defined")
127
+ end
128
+
129
+ if OS == :WINDOWS
130
+ new_binary_path = String.new(binary_path)
131
+ new_binary_args = Array.new(binary_args)
132
+ wrap_windows new_binary_path, new_binary_args
133
+ start_windows new_binary_path, new_binary_args, name, opts_specific
134
+ else # OS == LINUX
135
+ start_linux binary_path, binary_args, name, opts_specific
136
+ end
137
+
138
+ 0.upto(TIMEOUT) do
139
+ if exists?(name) && running?(name)
140
+ puts "daemon/service #{name} started\n"
141
+ Log.debug1("daemon/service #{name} started")
142
+ return
143
+ end
144
+ sleep 1
145
+ end
146
+ # if got here then something gone wrong and daemon/service wasn't started in timely manner
147
+ delete name if exists? name
148
+ Log.error("daemon/service #{name} wasn't started in timely manner")
149
+ Log.flush
150
+ raise "daemon/service #{name} wasn't started in timely manner"
151
+ end
152
+
153
+ def RunInBackground.start_linux binary_path, binary_args, name, opts = {}
154
+ unless File.executable? binary_path
155
+ raise ArgumentError.new("#{binary_path} is not executable.")
156
+ end
157
+
158
+ if opts.has_key? :dir
159
+ raise ArgumentError.new("No support for user-defined pid directories. See help")
160
+ end
161
+
162
+ opts[:app_name] = name
163
+ opts[:ARGV] = ['start']
164
+ (opts[:ARGV] << '--').concat(binary_args) if !binary_args.nil? && binary_args.size > 0
165
+ opts[:dir] = Params['pid_dir']
166
+ opts[:dir_mode] = :normal
167
+
168
+ Log.debug1("binary path: #{binary_path}")
169
+ Log.debug1("opts: #{opts}")
170
+
171
+ # Current process, that creates daemon, will transfer control to the Daemons library.
172
+ # So to continue working with current process, daemon creation initiated from separate process.
173
+ pid = fork do
174
+ Daemons.run binary_path, opts
175
+ end
176
+ Process.waitpid pid
177
+ end
178
+
179
+ def RunInBackground.start_windows binary_path, binary_args, name, opts = {}
180
+ raise ArgumentError.new("#{binary_path} doesn't exist'") unless File.exists? binary_path
181
+
182
+ # path that contains spaces must be escaped to be interpreted correctly
183
+ binary_path = %Q{"#{binary_path}"} if binary_path =~ / /
184
+ binary_path.tr!('/','\\')
185
+ # service should be run with the same load path as a current application
186
+ load_path = get_load_path
187
+ binary_args_str = binary_args.join ' '
188
+
189
+ opts[:binary_path_name] = \
190
+ "#{RUBY_INTERPRETER_PATH} #{load_path} #{binary_path} #{binary_args_str}"
191
+ # quotation marks must be escaped cause of ARGV parsing
192
+ opts[:binary_path_name] = opts[:binary_path_name].gsub '"', '"\\"'
193
+ opts[:service_name] = name
194
+ opts[:description] = name unless opts.has_key? :description
195
+ opts[:display_name] = name unless opts.has_key? :display_name
196
+ opts[:service_type] = Service::WIN32_OWN_PROCESS unless opts.has_key? :service_type
197
+ opts[:start_type] = Service::DEMAND_START unless opts.has_key? :start_type
198
+
199
+ # NOTE most of examples uses these dependencies. Meanwhile no explanations were found
200
+ opts[:dependencies] = ['W32Time','Schedule'] unless opts.has_key? :dependencies
201
+ # NOTE most of examples uses this option as defined beneath. The default is nil.
202
+ #opts[:load_order_group] = 'Network' unless opts.has_key? :load_order_group
203
+
204
+ Log.debug1("create service options: #{opts}")
205
+ Service.create(opts)
206
+ begin
207
+ Service.start(opts[:service_name])
208
+ rescue
209
+ Service.delete(opts[:service_name]) if Service.exists?(opts[:service_name])
210
+ raise
211
+ end
212
+ end
213
+
214
+ # Rerun current script in background.
215
+ # <br>Current process will be closed.
216
+ # <br>It suggested to remove from ARGV any command line arguments that point
217
+ # to run script in background, <br>otherwise an unexpexted result can be received
218
+ def RunInBackground.start! name, opts = {}
219
+ # $0 is the executable name.
220
+ start(File.expand_path($0), ARGV, name, opts)
221
+ Log.flush
222
+ exit!
223
+ end
224
+
225
+ # Run in background script that was written as Windows Service, i.e. can receive signals
226
+ # from Service Control.
227
+ # <br>The code that is run in this script should be an extension of Win32::Daemon class.
228
+ # <br>For more information see Win32::Daemon help and examples.
229
+ # <br>No need to wrap such a script.
230
+ def RunInBackground.start_win32service binary_path, binary_args, name, opts_specific = {}
231
+ Log.debug1("executable that should be run as service: #{binary_path}")
232
+ Log.debug1("arguments: #{binary_args}")
233
+ Log.debug1("specific options: #{opts_specific}")
234
+
235
+ if OS == :WINDOWS
236
+ start_windows binary_path, binary_args, name, opts_specific
237
+ else # OS == :LINUX
238
+ raise NotImplementedError.new("Unsupported method on #{OS}")
239
+ end
240
+ 0.upto(TIMEOUT) do
241
+ if exists?(name) && running?(name)
242
+ puts "windows service #{name} started\n"
243
+ Log.debug1("windows service #{name} started")
244
+ return
245
+ end
246
+ sleep 1
247
+ end
248
+ # if got here then something gone wrong and daemon/service wasn't started in timely manner
249
+ delete name if exists? name
250
+ Log.error("daemon/service #{name} wasn't started in timely manner")
251
+ Log.flush
252
+ raise "daemon/service #{name} wasn't started in timely manner"
253
+ end
254
+
255
+ # Wrap an arbitrary ruby script withing script that can be run as Windows Service.
256
+ # ==== Arguments
257
+ # * <tt>binary_path</tt> - absolute path of the script that should be run in background
258
+ # * <tt>binary_args</tt> - array (not nil) of scripts command line arguments
259
+ #
260
+ # NOTE binary_path and binary_args contents will be change
261
+ def RunInBackground.wrap_windows binary_path, binary_args
262
+ raise ArgumentError.new("#{binary_path} doesn't exists") unless File.exists? binary_path
263
+
264
+ # service should be run with the same load path as a current application
265
+ load_path = get_load_path
266
+ # path that contains spaces must be escaped to be interpreted correctly
267
+ binary_path = %Q{"#{binary_path}"} if binary_path =~ / /
268
+ binary_args.insert(0, RUBY_INTERPRETER_PATH, load_path, binary_path.tr('/','\\'))
269
+ binary_path.replace(WRAPPER_SCRIPT)
270
+ end
271
+
272
+ # NOTE if this method will become public then may be needed to change appropriately wrapper script
273
+ def RunInBackground.stop name
274
+ if not exists? name
275
+ raise ArgumentError.new("Daemon #{name} doesn't exists")
276
+ elsif OS == :WINDOWS
277
+ Service.stop(name)
278
+ else # OS == :LINUX
279
+ opts = {:app_name => name,
280
+ :ARGV => ['stop'],
281
+ :dir_mode => :normal,
282
+ :dir => Params['pid_dir']
283
+ }
284
+ # Current process, that creates daemon, will transfer control to the Daemons library.
285
+ # So to continue working with current process, daemon creation initiated from separate process.
286
+ # It looks that it holds only for start command
287
+ #pid = fork do
288
+ Daemons.run "", opts
289
+ #end
290
+ #Process.waitpid pid
291
+ end
292
+ end
293
+
294
+ # Delete service/daemon.
295
+ # <br>If running then stop and delete.
296
+ def RunInBackground.delete name
297
+ if not exists? name
298
+ raise ArgumentError.new("Daemon #{name} doesn't exists")
299
+ elsif running? name
300
+ stop name
301
+ end
302
+ if OS == :WINDOWS
303
+ Service.delete name
304
+ else # OS == :LINUX
305
+ opts = {:app_name => name,
306
+ :ARGV => ['zap'],
307
+ :dir_mode => :normal,
308
+ :dir => Params['pid_dir']
309
+ }
310
+ # Current process, that creates daemon, will transfer control to the Daemons library.
311
+ # So to continue working with current process, daemon creation initiated from separate process.
312
+ # It looks that it holds only for start command
313
+ #pid = fork do
314
+ Daemons.run "", opts
315
+ #end
316
+ #Process.waitpid pid
317
+ end
318
+ 0.upto(TIMEOUT) do
319
+ unless exists? name
320
+ puts "daemon/service #{name} deleted\n"
321
+ Log.debug1("daemon/service #{name} deleted")
322
+ return
323
+ end
324
+ sleep 1
325
+ end
326
+ # if got here then something gone wrong and daemon/service wasn't deleted in timely manner
327
+ Log.error("daemon/service #{name} wasn't deleted in timely manner")
328
+ Log.flush
329
+ raise "daemon/service #{name} wasn't deleted in timely manner"
330
+ end
331
+
332
+ def RunInBackground.exists? name
333
+ if name == nil
334
+ raise ArgumentError.new("service/daemon name argument must be defined")
335
+ elsif OS == :WINDOWS
336
+ Service.exists? name
337
+ else # OS == :LINUX
338
+ pid_files = Daemons::PidFile.find_files(Params['pid_dir'], name)
339
+ pid_files != nil && pid_files.size > 0
340
+ end
341
+ end
342
+
343
+ def RunInBackground.running? name
344
+ if not exists? name
345
+ raise ArgumentError.new("Daemon #{name} doesn't exists")
346
+ elsif OS == :WINDOWS
347
+ Service.status(name).current_state == 'running'
348
+ else # OS == :LINUX
349
+ Daemons::Pid.running? name
350
+ end
351
+ end
352
+
353
+ # Returns absolute standard form of the path.
354
+ # It includes path separators accepted on this OS
355
+ def RunInBackground.get_abs_std_path path
356
+ path = File.expand_path path
357
+ path = path.tr('/','\\') if OS == :WINDOWS
358
+ path
359
+ end
360
+
361
+ # Returns load path as it provided in command line.
362
+ def RunInBackground.get_load_path
363
+ load_path = Array.new
364
+ $:.each do |location|
365
+ load_path << %Q{-I"#{get_abs_std_path(location)}"}
366
+ end
367
+ load_path.join ' '
368
+ end
369
+
370
+ # Prepare ARGV so it can be provided as a command line arguments.
371
+ # Remove bg_command from ARGV to prevent infinite recursion.
372
+ def RunInBackground.prepare_argv
373
+ new_argv = Array.new
374
+ ARGV.each do |arg|
375
+ # For each argument try splitting to 'name'='value'
376
+ arg_arr = arg.split '='
377
+ # If no '=' is argument, just copy paste.
378
+ if arg_arr.size == 1
379
+ arg = "\"#{arg}\"" if arg =~ / /
380
+ new_argv << arg
381
+ # If it is a 'name'='value' argument add "" so the value can be passed as argument again.
382
+ elsif arg_arr.size == 2
383
+ # Skip bg_command flag (remove infinite recursion)!
384
+ if arg_arr[0] !~ /bg_command/
385
+ arg_arr[1] = "\"#{arg_arr[1]}\"" if arg_arr[1] =~ / /
386
+ new_argv << arg_arr.join('=')
387
+ end
388
+ else
389
+ Log.warning("ARGV argument #{arg} wasn't processed")
390
+ new_argv << arg
391
+ end
392
+ end
393
+ ARGV.clear
394
+ ARGV.concat new_argv
395
+ end
396
+
397
+ def RunInBackground.run &b
398
+ case Params['bg_command']
399
+ when nil
400
+ yield b
401
+ when 'start'
402
+ # To prevent service enter loop cause of background parameter
403
+ # all options that points to run in background must be disabled
404
+ # (for more information see documentation for RunInBackground::start!)
405
+ Params['bg_command'] = nil
406
+ RunInBackground.prepare_argv
407
+
408
+ begin
409
+ RunInBackground.start! Params['service_name']
410
+ rescue Exception => e
411
+ Log.error("Start service command failed: #{e.message}")
412
+ raise
413
+ end
414
+ when 'delete'
415
+ if RunInBackground.exists? Params['service_name']
416
+ RunInBackground.delete Params['service_name']
417
+ else
418
+ msg = "Can't delete. Service #{Params['service_name']} already deleted"
419
+ puts msg
420
+ Log.warning(msg)
421
+ end
422
+ else
423
+ msg = "Unsupported command #{Params['bg_command']}. Supported commands are: start, delete"
424
+ puts msg
425
+ Log.error(msg)
426
+ end
427
+ nil
428
+ end
429
+
430
+ private_class_method :start_linux, :start_windows, :wrap_windows, :stop, :get_abs_std_path, \
431
+ :get_load_path
432
+ end
@@ -0,0 +1,187 @@
1
+ require 'log4r'
2
+ require 'log'
3
+ require 'params'
4
+ require 'content_server'
5
+ require 'content_server/content_server' # specific content server impl
6
+ require 'content_server/backup_server' # specific backup server impl
7
+ require 'content_data'
8
+ require 'email'
9
+ require 'file_utils/file_generator/file_generator'
10
+
11
+ # Runs a memory test:
12
+ # 1. Run content server or backup server
13
+ # 2. Generate files.
14
+ # 3. Monitor files.
15
+ # 4. Index files.
16
+ # 5. Report memory of proces at different phases\times
17
+ # Examples:
18
+ # testing_server --conf_file=~/.bbfs/etc/backup_testing_memory.yml --server_to_test=backup
19
+ # testing_server --conf_file=~/.bbfs/etc/content_testing_memory.yml --server_to_test=content
20
+
21
+ module TestingMemory
22
+
23
+ Params.path('testing_log_path', nil, 'Testing server log path.')
24
+ Params.integer('memory_count_delay', 10, 'Memory report cycles in sec.')
25
+ Params.string('testing_title', 'Memory report', 'title to memory report')
26
+ Params.boolean('generate_files', true, 'if true, files will be generated.')
27
+
28
+ def init_log4r
29
+ #init log4r
30
+ log_path = Params['testing_log_path']
31
+ unless log_path
32
+ raise("pls specify testing log path through param:'testing_log_path'")
33
+ end
34
+ log_dir = File.dirname(log_path)
35
+ FileUtils.mkdir_p(log_dir) unless File.exists?(log_dir)
36
+
37
+ $testing_memory_log = Log4r::Logger.new 'BBFS testing server log'
38
+ $testing_memory_log.trace = true
39
+ formatter = Log4r::PatternFormatter.new(:pattern => "[%d] [%m]")
40
+ #file setup
41
+ file_config = {
42
+ "filename" => Params['testing_log_path'],
43
+ "trunc" => true
44
+ }
45
+ file_outputter = Log4r::FileOutputter.new("testing_log", file_config)
46
+ file_outputter.level = Log4r::INFO
47
+ file_outputter.formatter = formatter
48
+ $testing_memory_log.outputters << file_outputter
49
+ end
50
+
51
+ def run_content_memory_server
52
+ $testing_memory_active = true # this activates debug messages to console
53
+
54
+ Log.info('Testing server started')
55
+
56
+ #Init log
57
+ init_log4r
58
+ $testing_memory_log.info('Testing server started')
59
+
60
+ #create files
61
+ if Params['generate_files']
62
+ total_files = Params['total_created_directories']*Params['total_files_in_dir']
63
+ $testing_memory_log.info("Creating #{total_files} files")
64
+ fg = FileGenerator::FileGenerator.new
65
+ fg.run
66
+ $testing_memory_log.info('Finished creating files')
67
+ end
68
+
69
+
70
+ # run backup
71
+ Thread.new do
72
+ ContentServer.run_content_server
73
+ end
74
+
75
+ # run memory report cycles
76
+ check_memory_loop
77
+
78
+ raise("code should never reach here")
79
+ end
80
+
81
+ def run_backup_memory_server
82
+ $testing_memory_active = true # this activates debug messages to console
83
+
84
+ Log.info('Testing server started')
85
+
86
+ #Init log
87
+ init_log4r
88
+ $testing_memory_log.info('Testing server started')
89
+
90
+ #create files
91
+ if Params['generate_files']
92
+ total_files = Params['total_created_directories']*Params['total_files_in_dir']
93
+ $testing_memory_log.info("Creating #{total_files} files")
94
+ fg = FileGenerator::FileGenerator.new
95
+ fg.run
96
+ $testing_memory_log.info('Finished creating files')
97
+ end
98
+
99
+ # run backup
100
+ Thread.new do
101
+ ContentServer.run_backup_server
102
+ end
103
+
104
+ # run memory report cycles
105
+ check_memory_loop
106
+
107
+ raise("code should never reach here")
108
+ end
109
+
110
+ def check_memory_loop
111
+ start_time = Time.now
112
+ $testing_memory_log.info(Params['testing_title'])
113
+ total_files = Params['total_created_directories']*Params['total_files_in_dir']
114
+ $testing_memory_log.info("Start check all files:#{total_files} are indexed")
115
+ Params.get_init_info_messages.each { |msg|
116
+ $testing_memory_log.info(msg)
117
+ }
118
+ email_report = generate_mem_report
119
+
120
+ # memory loop
121
+ loop {
122
+ sleep(Params['memory_count_delay'])
123
+ email_report += generate_mem_report
124
+ email_report += "indexed files:#{$indexed_file_count}\n"
125
+ $testing_memory_log.info("indexed files:#{$indexed_file_count}")
126
+ puts "indexed files:#{$indexed_file_count}"
127
+ if total_files == $indexed_file_count
128
+ stop_time = Time.now
129
+ email_report += "\nAt this point all files are indexed. No mem changes should occur\n"
130
+ $testing_memory_log.info("Total indexing time = #{stop_time.to_i - start_time.to_i}[S]")
131
+ $testing_memory_log.info("\nAt this point all files are indexed. No mem changes should occur\n")
132
+ loop {
133
+ sleep(Params['memory_count_delay'])
134
+ email_report += generate_mem_report
135
+ }
136
+ #send_email("Final report:#{email_report}\nprocess memory:#{memory_of_process}\n")
137
+ end
138
+ }
139
+ end
140
+
141
+ def generate_mem_report
142
+ # Generate memory report
143
+ current_objects_counters = {}
144
+
145
+ count = ObjectSpace.each_object(String).count
146
+ current_objects_counters['String'] = count
147
+ count = ObjectSpace.each_object(ContentData::ContentData).count
148
+ current_objects_counters['ContentData'] = count
149
+ dir_count = ObjectSpace.each_object(FileMonitoring::DirStat).count
150
+ current_objects_counters['DirStat'] = dir_count
151
+ file_count = ObjectSpace.each_object(FileMonitoring::FileStat).count
152
+ current_objects_counters['FileStat'] = file_count-dir_count
153
+
154
+ # Generate report and update global counters
155
+ report = ""
156
+ current_objects_counters.each_key { |type|
157
+ report += "Type:#{type} count:#{current_objects_counters[type]} \n"
158
+ }
159
+ unless Gem::win_platform?
160
+ memory_of_process = `ps -o rss= -p #{Process.pid}`.to_i / 1000
161
+ else
162
+ memory_of_process = `tasklist /FI \"PID eq #{Process.pid}\" /NH /FO \"CSV\"`.split(',')[4]
163
+ end
164
+ final_report = "Time:#{Time.now}. Process memory:#{memory_of_process}[M]\nCount report:\n#{report}"
165
+ puts "Process memory:#{memory_of_process}[M]"
166
+ $testing_memory_log.info(final_report)
167
+ final_report
168
+ end
169
+
170
+ def send_email(report)
171
+
172
+ msg =<<EOF
173
+ #{report}
174
+ EOF
175
+ Email.send_email(Params['from_email'],
176
+ Params['from_email_password'],
177
+ Params['to_email'],
178
+ 'Memory server update',
179
+ msg)
180
+ end
181
+
182
+ module_function :run_content_memory_server, :run_backup_memory_server, :init_log4r, :send_email
183
+ module_function :check_memory_loop, :generate_mem_report
184
+
185
+ end # module TestingServer
186
+
187
+