mongrel_service 0.3.4-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,179 @@
1
+ '##################################################################
2
+ '#
3
+ '# mongrel_service: Win32 native implementation for mongrel
4
+ '# (using ServiceFB and FreeBASIC)
5
+ '#
6
+ '# Copyright (c) 2006 Multimedia systems
7
+ '# (c) and code by Luis Lavena
8
+ '#
9
+ '# mongrel_service (native) and mongrel_service gem_pluing are licensed
10
+ '# in the same terms as mongrel, please review the mongrel license at
11
+ '# http://mongrel.rubyforge.org/license.html
12
+ '#
13
+ '##################################################################
14
+
15
+ '##################################################################
16
+ '# Requirements:
17
+ '# - FreeBASIC 0.18
18
+ '#
19
+ '##################################################################
20
+
21
+ #include once "mongrel_service.bi"
22
+ #define DEBUG_LOG_FILE EXEPATH + "\mongrel_service.log"
23
+ #include once "_debug.bi"
24
+
25
+ namespace mongrel_service
26
+ constructor SingleMongrel()
27
+ dim redirect_file as string
28
+
29
+ with this.__service
30
+ .name = "single"
31
+ .description = "Mongrel Single Process service"
32
+
33
+ '# disabling shared process
34
+ .shared_process = FALSE
35
+
36
+ '# TODO: fix inheritance here
37
+ .onInit = @single_onInit
38
+ .onStart = @single_onStart
39
+ .onStop = @single_onStop
40
+ end with
41
+
42
+ with this.__console
43
+ redirect_file = EXEPATH + "\mongrel.log"
44
+ debug("redirecting to: " + redirect_file)
45
+ .redirect(ProcessStdBoth, redirect_file)
46
+ end with
47
+
48
+ '# TODO: fix inheritance here
49
+ single_mongrel_ref = @this
50
+ end constructor
51
+
52
+ destructor SingleMongrel()
53
+ '# TODO: fin inheritance here
54
+ end destructor
55
+
56
+ function single_onInit(byref self as ServiceProcess) as integer
57
+ dim result as integer
58
+ dim mongrel_cmd as string
59
+
60
+ debug("single_onInit()")
61
+
62
+ '# ruby.exe must be in the path, which we guess is already there.
63
+ '# because mongrel_service executable (.exe) is located in the same
64
+ '# folder than mongrel_rails ruby script, we complete the path with
65
+ '# EXEPATH + "\mongrel_rails" to make it work.
66
+ '# FIXED ruby installation outside PATH and inside folders with spaces
67
+ mongrel_cmd = !"\"" + EXEPATH + !"\\ruby.exe" + !"\" " + !"\"" + EXEPATH + !"\\mongrel_rails" + !"\"" + " start"
68
+
69
+ '# due lack of inheritance, we use single_mongrel_ref as pointer to
70
+ '# SingleMongrel instance. now we should call StillAlive
71
+ self.StillAlive()
72
+ if (len(self.commandline) > 0) then
73
+ '# assign the program
74
+ single_mongrel_ref->__console.filename = mongrel_cmd
75
+ single_mongrel_ref->__console.arguments = self.commandline
76
+
77
+ '# fix commandline, it currently contains params to be passed to
78
+ '# mongrel_rails, and not ruby.exe nor the script to be run.
79
+ self.commandline = mongrel_cmd + " " + self.commandline
80
+
81
+ '# now launch the child process
82
+ debug("starting child process with cmdline: " + self.commandline)
83
+ single_mongrel_ref->__child_pid = 0
84
+ if (single_mongrel_ref->__console.start() = true) then
85
+ single_mongrel_ref->__child_pid = single_mongrel_ref->__console.pid
86
+ end if
87
+ self.StillAlive()
88
+
89
+ '# check if pid is valid
90
+ if (single_mongrel_ref->__child_pid > 0) then
91
+ '# it worked
92
+ debug("child process pid: " + str(single_mongrel_ref->__child_pid))
93
+ result = not FALSE
94
+ end if
95
+ else
96
+ '# if no param, no service!
97
+ debug("no parameters was passed to this service!")
98
+ result = FALSE
99
+ end if
100
+
101
+ debug("single_onInit() done")
102
+ return result
103
+ end function
104
+
105
+ sub single_onStart(byref self as ServiceProcess)
106
+ debug("single_onStart()")
107
+
108
+ do while (self.state = Running) or (self.state = Paused)
109
+ '# instead of sitting idle here, we must monitor the pid
110
+ '# and re-spawn a new process if needed
111
+ if not (single_mongrel_ref->__console.running = true) then
112
+ '# check if we aren't terminating
113
+ if (self.state = Running) or (self.state = Paused) then
114
+ debug("child process terminated!, re-spawning a new one")
115
+
116
+ single_mongrel_ref->__child_pid = 0
117
+ if (single_mongrel_ref->__console.start() = true) then
118
+ single_mongrel_ref->__child_pid = single_mongrel_ref->__console.pid
119
+ end if
120
+
121
+ if (single_mongrel_ref->__child_pid > 0) then
122
+ debug("new child process pid: " + str(single_mongrel_ref->__child_pid))
123
+ end if
124
+ end if
125
+ end if
126
+
127
+ '# wait for 5 seconds
128
+ sleep 5000
129
+ loop
130
+
131
+ debug("single_onStart() done")
132
+ end sub
133
+
134
+ sub single_onStop(byref self as ServiceProcess)
135
+ debug("single_onStop()")
136
+
137
+ '# now terminates the child process
138
+ if not (single_mongrel_ref->__child_pid = 0) then
139
+ debug("trying to kill pid: " + str(single_mongrel_ref->__child_pid))
140
+ if not (single_mongrel_ref->__console.terminate() = true) then
141
+ debug("Terminate() reported a problem when terminating process " + str(single_mongrel_ref->__child_pid))
142
+ else
143
+ debug("child process terminated with success.")
144
+ single_mongrel_ref->__child_pid = 0
145
+ end if
146
+ end if
147
+
148
+ debug("single_onStop() done")
149
+ end sub
150
+
151
+ sub application()
152
+ dim simple as SingleMongrel
153
+ dim host as ServiceHost
154
+ dim ctrl as ServiceController = ServiceController("Mongrel Win32 Service", "version " + VERSION, _
155
+ "(c) 2006 The Mongrel development team.")
156
+
157
+ '# add SingleMongrel (service)
158
+ host.Add(simple.__service)
159
+ select case ctrl.RunMode()
160
+ '# call from Service Control Manager (SCM)
161
+ case RunAsService:
162
+ debug("ServiceHost RunAsService")
163
+ host.Run()
164
+
165
+ '# call from console, useful for debug purposes.
166
+ case RunAsConsole:
167
+ debug("ServiceController Console")
168
+ ctrl.Console()
169
+
170
+ case else:
171
+ ctrl.Banner()
172
+ print "mongrel_service is not designed to run form commandline,"
173
+ print "please use mongrel_rails service:: commands to create a win32 service."
174
+ end select
175
+ end sub
176
+ end namespace
177
+
178
+ '# MAIN: start native mongrel_service here
179
+ mongrel_service.application()
@@ -0,0 +1,61 @@
1
+ '##################################################################
2
+ '#
3
+ '# mongrel_service: Win32 native implementation for mongrel
4
+ '# (using ServiceFB and FreeBASIC)
5
+ '#
6
+ '# Copyright (c) 2006 Multimedia systems
7
+ '# (c) and code by Luis Lavena
8
+ '#
9
+ '# mongrel_service (native) and mongrel_service gem_pluing are licensed
10
+ '# in the same terms as mongrel, please review the mongrel license at
11
+ '# http://mongrel.rubyforge.org/license.html
12
+ '#
13
+ '##################################################################
14
+
15
+ '##################################################################
16
+ '# Requirements:
17
+ '# - FreeBASIC 0.18.
18
+ '#
19
+ '##################################################################
20
+
21
+ #define SERVICEFB_INCLUDE_UTILS
22
+ #include once "lib/ServiceFB/ServiceFB.bi"
23
+ #include once "console_process.bi"
24
+
25
+ '# use for debug versions
26
+ #if not defined(GEM_VERSION)
27
+ #define GEM_VERSION (debug mode)
28
+ #endif
29
+
30
+ '# preprocessor stringize
31
+ #define PPSTR(x) #x
32
+
33
+ namespace mongrel_service
34
+ const VERSION as string = PPSTR(GEM_VERSION)
35
+
36
+ '# namespace include
37
+ using fb.svc
38
+ using fb.svc.utils
39
+
40
+ declare function single_onInit(byref as ServiceProcess) as integer
41
+ declare sub single_onStart(byref as ServiceProcess)
42
+ declare sub single_onStop(byref as ServiceProcess)
43
+
44
+ '# SingleMongrel
45
+ type SingleMongrel
46
+ declare constructor()
47
+ declare destructor()
48
+
49
+ '# TODO: replace for inheritance here
50
+ 'declare function onInit() as integer
51
+ 'declare sub onStart()
52
+ 'declare sub onStop()
53
+
54
+ __service as ServiceProcess
55
+ __console as ConsoleProcess
56
+ __child_pid as uinteger
57
+ end type
58
+
59
+ '# TODO: replace with inheritance here
60
+ dim shared single_mongrel_ref as SingleMongrel ptr
61
+ end namespace
@@ -0,0 +1,2 @@
1
+ ---
2
+ :debug: false
@@ -0,0 +1,355 @@
1
+ #--
2
+ # FreeBASIC project builder
3
+ # inspired by Asset Compiler by Jeremy Voorhis
4
+ # coded by Luis Lavena
5
+ #--
6
+
7
+ # FreeBASIC Project library for compilation.
8
+ # For example:
9
+ #
10
+ # namespace :projects do
11
+ # project_task :my_fb_project do
12
+ # lib 'static'
13
+ # dylib 'dynamic library'
14
+ # executable 'exename'
15
+ #
16
+ # build_to 'bin'
17
+ #
18
+ # define 'MY_DEFINE'
19
+ #
20
+ # main 'src/main.bas'
21
+ # source 'src/other_module.bas'
22
+ # source "src/*.bas"
23
+ # end
24
+ # end
25
+ #
26
+ # This example defines the following tasks:
27
+ #
28
+ # rake projects:build # Build all projects
29
+ # rake projects:clobber # Clobber all projects
30
+ # rake projects:my_fb_project:build # Build the my_fb_project files
31
+ # rake projects:my_fb_project:clobber # Remove the my_fb_project files
32
+ # rake projects:my_fb_project:rebuild # Force a rebuild of the my_fb_project files
33
+ # rake projects:rebuild # Rebuild all projects
34
+
35
+ require 'rake/tasklib'
36
+ require 'pp'
37
+
38
+ module FreeBASIC
39
+ # this help me reduce the attempts to remove already removed files.
40
+ # works with src_files
41
+ CLOBBER = Rake::FileList.new
42
+ ON_WINDOWS = (RUBY_PLATFORM =~ /mswin|cygwin|bccwin/)
43
+
44
+ class ProjectTask
45
+ attr_accessor :name
46
+ attr_accessor :output_name
47
+ attr_accessor :type
48
+ attr_accessor :build_path
49
+ attr_accessor :defines
50
+ attr_accessor :main_file
51
+ attr_accessor :sources
52
+ attr_accessor :libraries
53
+ attr_accessor :search_path
54
+ attr_accessor :libraries_path
55
+
56
+ def initialize(name, &block)
57
+ @name = name.to_s
58
+ @build_path = '.'
59
+ @defines = []
60
+ @sources = Rake::FileList.new
61
+ @libraries = []
62
+ @search_path = []
63
+ @libraries_path = []
64
+ @options = {}
65
+
66
+ instance_eval &block
67
+
68
+ do_cleanup
69
+
70
+ namespace @name do
71
+ define_clobber_task
72
+ define_rebuild_task
73
+ define_build_directory_task
74
+ define_build_task
75
+ end
76
+ add_dependencies_to_main_task
77
+ end
78
+
79
+ public
80
+ # using this will set your project type to :executable
81
+ # and assign exe_name as the output_name for the project
82
+ # it dynamically will assign extension when running on windows
83
+ def executable(exe_name)
84
+ @type = :executable
85
+ @output_name = "#{exe_name}.#{(ON_WINDOWS ? "exe" : "")}"
86
+ @real_file_name = @output_name
87
+ end
88
+
89
+ # lib will set type to :lib and assign 'lib#{lib_name}.a'
90
+ # as output_name for the project
91
+ def lib(lib_name)
92
+ @type = :lib
93
+ @output_name = lib_name
94
+ @real_file_name = "lib#{lib_name}.a"
95
+ end
96
+
97
+ # dynlib will set type to :dynlib and assign '#{dll_name}.dll|so'
98
+ # as output_name for this project
99
+ def dylib(dll_name)
100
+ @type = :dylib
101
+ @output_name = "#{dll_name}.#{(ON_WINDOWS ? "dll" : "so")}"
102
+ @real_file_name = @output_name
103
+ @complement_file = "lib#{@output_name}.a"
104
+ end
105
+
106
+ # this set where the final, compiled executable should be linked
107
+ # uses @build_path as variable
108
+ def build_to(path)
109
+ @build_path = path
110
+ end
111
+
112
+ # define allow you set compiler time options
113
+ # collect them into @defines and use later
114
+ # to call source file compilation process (it wil require cleanup)
115
+ def define(*defines)
116
+ @defines << defines
117
+ end
118
+
119
+ # main set @main_file to be the main module used during the linking
120
+ # process. also, this module requires special -m flag during his
121
+ # own compile process
122
+ # question: in case @no main_file was set, will use the first 'source'
123
+ # file defined as main? or it should raise a error?
124
+ def main(main_file)
125
+ @main_file = main_file
126
+ end
127
+
128
+ # used to collect sources files for compilation
129
+ # it will take .bas, .rc, .res as sources
130
+ # before compilation we should clean @sources!
131
+ def source(*sources)
132
+ @sources.include sources
133
+ end
134
+
135
+ # this is similar to sources, instead library linking is used
136
+ # also will require cleanup services ;-)
137
+ def library(*libraries)
138
+ @libraries << libraries
139
+ end
140
+
141
+ # use this to set the include path when looking for, ehem, includes
142
+ # (equals -i fbc compiler param)
143
+ def search_path(*search_path)
144
+ @search_path << search_path
145
+ end
146
+
147
+ # use this to tell the compiler where to look for libraries
148
+ # (equals -p fbc compiler param)
149
+ def lib_path(*libraries_path)
150
+ @libraries_path << libraries_path
151
+ end
152
+
153
+ # use this to add additional compiler parameters (like debug or errorchecking options)
154
+ #
155
+ def option(new_options = {})
156
+ @options.merge!(new_options)
157
+ end
158
+
159
+ protected
160
+ # this method will fix nested libraries and defines
161
+ # also, if main_file is missing (or wasn't set) will shift the first one
162
+ # as main
163
+ def do_cleanup
164
+ # remove duplicated definitions, flatten
165
+ @defines.flatten!
166
+ @defines.uniq! if @defines.length > 1
167
+
168
+ # set main_file
169
+ if @type == :executable
170
+ @main_file = @sources.shift unless defined?(@main_file)
171
+ end
172
+
173
+ # empty path? must be corrected
174
+ @build_path = '.' if @build_path == ''
175
+
176
+ # remove duplicates from sources
177
+ @sources.uniq! if @sources.length > 1
178
+
179
+ # now the libraries
180
+ @libraries.flatten!
181
+ @libraries.uniq! if @libraries.length > 1
182
+
183
+ # search path
184
+ @search_path.flatten!
185
+ @search_path.uniq! if @search_path.length > 1
186
+
187
+ # libraries path
188
+ @libraries_path.flatten!
189
+ @libraries_path.uniq! if @libraries_path.length > 1
190
+
191
+ # if no target was set, default to executable
192
+ unless defined?(@output_name)
193
+ executable(@name)
194
+ end
195
+ end
196
+
197
+ # return the compiled name version of the passed source file (src)
198
+ # compiled_form("test.bas") => "test.o"
199
+ def compiled_form(src)
200
+ src.ext({ ".bas" => "o", ".rc" => "obj" }[File.extname(src)])
201
+ end
202
+
203
+ def compiled_project_file
204
+ File.join @build_path, @real_file_name
205
+ end
206
+
207
+ def fbc_compile(source, target, main = nil)
208
+ cmdline = []
209
+ cmdline << "fbc"
210
+ cmdline << "-g" if (@options.has_key?(:debug) && @options[:debug] == true)
211
+ cmdline << "-#{@options[:errorchecking].to_s}" if @options.has_key?(:errorchecking)
212
+ cmdline << "-profile" if (@options.has_key?(:profile) && @options[:profile] == true)
213
+ cmdline << "-mt" if (@options.has_key?(:mt) && @options[:mt] == true)
214
+ cmdline << "-w pedantic" if (@options.has_key?(:pedantic) && @options[:pedantic] == true)
215
+ cmdline << "-c #{source}"
216
+ cmdline << "-o #{target}"
217
+ cmdline << "-m #{main}" unless main.nil?
218
+ cmdline << @defines.collect { |defname| "-d #{defname}" }
219
+ cmdline << @search_path.collect { |path| "-i #{path}" }
220
+ cmdline.flatten.join(' ')
221
+ end
222
+
223
+ def fbc_link(target, files, extra_files = [])
224
+ cmdline = []
225
+ cmdline << "fbc"
226
+ cmdline << "-g" if (@options.has_key?(:debug) && @options[:debug] == true)
227
+ cmdline << "-profile" if (@options.has_key?(:profile) && @options[:profile] == true)
228
+ cmdline << "-mt" if (@options.has_key?(:mt) && @options[:mt] == true)
229
+ cmdline << "-#{@type.to_s}" unless @type == :executable
230
+ cmdline << "-x #{target}"
231
+ cmdline << files << extra_files
232
+ cmdline << @defines.collect { |defname| "-d #{defname}" }
233
+ unless @type == :lib
234
+ cmdline << @libraries_path.collect { |path| "-p #{path}" }
235
+ cmdline << @libraries.collect { |libname| "-l #{libname}" }
236
+ end
237
+ cmdline.flatten.join(' ')
238
+ end
239
+
240
+ def define_clobber_task
241
+ desc "Remove all compiled files for #{@name}"
242
+ task :clobber do
243
+ # remove compiled and linked file
244
+ rm compiled_project_file rescue nil #unless @type == :lib
245
+ rm File.join(@build_path, @complement_file) rescue nil if @type == :dylib
246
+
247
+ # remove main file
248
+ rm compiled_form(@main_file) rescue nil
249
+
250
+ # now the sources files
251
+ # avoid attempt to remove the file two times (this is a bug in Rake)
252
+ @sources.each do |src|
253
+ # exclude compiled source files (c obj).
254
+ unless src =~ /o$/
255
+ target = compiled_form(src)
256
+ unless CLOBBER.include?(target)
257
+ CLOBBER.include(target)
258
+ rm target rescue nil
259
+ end
260
+ end
261
+ end
262
+ end
263
+ end
264
+
265
+ def define_rebuild_task
266
+ desc "Force a rebuild of files for #{@name}"
267
+ task :rebuild => [:clobber, :build]
268
+ end
269
+
270
+ def define_build_directory_task
271
+ directory @build_path
272
+ task :build => @build_path
273
+ end
274
+
275
+ def define_build_task
276
+ desc "Build project #{@name}"
277
+ task :build
278
+
279
+ # empty file task
280
+ file compiled_project_file
281
+
282
+ # compile main_file
283
+ # use as pre-requisite the source filename
284
+ if @type == :executable
285
+ file compiled_form(@main_file) => @main_file do |t|
286
+ # remove the path and the extension
287
+ main_module = File.basename(t.name).ext
288
+ sh fbc_compile(@main_file, t.name, main_module)
289
+ end
290
+
291
+ # add dependency
292
+ file compiled_project_file => compiled_form(@main_file)
293
+ end
294
+
295
+ # gather files that are passed "as-is" to the compiler
296
+ unprocessed_files = @sources.select { |rcfile| rcfile =~ /(res|rc|o|obj)$/ }
297
+
298
+ @sources.each do |src|
299
+ # is a unprocessed file?
300
+ unless unprocessed_files.include?(src)
301
+ target = compiled_form(src)
302
+
303
+ # is already in our list of tasks?
304
+ if not Rake::Task.task_defined?(target)
305
+ # if not, compile
306
+
307
+ file target => src do
308
+ sh fbc_compile(src, target)
309
+ end
310
+ end
311
+
312
+ # include dependency
313
+ file compiled_project_file => target
314
+ end
315
+ end
316
+
317
+ # now the linking process
318
+ file compiled_project_file do |t|
319
+ target = File.join(@build_path, @output_name)
320
+ sh fbc_link(target, t.prerequisites, unprocessed_files)
321
+ end
322
+
323
+ # add the dependency
324
+ task :build => compiled_project_file
325
+ end
326
+
327
+ # Adds dependencies in the parent namespace
328
+ def add_dependencies_to_main_task
329
+ desc 'Build all projects' unless task( :build ).comment
330
+ task :build => "#{@name}:build"
331
+
332
+ desc 'Clobber all projects' unless task( :clobber ).comment
333
+ task :clobber => "#{@name}:clobber"
334
+
335
+ desc 'Rebuild all projects' unless task( :rebuild ).comment
336
+ task :rebuild => ["#{@name}:clobber", "#{@name}:build"]
337
+ end
338
+ end
339
+ end
340
+
341
+ # helper method to define a FreeBASIC::ProjectTask in the current namespace
342
+ def project_task name, &block
343
+ FreeBASIC::ProjectTask.new name, &block
344
+ end
345
+
346
+ def include_projects_of name
347
+ desc 'Build all projects' unless task( :build ).comment
348
+ task :build => "#{name}:build"
349
+
350
+ desc 'Clobber all projects' unless task( :clobber ).comment
351
+ task :clobber => "#{name}:clobber"
352
+
353
+ desc 'Rebuild all projects' unless task( :rebuild ).comment
354
+ task :rebuild => "#{name}:rebuild"
355
+ end