madeleine 0.7.1

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.
@@ -0,0 +1,19 @@
1
+ #
2
+ # Wrapper for Ruby's file services, replaced during testing
3
+ # so we can run tests without touching a real filesystem.
4
+ #
5
+
6
+ class FileService
7
+
8
+ def open(*args)
9
+ super(*args)
10
+ end
11
+
12
+ def exist?(name)
13
+ File.exist?(name)
14
+ end
15
+
16
+ def dir_entries(name)
17
+ Dir.entries(name)
18
+ end
19
+ end
@@ -0,0 +1,60 @@
1
+ #
2
+ # Author:: Anders Bengtsson <ndrsbngtssn@yahoo.se>
3
+ # Copyright:: Copyright (c) 2004
4
+ #
5
+
6
+ require 'zlib'
7
+
8
+ module Madeleine
9
+ #
10
+ # Snapshot marshaller for compressed snapshots.
11
+ #
12
+ # Compresses the snapshots created by another marshaller. Uses either
13
+ # Marshal (the default) or another supplied marshaller.
14
+ #
15
+ # Uses <tt>zlib</tt> to do on-the-fly compression/decompression.
16
+ #
17
+ # ZMarshal works with Ruby's own Marshal and YAML, but not with SOAP
18
+ # marshalling.
19
+ #
20
+ # Usage:
21
+ #
22
+ # require 'madeleine'
23
+ # require 'madeleine/zmarshal'
24
+ #
25
+ # marshaller = Madeleine::ZMarshal.new(YAML)
26
+ # madeleine = SnapshotMadeleine.new("my_example_storage", marshaller) {
27
+ # SomeExampleApplication.new()
28
+ # }
29
+ #
30
+ class ZMarshal
31
+
32
+ def initialize(marshaller=Marshal)
33
+ @marshaller = marshaller
34
+ end
35
+
36
+ def load(stream)
37
+ zstream = Zlib::GzipReader.new(stream)
38
+ begin
39
+ # Buffer into a string first, since GzipReader can't handle
40
+ # Marshal's 0-sized reads and SOAP can't handle streams at all.
41
+ # In a bright future we can revert to reading directly from the
42
+ # stream again.
43
+ buffer = zstream.read
44
+ return @marshaller.load(buffer)
45
+ ensure
46
+ zstream.finish
47
+ end
48
+ end
49
+
50
+ def dump(system, stream)
51
+ zstream = Zlib::GzipWriter.new(stream)
52
+ begin
53
+ @marshaller.dump(system, zstream)
54
+ ensure
55
+ zstream.finish
56
+ end
57
+ nil
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,73 @@
1
+ #
2
+ # Simple example of using time with Madeleine.
3
+ #
4
+
5
+ $LOAD_PATH.unshift(".." + File::SEPARATOR + "lib")
6
+
7
+ require 'madeleine/clock'
8
+ require 'tk'
9
+
10
+ # The Clicker keeps track of when it was last clicked.
11
+ #
12
+ # To access the time it extends ClockedSystem, which provides
13
+ # it with the 'clock' attribute.
14
+ #
15
+ class Clicker
16
+ include Madeleine::Clock::ClockedSystem
17
+
18
+ def initialize
19
+ @last_clicked = nil
20
+ end
21
+
22
+ def click
23
+ @last_clicked = clock.time
24
+ end
25
+
26
+ def last_clicked
27
+ return '-' if @last_clicked.nil?
28
+ @last_clicked.to_s
29
+ end
30
+ end
31
+
32
+ # A command to update the Clicker with.
33
+ #
34
+ class Click
35
+ def execute(system)
36
+ system.click
37
+ end
38
+ end
39
+
40
+ # Launch a ClockedSnapshotMadeleine.
41
+ #
42
+ # ClockedSnapshotMadeleine works like the regular SnapshotMadeleine, but
43
+ # optimizes away redundant commands from TimeActor.
44
+ #
45
+ madeleine = ClockedSnapshotMadeleine.new("clock-demo") { Clicker.new }
46
+
47
+ # Launch the TimeActor.
48
+ #
49
+ # This provides time commands, without which the system's time would stand still.
50
+ #
51
+ Madeleine::Clock::TimeActor.launch(madeleine)
52
+
53
+ clicker = madeleine.system
54
+
55
+ # The GUI
56
+
57
+ root = TkRoot.new() { title "Madeleine Clock Example" }
58
+ label = TkLabel.new(root) {
59
+ text "Last clicked " + clicker.last_clicked
60
+ width 40
61
+ pack
62
+ }
63
+ button = TkButton.new(root) {
64
+ text 'Click'
65
+ command proc {
66
+ madeleine.execute_command(Click.new)
67
+ label.text("Last clicked " + clicker.last_clicked)
68
+ }
69
+ pack
70
+ }
71
+
72
+ Tk.mainloop
73
+
@@ -0,0 +1,23 @@
1
+ #
2
+ # Dictionary client
3
+ #
4
+ # See dictionary_server.rb for details
5
+ #
6
+
7
+ require 'drb'
8
+
9
+ DRb.start_service
10
+ dictionary = DRbObject.new(nil, "druby://localhost:1234")
11
+
12
+ if ARGV.length == 1
13
+ puts dictionary.lookup(ARGV[0])
14
+ elsif ARGV.length == 2
15
+ dictionary.add(ARGV[0], ARGV[1])
16
+ puts "Stored"
17
+ else
18
+ puts "Usage: dictionary_client <key> [<value>]"
19
+ end
20
+
21
+
22
+
23
+
@@ -0,0 +1,94 @@
1
+ #
2
+ # A dictionary server using Distributed Ruby (DRb).
3
+ #
4
+ # All modifications to the dictionary are done as commands,
5
+ # while read-only queries (i.e 'lookup') are done directly.
6
+ #
7
+ # First launch this server in the background, then use
8
+ # dictionary_client.rb to look up and add items to the
9
+ # dictionary.
10
+ # You can kill the server at any time. The contents of the
11
+ # dictionary will still be there when you restart it.
12
+ #
13
+ # DRb is available at http://raa.ruby-lang.org/list.rhtml?name=druby
14
+ #
15
+
16
+ $LOAD_PATH.unshift(".." + File::SEPARATOR + "lib")
17
+ require 'madeleine'
18
+
19
+ require 'drb'
20
+
21
+
22
+ class Dictionary
23
+ def initialize
24
+ @data = {}
25
+ end
26
+
27
+ def add(key, value)
28
+ @data[key] = value
29
+ end
30
+
31
+ def lookup(key)
32
+ @data[key]
33
+ end
34
+ end
35
+
36
+
37
+ class Addition
38
+ def initialize(key, value)
39
+ @key, @value = key, value
40
+ end
41
+
42
+ def execute(system)
43
+ system.add(@key, @value)
44
+ end
45
+ end
46
+
47
+
48
+ class Lookup
49
+ def initialize(key)
50
+ @key = key
51
+ end
52
+
53
+ def execute(system)
54
+ system.lookup(@key)
55
+ end
56
+ end
57
+
58
+
59
+ class DictionaryServer
60
+
61
+ def initialize(madeleine)
62
+ @madeleine = madeleine
63
+ @dictionary = madeleine.system
64
+ end
65
+
66
+ def add(key, value)
67
+ # When adding a new key-value pair we modify the system, so
68
+ # this operation has to be done through a command.
69
+ @madeleine.execute_command(Addition.new(key, value))
70
+ end
71
+
72
+ def lookup(key)
73
+ # A lookup is a read-only operation, so we can do it as a non-logged
74
+ # query. If we weren't worried about concurrency problems we could
75
+ # have just called @dictionary.lookup(key) directly instead.
76
+ @madeleine.execute_query(Lookup.new(key))
77
+ end
78
+ end
79
+
80
+
81
+ madeleine = SnapshotMadeleine.new("dictionary-base") { Dictionary.new }
82
+
83
+ Thread.new(madeleine) {
84
+ puts "Taking snapshot every 30 seconds."
85
+ while true
86
+ sleep(30)
87
+ madeleine.take_snapshot
88
+ end
89
+ }
90
+
91
+ DRb.start_service("druby://localhost:1234",
92
+ DictionaryServer.new(madeleine))
93
+ DRb.thread.join
94
+
@@ -0,0 +1,60 @@
1
+ #
2
+ # Simple drawing program to show Madeleine's logging feature.
3
+ #
4
+ # When you restart the program, your old artwork is still there.
5
+ #
6
+ # (Note: The GUI components used here aren't marshal-able,
7
+ # so in a real app you would have to do custom marshaling for
8
+ # the Painter class to get working snapshots. Then again, in a real
9
+ # app you wouldn't use the GUI components to hold the app's data,
10
+ # would you?)
11
+ #
12
+
13
+ $LOAD_PATH.unshift(".." + File::SEPARATOR + "lib")
14
+
15
+ require 'madeleine'
16
+
17
+ require 'tkclass'
18
+
19
+ class Painter
20
+
21
+ def initialize(canvas)
22
+ @canvas = canvas
23
+ end
24
+
25
+ def draw(x, y)
26
+ line = Line.new(@canvas, x, y, x + 1, y + 1)
27
+ line.fill('black')
28
+ end
29
+ end
30
+
31
+ class PaintCommand
32
+
33
+ def initialize(x, y)
34
+ @x, @y = x, y
35
+ end
36
+
37
+ def execute(system)
38
+ system.draw(@x, @y)
39
+ end
40
+ end
41
+
42
+ root = TkRoot.new() { title "Madeleine Painter" }
43
+ canvas = Canvas.new(root)
44
+ canvas.pack
45
+
46
+ $madeleine = Madeleine::SnapshotMadeleine.new("painter-demo") { Painter.new(canvas) }
47
+
48
+ canvas.bind("1",
49
+ proc {|x, y|
50
+ $madeleine.execute_command(PaintCommand.new(x, y))
51
+ },
52
+ "%x %y")
53
+ canvas.bind("B1-Motion",
54
+ proc {|x, y|
55
+ $madeleine.execute_command(PaintCommand.new(x, y))
56
+ },
57
+ "%x %y")
58
+
59
+ Tk.mainloop
60
+
metadata ADDED
@@ -0,0 +1,53 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.4
3
+ specification_version: 1
4
+ name: madeleine
5
+ version: !ruby/object:Gem::Version
6
+ version: 0.7.1
7
+ date: 2005-01-06
8
+ summary: Madeleine is a Ruby implementation of Object Prevalence
9
+ require_paths:
10
+ - lib
11
+ email: ndrsbngtssn@yahoo.se
12
+ homepage: http://madeleine.sourceforge.net
13
+ rubyforge_project:
14
+ description:
15
+ autorequire: madeleine
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: false
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ -
22
+ - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: 1.8.1
25
+ version:
26
+ platform: ruby
27
+ authors:
28
+ - Anders Bengtsson
29
+ files:
30
+ - lib/madeleine.rb
31
+ - lib/madeleine/automatic.rb
32
+ - lib/madeleine/clock.rb
33
+ - lib/madeleine/files.rb
34
+ - lib/madeleine/zmarshal.rb
35
+ - samples/clock_click.rb
36
+ - samples/dictionary_client.rb
37
+ - samples/dictionary_server.rb
38
+ - samples/painter.rb
39
+ - contrib/batched.rb
40
+ - contrib/benchmark.rb
41
+ - contrib/test_batched.rb
42
+ - contrib/test_scalability.rb
43
+ - contrib/threaded_benchmark.rb
44
+ - README
45
+ - NEWS
46
+ - COPYING
47
+ test_files: []
48
+ rdoc_options: []
49
+ extra_rdoc_files: []
50
+ executables: []
51
+ extensions: []
52
+ requirements: []
53
+ dependencies: []