nitro 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +8 -0
- data/ChangeLog +1546 -0
- data/LICENCE +32 -0
- data/README +278 -0
- data/RELEASES +7 -0
- data/Rakefile +79 -0
- data/bin/cluster.rb +219 -0
- data/doc/architecture.txt +28 -0
- data/doc/bugs.txt +7 -0
- data/doc/css.txt +20 -0
- data/doc/ideas.txt +120 -0
- data/doc/pg.txt +47 -0
- data/doc/svn.txt +82 -0
- data/doc/todo.txt +30 -0
- data/etc/new-project.rb +18 -0
- data/examples/simple/README +15 -0
- data/examples/simple/app.rb +31 -0
- data/examples/simple/conf/apache.conf +100 -0
- data/examples/simple/conf/config.rb +89 -0
- data/examples/simple/conf/debug-config.rb +53 -0
- data/examples/simple/conf/live-config.rb +48 -0
- data/examples/simple/conf/overrides.rb +9 -0
- data/examples/simple/conf/requires.rb +51 -0
- data/examples/simple/ctl +32 -0
- data/examples/simple/env.rb +33 -0
- data/examples/simple/install.rb +12 -0
- data/examples/simple/lib/articles/entities.rb +35 -0
- data/examples/simple/lib/articles/lc-en.rb +36 -0
- data/examples/simple/lib/articles/methods.rb +55 -0
- data/examples/simple/lib/articles/part.rb +58 -0
- data/examples/simple/logs/access_log +2 -0
- data/examples/simple/logs/apache.log +3 -0
- data/examples/simple/logs/app.log +1 -0
- data/examples/simple/logs/events.log +1 -0
- data/examples/simple/root/add-article.sx +15 -0
- data/examples/simple/root/article-form.ss +20 -0
- data/examples/simple/root/comments-form.ss +16 -0
- data/examples/simple/root/comments.si +30 -0
- data/examples/simple/root/index.sx +44 -0
- data/examples/simple/root/shader/shader.xsl +100 -0
- data/examples/simple/root/shader/style.css +9 -0
- data/examples/simple/root/view-article.sx +30 -0
- data/examples/tiny/app.rb +30 -0
- data/examples/tiny/conf/apache.conf +100 -0
- data/examples/tiny/conf/config.rb +67 -0
- data/examples/tiny/conf/requires.rb +40 -0
- data/examples/tiny/ctl +31 -0
- data/examples/tiny/logs/access_log +9 -0
- data/examples/tiny/logs/apache.log +9 -0
- data/examples/tiny/root/index.sx +35 -0
- data/lib/n/app/cluster.rb +219 -0
- data/lib/n/app/cookie.rb +86 -0
- data/lib/n/app/filters/autologin.rb +50 -0
- data/lib/n/app/fragment.rb +67 -0
- data/lib/n/app/handlers.rb +120 -0
- data/lib/n/app/handlers/code-handler.rb +184 -0
- data/lib/n/app/handlers/page-handler.rb +612 -0
- data/lib/n/app/request-part.rb +59 -0
- data/lib/n/app/request.rb +653 -0
- data/lib/n/app/script.rb +398 -0
- data/lib/n/app/server.rb +53 -0
- data/lib/n/app/session.rb +224 -0
- data/lib/n/app/user.rb +47 -0
- data/lib/n/app/webrick-servlet.rb +213 -0
- data/lib/n/app/webrick.rb +70 -0
- data/lib/n/application.rb +187 -0
- data/lib/n/config.rb +31 -0
- data/lib/n/db.rb +217 -0
- data/lib/n/db/README +232 -0
- data/lib/n/db/connection.rb +369 -0
- data/lib/n/db/make-release.sh +26 -0
- data/lib/n/db/managed.rb +235 -0
- data/lib/n/db/mixins.rb +282 -0
- data/lib/n/db/mysql.rb +342 -0
- data/lib/n/db/psql.rb +378 -0
- data/lib/n/db/tools.rb +110 -0
- data/lib/n/db/utils.rb +99 -0
- data/lib/n/events.rb +118 -0
- data/lib/n/l10n.rb +22 -0
- data/lib/n/logger.rb +33 -0
- data/lib/n/macros.rb +53 -0
- data/lib/n/mixins.rb +46 -0
- data/lib/n/parts.rb +154 -0
- data/lib/n/properties.rb +194 -0
- data/lib/n/server.rb +61 -0
- data/lib/n/server/PLAYBACK.txt +8 -0
- data/lib/n/server/RESEARCH.txt +13 -0
- data/lib/n/server/filter.rb +77 -0
- data/lib/n/shaders.rb +167 -0
- data/lib/n/sitemap.rb +188 -0
- data/lib/n/std.rb +69 -0
- data/lib/n/sync/clc.rb +108 -0
- data/lib/n/sync/handler.rb +221 -0
- data/lib/n/sync/server.rb +170 -0
- data/lib/n/tools/README +11 -0
- data/lib/n/ui/date-select.rb +74 -0
- data/lib/n/ui/pager.rb +187 -0
- data/lib/n/ui/popup.rb +45 -0
- data/lib/n/ui/select.rb +41 -0
- data/lib/n/ui/tabs.rb +34 -0
- data/lib/n/utils/array.rb +92 -0
- data/lib/n/utils/cache.rb +144 -0
- data/lib/n/utils/gfx.rb +108 -0
- data/lib/n/utils/hash.rb +148 -0
- data/lib/n/utils/html.rb +147 -0
- data/lib/n/utils/http.rb +98 -0
- data/lib/n/utils/mail.rb +28 -0
- data/lib/n/utils/number.rb +31 -0
- data/lib/n/utils/pool.rb +66 -0
- data/lib/n/utils/string.rb +297 -0
- data/lib/n/utils/template.rb +38 -0
- data/lib/n/utils/time.rb +91 -0
- data/lib/n/utils/uri.rb +193 -0
- data/lib/xsl/base.xsl +205 -0
- data/lib/xsl/ce.xsl +30 -0
- data/lib/xsl/localization.xsl +23 -0
- data/lib/xsl/xforms.xsl +26 -0
- data/test/run.rb +95 -0
- metadata +187 -0
data/LICENCE
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
The BSD Licence
|
2
|
+
|
3
|
+
Copyright (c) 2004, Navel Ltd. (http://www.navel.gr)
|
4
|
+
All rights reserved.
|
5
|
+
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
7
|
+
modification, are permitted provided that the following conditions are
|
8
|
+
met:
|
9
|
+
|
10
|
+
* Redistributions of source code must retain the above copyright
|
11
|
+
notice, this list of conditions and the following disclaimer.
|
12
|
+
|
13
|
+
* Redistributions in binary form must reproduce the above copyright
|
14
|
+
notice, this list of conditions and the following disclaimer in the
|
15
|
+
documentation and/or other materials provided with the distribution.
|
16
|
+
|
17
|
+
* Neither the name of Navel nor the names of its contributors may be
|
18
|
+
used to endorse or promote products derived from this software
|
19
|
+
without specific prior written permission.
|
20
|
+
|
21
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
22
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
23
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
24
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
25
|
+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
26
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
27
|
+
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
28
|
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
29
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
30
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
31
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
32
|
+
|
data/README
ADDED
@@ -0,0 +1,278 @@
|
|
1
|
+
= Nitro
|
2
|
+
|
3
|
+
Nitro is an efficient, yet simple engine for developing professional Web
|
4
|
+
Applications using the Ruby language. Nitro aims to provide a robust
|
5
|
+
infrastructure for scalable web applications that can be distributed
|
6
|
+
over a server cluster. However, Nitro can also power simple web
|
7
|
+
applications for deployment on intranets or even personal computers.
|
8
|
+
|
9
|
+
|
10
|
+
== Features
|
11
|
+
|
12
|
+
A short summary of the major features:
|
13
|
+
|
14
|
+
* XML server pages (.sx)
|
15
|
+
|
16
|
+
Nitro introduces a new format for server pages that combines the
|
17
|
+
power of embededed Ruby (like erb, eruby) with the xml compliance
|
18
|
+
of Amrita. Even though it is a 'Callback' style templating system
|
19
|
+
it is flexible enough to run as 'Pipeline' style system if the
|
20
|
+
developer prefers this mode of operation.
|
21
|
+
|
22
|
+
<?xml version="1.0"?>
|
23
|
+
|
24
|
+
<!-- example page -->
|
25
|
+
<html>
|
26
|
+
<?r
|
27
|
+
title = "Example"
|
28
|
+
version = request["version"]
|
29
|
+
?>
|
30
|
+
|
31
|
+
<h1>#{title}</h1>
|
32
|
+
|
33
|
+
<?r if version > 1 ?>
|
34
|
+
<b>Version:</b> #{version}
|
35
|
+
<?r end ?>
|
36
|
+
|
37
|
+
</html>
|
38
|
+
|
39
|
+
* Shaders, XSLT templates
|
40
|
+
|
41
|
+
Nitro promotes the usage of XSLT for web templates. The functional
|
42
|
+
nature of XSL is ideal for the Web. Moreover, the engine efficiently
|
43
|
+
precompiles the xsl transformation along with other transformations
|
44
|
+
(for example localization) essentially providing a computationally
|
45
|
+
free transformation step.
|
46
|
+
|
47
|
+
A shader integrates many XSLT templates and or CSS stylesheets
|
48
|
+
to encapsulate all styling/skinning requirements of a Web Application.
|
49
|
+
|
50
|
+
* Multi phase evaluation
|
51
|
+
|
52
|
+
Experimental, facilitates efficient HTTP1.1 caching.
|
53
|
+
|
54
|
+
* Fragment Synthesis
|
55
|
+
|
56
|
+
Nitro server pages can include fragments at 'Compile' time or at
|
57
|
+
'RunTime' time.
|
58
|
+
|
59
|
+
<!-- compile time include (static include) -->
|
60
|
+
<?include xl:href="myfile.si" />
|
61
|
+
|
62
|
+
<!-- run time include (dynamic include) -->
|
63
|
+
<x:include xl:href="myfile.si" />
|
64
|
+
|
65
|
+
* Object-Relational Mapping
|
66
|
+
|
67
|
+
Nitro integrates the NDB object-relational mapping library. NDB
|
68
|
+
provides transparent serialization of object graphs to a RDBMS
|
69
|
+
backend. Unlike other similar libraries NDB maps standard Ruby
|
70
|
+
objects to SQL tables and not vice versa. NDB provides a flexible
|
71
|
+
and intuitive api for querieng the database, raw access to the
|
72
|
+
SQL language if needed (for example to fine tune the automatically
|
73
|
+
generated SQL tables, or for custom queries), suports deserialization
|
74
|
+
to Ruby objects or tuples and provides a collection of usefull Mixins
|
75
|
+
to synthesize common Entities.
|
76
|
+
|
77
|
+
* Distributed State
|
78
|
+
|
79
|
+
Nitro provides a powerfull distributed state mechanism that utilizes
|
80
|
+
the DRb library. A typicall use of this infrastructure is to provide
|
81
|
+
distributed sessions when running your application over a server
|
82
|
+
cluster. Distributed sessions are fully transparent to the developer.
|
83
|
+
|
84
|
+
* Synchronous Server
|
85
|
+
|
86
|
+
An experimental synchronous server for implementing services like
|
87
|
+
Chat Rooms, Multiplayer Games, etc. Compatible with Macromedia Flash.
|
88
|
+
|
89
|
+
* Request Filters
|
90
|
+
|
91
|
+
The develpoper has full access to the request handling pipeline.
|
92
|
+
Request filters are a powerfull mechanism for customized processing
|
93
|
+
of special requests. Example filters are the autologin filter,
|
94
|
+
a gzip filter etc.
|
95
|
+
|
96
|
+
* Hierarchical Caching
|
97
|
+
|
98
|
+
Nitro provides a well designed and efficient caching mechanism. Caching
|
99
|
+
will be provided at the following levels:
|
100
|
+
|
101
|
+
* DB Cache
|
102
|
+
* Object Cache (deserialized objects)
|
103
|
+
* Fragment Caching (cache generated sub-parts of a page, or a page)
|
104
|
+
* HTTP 1.1 Caching (downstream caching of whole pages)
|
105
|
+
|
106
|
+
The engine calculates intra-page dependencies automatically. A variety
|
107
|
+
of invalidation strategies can be implemented.
|
108
|
+
|
109
|
+
* Support for 'nice' urls.
|
110
|
+
|
111
|
+
Experimental
|
112
|
+
|
113
|
+
* Advanced debuging features
|
114
|
+
|
115
|
+
* When running in debug mode, all exceptions raise are logged
|
116
|
+
to a special debug panel in the current page. Find out the offending
|
117
|
+
file and line from the exception dump, fix the bug, refresh the page.
|
118
|
+
|
119
|
+
* in-process console: inject an irb session to a running application
|
120
|
+
server. You can use the irb console to investigate all variables
|
121
|
+
and code in your running server process.
|
122
|
+
|
123
|
+
* Parts
|
124
|
+
|
125
|
+
Parts are organized modules of web services. A Web Framework that
|
126
|
+
integrates a large collection of parts (User management, Blog,
|
127
|
+
Fora, CMS, Personalization, ..) will be released by Navel.
|
128
|
+
|
129
|
+
Other libraries of parts are expected from the Ruby community when
|
130
|
+
the Part API is finalized.
|
131
|
+
|
132
|
+
* UI Components
|
133
|
+
|
134
|
+
Nitro is distributed with a collection of usefull UI components
|
135
|
+
to make form based application development easier (for example
|
136
|
+
an efficient, ndb-aware Pager component).
|
137
|
+
|
138
|
+
* Path overloading
|
139
|
+
|
140
|
+
Experimental
|
141
|
+
|
142
|
+
* Localization
|
143
|
+
|
144
|
+
Nitro supports efficient localization of web applications.
|
145
|
+
|
146
|
+
|
147
|
+
== Download
|
148
|
+
|
149
|
+
The latest version of Nitro can be found at
|
150
|
+
|
151
|
+
* http://www.navel.gr/nitro
|
152
|
+
|
153
|
+
Documentation for Nitro can be found at
|
154
|
+
|
155
|
+
* http://www.navel.gr/nitro/doc
|
156
|
+
|
157
|
+
|
158
|
+
== Requirements
|
159
|
+
|
160
|
+
Nitro requires the following applications or libraries:
|
161
|
+
|
162
|
+
* Ruby 1.8.1 and greater (http://www.ruby-lang.org)
|
163
|
+
Version 1.8.2.preview2 is recomended
|
164
|
+
|
165
|
+
* Apache 2.0 (http://www.apache.org)
|
166
|
+
Will be optional in a future version.
|
167
|
+
|
168
|
+
The following applications or libraries are optional:
|
169
|
+
|
170
|
+
* PostgreSQL (http://www.postgres.org)
|
171
|
+
Used for Database driven web applications
|
172
|
+
|
173
|
+
* Ruby-psql (http://www.postgresql.jp/interfaces/ruby/archive/ruby-postgres-0.7.1.tar.gz)
|
174
|
+
Ruby interface to the PostgreSQL RDBMS.
|
175
|
+
|
176
|
+
* Ruby-XSLT (http://gregoire.lejeune.free.fr/ruby-xslt_0.4.0.tar.gz)
|
177
|
+
Used for XSLT based templates.
|
178
|
+
|
179
|
+
Please install the required applications and libraries before continuing
|
180
|
+
with the installation of Nitro.
|
181
|
+
|
182
|
+
|
183
|
+
== Instalation
|
184
|
+
|
185
|
+
Nitro is distributed as a RubyGem. First of all make sure you have
|
186
|
+
installed RubyGems on your system. Then run the following command:
|
187
|
+
|
188
|
+
gem install nitro
|
189
|
+
|
190
|
+
Then try to run the examples/tiny Example application.
|
191
|
+
|
192
|
+
A tar.gz distribution is also available on http://www.navel.gr/nitro
|
193
|
+
|
194
|
+
|
195
|
+
== Running the example applications
|
196
|
+
|
197
|
+
* examples/tiny
|
198
|
+
|
199
|
+
A simple application that requires no external applications
|
200
|
+
|
201
|
+
$ cd nitro/examples/tiny
|
202
|
+
|
203
|
+
$ vi conf/apache.conf
|
204
|
+
|
205
|
+
edit user, group,DocumentRoot root as needed.
|
206
|
+
|
207
|
+
$ ./ctl start
|
208
|
+
|
209
|
+
this script starts the distributed session cluster, apache and the
|
210
|
+
application server.
|
211
|
+
|
212
|
+
browse http://127.0.0.1:8080
|
213
|
+
|
214
|
+
to stop the application execute:
|
215
|
+
|
216
|
+
$ ./ctl stop
|
217
|
+
|
218
|
+
* examples/simple
|
219
|
+
|
220
|
+
A simple application to demonstrate xsl skins, entities, postback.
|
221
|
+
|
222
|
+
$ cd nitro/examples/simple
|
223
|
+
|
224
|
+
$ vi conf/apache.conf
|
225
|
+
|
226
|
+
edit user, group,DocumentRoot root as needed.
|
227
|
+
|
228
|
+
$ vi conf/config.rb
|
229
|
+
|
230
|
+
edit the postgresql user and password
|
231
|
+
|
232
|
+
run the following script to initialize the postgresql database used by
|
233
|
+
the example
|
234
|
+
|
235
|
+
$ ruby install.rb
|
236
|
+
|
237
|
+
$ ./ctl start
|
238
|
+
|
239
|
+
this script starts the distributed session cluster, apache and the
|
240
|
+
application server.
|
241
|
+
|
242
|
+
browse http://127.0.0.1:8080
|
243
|
+
|
244
|
+
to attach an irb console to the running server, execute from
|
245
|
+
another shell:
|
246
|
+
|
247
|
+
$ cd /examples/simple
|
248
|
+
|
249
|
+
$ irb -r env.rb
|
250
|
+
|
251
|
+
to stop the application execute:
|
252
|
+
|
253
|
+
$ ./ctl stop
|
254
|
+
|
255
|
+
== Debuging Nitro applications
|
256
|
+
|
257
|
+
Have "tail -f" commands running on logs/app.log in your application
|
258
|
+
directory. Nitro will automatically display debugging and runtime
|
259
|
+
information to these files. Debugging info will also be shown in the
|
260
|
+
browser when running in debug mode.
|
261
|
+
|
262
|
+
|
263
|
+
== Support
|
264
|
+
|
265
|
+
For any questions regarding Nitro, feel free to ask on the ruby-talk
|
266
|
+
mailing list (which is mirrored to comp.lang.ruby) or contact
|
267
|
+
mailto:gm@navel.gr.
|
268
|
+
|
269
|
+
|
270
|
+
== Licence
|
271
|
+
|
272
|
+
Copyright (c) 2004 Navel Ltd (http://www.navel.gr)
|
273
|
+
|
274
|
+
Nitro (http://www.navel.gr/nitro) is copyrighted free software
|
275
|
+
created and maintained by George Moschovitis (mailto:gm@navel.gr)
|
276
|
+
and released under the standard BSD Licence. For details consult
|
277
|
+
the file LICENCE.
|
278
|
+
|
data/RELEASES
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
|
2
|
+
== Version 0.1.2 was released on 21/10/2004.
|
3
|
+
|
4
|
+
The first public version. Features 2 examples and limited
|
5
|
+
documentation. The aim of this release is to make the procect known
|
6
|
+
to the Ruby Community. We hope that the Ruby hackers will respond
|
7
|
+
with valueable suggestions and ideas.
|
data/Rakefile
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
# = Rakefile
|
2
|
+
#
|
3
|
+
# code:
|
4
|
+
# George Moschovitis <gm@navel.gr>
|
5
|
+
#
|
6
|
+
# (c) 2004 Navel, all rights reserved.
|
7
|
+
# $Id: connection.rb 71 2004-10-18 10:50:22Z gmosx $
|
8
|
+
|
9
|
+
require "rake"
|
10
|
+
require "rake/rdoctask"
|
11
|
+
require "rubygems"
|
12
|
+
require "rake/gempackagetask"
|
13
|
+
|
14
|
+
require "lib/n/config"
|
15
|
+
|
16
|
+
# ----------------------------------------------------------------------
|
17
|
+
|
18
|
+
desc "Default Task"
|
19
|
+
task :default => :package
|
20
|
+
|
21
|
+
# ----------------------------------------------------------------------
|
22
|
+
|
23
|
+
desc "Run unit tests"
|
24
|
+
task :test do
|
25
|
+
# Might wait until I"ve got some...
|
26
|
+
end
|
27
|
+
|
28
|
+
# ----------------------------------------------------------------------
|
29
|
+
|
30
|
+
Rake::RDocTask.new do |rd|
|
31
|
+
rd.main = "README"
|
32
|
+
rd.rdoc_dir = "rdoc"
|
33
|
+
rd.rdoc_files.include("README", "lib/**/*.rb")
|
34
|
+
end
|
35
|
+
|
36
|
+
# ----------------------------------------------------------------------
|
37
|
+
|
38
|
+
PKG_VERSION = $srv_version
|
39
|
+
PKG_FILES = FileList[
|
40
|
+
"[A-Z]*", "{bin,etc,examples,doc,lib,test}/**/*"
|
41
|
+
# "examples/*.rb"
|
42
|
+
].exclude(".svn/**/*")
|
43
|
+
|
44
|
+
spec = Gem::Specification.new do |s|
|
45
|
+
s.name = "nitro"
|
46
|
+
s.version = PKG_VERSION
|
47
|
+
s.summary = "Web Engine"
|
48
|
+
s.description = "An efficient, yet simple engine for Web Applications"
|
49
|
+
# s.add_dependency("extensions", ">= 0.5")
|
50
|
+
s.required_ruby_version = ">= 1.8.1"
|
51
|
+
s.files = PKG_FILES.to_a
|
52
|
+
s.require_path = "lib"
|
53
|
+
s.autorequire = "n/std"
|
54
|
+
s.has_rdoc = true
|
55
|
+
s.extra_rdoc_files = FileList["[A-Z]*"].to_a
|
56
|
+
s.rdoc_options << "--main" << "README" << "--title" <<
|
57
|
+
"Nitro Documentation"
|
58
|
+
s.test_files = []
|
59
|
+
s.bindir = "bin"
|
60
|
+
s.author = "George Moschovitis"
|
61
|
+
s.email = "gm@navel.gr"
|
62
|
+
s.homepage = "http://www.navel.gr/nitro"
|
63
|
+
s.rubyforge_project = "nitro"
|
64
|
+
end
|
65
|
+
|
66
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
67
|
+
pkg.package_dir = "dist"
|
68
|
+
pkg.need_zip = true
|
69
|
+
pkg.need_tar = true
|
70
|
+
end
|
71
|
+
|
72
|
+
# ----------------------------------------------------------------------
|
73
|
+
|
74
|
+
desc "Install the gem"
|
75
|
+
task :install => :repackage do
|
76
|
+
sh "gem install --local --no-rdoc dist/nitro-#{PKG_VERSION}.gem"
|
77
|
+
end
|
78
|
+
|
79
|
+
# vim: ft=ruby
|
data/bin/cluster.rb
ADDED
@@ -0,0 +1,219 @@
|
|
1
|
+
# = Cluster
|
2
|
+
#
|
3
|
+
# TODO: use Sync instead of Monitor
|
4
|
+
#
|
5
|
+
# code:: gmosx
|
6
|
+
#
|
7
|
+
# (c) 2004 Navel, all rights reserved.
|
8
|
+
# $Id: cluster.rb 74 2004-10-18 11:30:20Z gmosx $
|
9
|
+
|
10
|
+
$:.unshift "nitro/lib"
|
11
|
+
|
12
|
+
require "drb"
|
13
|
+
require "monitor"
|
14
|
+
|
15
|
+
require "n/application"
|
16
|
+
require "n/server"
|
17
|
+
require "n/utils/cache"
|
18
|
+
require "n/app/session"
|
19
|
+
|
20
|
+
module N
|
21
|
+
|
22
|
+
# = Cluster
|
23
|
+
#
|
24
|
+
# A Cluster is a collection of servers. The cluster synchronizes the
|
25
|
+
# servers and distributes the state. An older version used a polling
|
26
|
+
# system, ie: the servers polled the cluster to obtain the state. This
|
27
|
+
# version uses a push system, ie when the state is changed a delta
|
28
|
+
# is pushed to the clients.
|
29
|
+
#
|
30
|
+
class Cluster < N::Application
|
31
|
+
|
32
|
+
# = CHash ClusterHash
|
33
|
+
#
|
34
|
+
class CHash < Hash
|
35
|
+
attr :mon
|
36
|
+
|
37
|
+
# drbobject for this hash (local)
|
38
|
+
attr_accessor :ldrb
|
39
|
+
|
40
|
+
# the cluster, use a cluster to implement a set
|
41
|
+
# (one server per drb_uri)
|
42
|
+
attr_accessor :cluster
|
43
|
+
|
44
|
+
#
|
45
|
+
#
|
46
|
+
def initialize(ldrb_uri = "druby://:8000")
|
47
|
+
@mon = Monitor.new
|
48
|
+
@ldrb = DRb.start_service(ldrb_uri, self)
|
49
|
+
@cluster = {}
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
#
|
54
|
+
def join(sdrb_uri)
|
55
|
+
@mon.synchronize {
|
56
|
+
cluster[sdrb_uri] = DRbObject.new(nil, sdrb_uri)
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
alias_method :old_set, :[]=
|
61
|
+
|
62
|
+
# Not really usefull
|
63
|
+
#
|
64
|
+
def []=(key, value)
|
65
|
+
# store the value (useful on server restarts)
|
66
|
+
@mon.synchronize {
|
67
|
+
old_set(key, value)
|
68
|
+
|
69
|
+
puts "CLUSTER #{key} = #{value}"
|
70
|
+
|
71
|
+
cluster.each { |uri, sdrb|
|
72
|
+
begin
|
73
|
+
sdrb.server_sync(key, value)
|
74
|
+
rescue => ex
|
75
|
+
$log.error "Server at #{uri} is down, removing from cluster"
|
76
|
+
cluster.delete(uri)
|
77
|
+
end
|
78
|
+
}
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
# Use this, avoids syncing the original server, and avoids a
|
83
|
+
# nasty deadlock.
|
84
|
+
#
|
85
|
+
def cluster_sync(key, value, server_uri)
|
86
|
+
# store the value (useful on server restarts)
|
87
|
+
@mon.synchronize {
|
88
|
+
old_set(key, value)
|
89
|
+
|
90
|
+
puts "CLUSTER #{key} = #{value}"
|
91
|
+
|
92
|
+
cluster.each { |uri, sdrb|
|
93
|
+
begin
|
94
|
+
sdrb.server_sync(key, value) unless uri == server_uri
|
95
|
+
rescue => ex
|
96
|
+
$log.error "Server at #{uri} is down, removing from cluster"
|
97
|
+
cluster.delete(uri)
|
98
|
+
end
|
99
|
+
}
|
100
|
+
}
|
101
|
+
end
|
102
|
+
|
103
|
+
def [](key)
|
104
|
+
@mon.synchronize {
|
105
|
+
puts "LOOKUP #{key}"
|
106
|
+
return super
|
107
|
+
}
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
# = SHash ServerHash
|
113
|
+
#
|
114
|
+
class SHash < Hash
|
115
|
+
attr :mon
|
116
|
+
|
117
|
+
# drbobject for this hash (local)
|
118
|
+
attr_accessor :ldrb
|
119
|
+
|
120
|
+
# drb for the cluster hash
|
121
|
+
attr_accessor :cdrb
|
122
|
+
|
123
|
+
# ldrb = local drb uri
|
124
|
+
# cdrb = cluster drb uri
|
125
|
+
#
|
126
|
+
def initialize(ldrb_uri = "druby://:9000", cdrb_uri = "druby://:8000")
|
127
|
+
@mon = Monitor.new
|
128
|
+
@ldrb_uri = ldrb_uri
|
129
|
+
@ldrb = DRb.start_service(ldrb_uri, self)
|
130
|
+
@cdrb = DRbObject.new(nil, cdrb_uri)
|
131
|
+
@cdrb.join(ldrb_uri)
|
132
|
+
end
|
133
|
+
|
134
|
+
alias_method :old_set, :[]=
|
135
|
+
|
136
|
+
#
|
137
|
+
#
|
138
|
+
def []=(key, value)
|
139
|
+
# store the value in the local hash
|
140
|
+
@mon.synchronize {
|
141
|
+
puts "LOCAL #{key} = #{value}"
|
142
|
+
old_set(key, value)
|
143
|
+
@cdrb.cluster_sync(key, value, @ldrb_uri)
|
144
|
+
}
|
145
|
+
end
|
146
|
+
|
147
|
+
# If the key is not found in the local hash, try the
|
148
|
+
# cluster hash.
|
149
|
+
#
|
150
|
+
def [](key)
|
151
|
+
@mon.synchronize {
|
152
|
+
unless value = super
|
153
|
+
value = @cdrb[key]
|
154
|
+
old_set(key, value)
|
155
|
+
end
|
156
|
+
return value
|
157
|
+
}
|
158
|
+
end
|
159
|
+
|
160
|
+
# Called by the cluster
|
161
|
+
#
|
162
|
+
def server_sync(key, value)
|
163
|
+
puts "SYNC #{key} = #{value}"
|
164
|
+
@mon.synchronize {
|
165
|
+
old_set(key, value)
|
166
|
+
}
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
# = Clm Cluster Last Modified Hash
|
172
|
+
#
|
173
|
+
class Clm < CHash
|
174
|
+
def [](key)
|
175
|
+
@mon.synchronize {
|
176
|
+
unless value = super
|
177
|
+
puts "INIT #{key}"
|
178
|
+
value = Time.now.to_i
|
179
|
+
old_set(key, value)
|
180
|
+
end
|
181
|
+
return value
|
182
|
+
}
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
# = Slm Server Last Modified Hash
|
187
|
+
#
|
188
|
+
class Slm < SHash
|
189
|
+
def set!(key, lm = nil)
|
190
|
+
lm = Time.now.to_i unless lm
|
191
|
+
self[key] = lm
|
192
|
+
return lm
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def initialize(name = "Cluster")
|
197
|
+
super
|
198
|
+
end
|
199
|
+
|
200
|
+
def run
|
201
|
+
N::Cluster::Clm.new
|
202
|
+
DRb.start_service("druby://:8001", N::App::SessionManager.new)
|
203
|
+
|
204
|
+
while true
|
205
|
+
sleep(5000)
|
206
|
+
end
|
207
|
+
|
208
|
+
super
|
209
|
+
end
|
210
|
+
|
211
|
+
end
|
212
|
+
|
213
|
+
end # module
|
214
|
+
|
215
|
+
if $0 == __FILE__
|
216
|
+
require "logger"; $log = Logger.new(STDERR)
|
217
|
+
|
218
|
+
N::Cluster.new.exec()
|
219
|
+
end
|