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