tupelo 0.12 → 0.13

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: dc4bce707ea05097c67e685d20435968d326daaf
4
- data.tar.gz: 02a62f5ed3513d411b0e3bbd4b6d21af08b06c58
3
+ metadata.gz: 8a657d2c56962432faa339d693f6856f409249f6
4
+ data.tar.gz: 64a58b3ab627151aeb2fc8965de21a39c1ebf3f6
5
5
  SHA512:
6
- metadata.gz: 843a155e6e411c6ff9da110b83cfae4c69fa53b06abd0b34b0aa4f469bd97447e58e08091a3009b49d914615547dee9c5f3f3a84e1e0c89481b6184c8f429581
7
- data.tar.gz: 74fd680cd05b27977afc4958eeea19311dcf11120e1d3c2232371e8abda0f275ffc3f9204cb3197412cbb08664c9fc37a789b43c7341a716b00a1f0fc8261fe3
6
+ metadata.gz: 7ea7042705c178a855d4d9ad621c2b65433d0adb4ff7dd75ee855f75d4b53d2bc4301ea91f3491bfaf2847294076a9edffa176290192d004488bdf87caa0b016
7
+ data.tar.gz: 7e371d515db7f86bd95c353fcd5153efd5d1f34ba6edb0c75b7602994309509615f602ba7463729326f3c8d3aa55ba290e67c0e24fac07e917d61e72d668b886
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- **NEWS**: Come hear a talk on Tupelo on December 11 in San Francisco at the [SF Distributed Computing meetup](http://www.meetup.com/San-Francisco-Distributed-Computing). Location is TBD. Abstract: [doc/sfdc.txt](doc/sfdc.txt).
1
+ **NEWS**: Come hear a talk on Tupelo on December 11 in San Francisco at the [SF Distributed Computing meetup](http://www.meetup.com/San-Francisco-Distributed-Computing/events/153886592/). Abstract: [doc/sfdc.txt](doc/sfdc.md).
2
2
 
3
3
  tupelo
4
4
  ==
@@ -93,6 +93,11 @@ Getting started
93
93
 
94
94
  reads all 2-tuples.
95
95
 
96
+ Read tuples in a stream, both existing and as they arrive:
97
+
98
+ read <template> do |tuple| ... end
99
+ read do |tuple| ... end # match any tuple
100
+
96
101
  Take a tuple matching a template:
97
102
 
98
103
  t <template>
@@ -0,0 +1,35 @@
1
+ # more like how you would do it in redis, except that the queue is not stored in
2
+ # the central server, so operations on it are not a bottleneck, FWIW
3
+
4
+ require 'tupelo/app'
5
+
6
+ N_PLAYERS = 10
7
+
8
+ Tupelo.application do
9
+ N_PLAYERS.times do
10
+ # sleep rand / 10 # reduce contention -- could also randomize inserts
11
+ child do
12
+ me = client_id
13
+ write name: me
14
+
15
+ you = transaction do
16
+ game = read_nowait(
17
+ player1: nil,
18
+ player2: me)
19
+ break game["player1"] if game
20
+
21
+ unless take_nowait name: me
22
+ raise Tupelo::Client::TransactionFailure
23
+ end
24
+
25
+ you = take(name: nil)["name"]
26
+ write(
27
+ player1: me,
28
+ player2: you)
29
+ you
30
+ end
31
+
32
+ log "now playing with #{you}"
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,33 @@
1
+ # Same as chat.rb, but no messages are stored.
2
+
3
+ require 'tupelo/app'
4
+
5
+ svr = "chat-nohistory.yaml"
6
+
7
+ Thread.abort_on_exception = true
8
+
9
+ def display_message msg
10
+ from, time, line = msg.values_at(*%w{from time line})
11
+ time_str = Time.at(time).strftime("%I:%M:%S")
12
+ print "\r\033[2K" # Esc[2K is "Clear entire line"
13
+ puts "#{from}@#{time_str}> #{line}"
14
+ end
15
+
16
+ Tupelo.tcp_application servers_file: svr do
17
+ me = argv.shift
18
+
19
+ local do
20
+ require 'readline'
21
+
22
+ Thread.new do
23
+ read from: nil, line: nil, time: nil do |msg|
24
+ display_message msg
25
+ Readline.refresh_line
26
+ end
27
+ end
28
+
29
+ while line = Readline.readline("#{me}> ", true)
30
+ pulse from: me, line: line, time: Time.now.to_f
31
+ end
32
+ end
33
+ end
data/example/chat/chat.rb CHANGED
@@ -22,7 +22,8 @@ Thread.abort_on_exception = true
22
22
 
23
23
  def display_message msg
24
24
  from, time, line = msg.values_at(*%w{from time line})
25
- time_str = Time.at(time).strftime("%I:%M.%S")
25
+ time_str = Time.at(time).strftime("%I:%M:%S")
26
+ print "\r\033[2K" # Esc[2K is "Clear entire line"
26
27
  puts "#{from}@#{time_str}> #{line}"
27
28
  end
28
29
 
@@ -33,15 +34,9 @@ Tupelo.tcp_application servers_file: svr do
33
34
  require 'readline'
34
35
 
35
36
  Thread.new do
36
- seen_at_start = {}
37
- read_all(from: nil, line: nil, time: nil).
38
- sort_by {|msg| msg["time"]}.
39
- each {|msg| display_message msg; seen_at_start[msg] = true}
40
-
41
37
  read from: nil, line: nil, time: nil do |msg|
42
- next if msg["from"] == me or seen_at_start[msg]
43
- print "\r"; display_message msg
44
- Readline.redisplay ### why not u work?
38
+ display_message msg
39
+ Readline.refresh_line
45
40
  end
46
41
  end
47
42
 
@@ -0,0 +1,34 @@
1
+ require 'tupelo/app'
2
+
3
+ ### need a programmatic way to start up clients
4
+
5
+ Tupelo.application do |app|
6
+
7
+ app.child do ## local still hangs
8
+ 3.times do |i|
9
+ app.child do
10
+ write [i]
11
+ log "wrote #{i}"
12
+ end
13
+ end
14
+
15
+ 3.times do
16
+ log take [nil]
17
+ end
18
+ end
19
+ end
20
+
21
+ __END__
22
+
23
+ this hangs sometimes but not always:
24
+
25
+ tick cid status operation
26
+ A: client 3: wrote 0
27
+ A: client 4: wrote 1
28
+ 1 3 batch write [0]
29
+ 2 4 batch write [1]
30
+ A: client 2: [0]
31
+ 3 2 atomic take [0]
32
+ 4 2 atomic take [1]
33
+ A: client 2: [1]
34
+ A: client 5: wrote 2
data/example/fish01.rb ADDED
@@ -0,0 +1,48 @@
1
+ # This works, but requires a fix-up step.
2
+
3
+ require 'tupelo/app'
4
+
5
+ Tupelo.application do
6
+ 2.times do
7
+ child passive: true do
8
+ loop do
9
+ fish = nil
10
+
11
+ transaction do
12
+ fish, _ = take([String])
13
+ n, _ = take_nowait([Integer, fish])
14
+ if n
15
+ write [n + 1, fish]
16
+ else
17
+ write [1, fish] # another process might also write this, so ...
18
+ end
19
+ end
20
+ ### what if both processes die here?
21
+ transaction do # ... fix up the two tuples.
22
+ n1, _ = take_nowait [Integer, fish]; abort unless n1
23
+ n2, _ = take_nowait [Integer, fish]; abort unless n2
24
+ #log "fixing: #{[n1 + n2, fish]}"
25
+ write [n1 + n2, fish]
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ local do
32
+ seed = 3
33
+ srand seed
34
+ log "seed = #{seed}"
35
+
36
+ fishes = %w{ trout marlin char salmon }
37
+
38
+ a = fishes * 10
39
+ a.shuffle!
40
+ a.each do |fish|
41
+ write [fish]
42
+ end
43
+
44
+ fishes.each do |fish|
45
+ log take [10, fish]
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,15 @@
1
+ #
2
+ # Minor optimization:
3
+
4
+ class KeyMatcher
5
+ def initialize i, n
6
+ @i = i
7
+ @n = n
8
+ end
9
+
10
+ def === id
11
+ id % @n == @i
12
+ end
13
+ end
14
+
15
+ vertex = take id: v_id_matcher, step: step, rank: nil, active: true
@@ -0,0 +1,106 @@
1
+ ## TODO
2
+ ##
3
+ ## scaling params
4
+
5
+ require 'tupelo/app'
6
+
7
+ ab_tag = "my address book"
8
+ ab_sort_field = 1
9
+ ab_val_field = 2
10
+ cmd_tag = "#{ab_tag} commands"
11
+ resp_tag = "#{ab_tag} responses"
12
+
13
+ Tupelo.application do
14
+ local do
15
+ use_subspaces!
16
+
17
+ # Subspace for tuples belonging to the addr book.
18
+ define_subspace(
19
+ tag: ab_tag,
20
+ template: [
21
+ {value: ab_tag},
22
+ {type: "string"}, # name <-- ab_sort_field references this field
23
+ nil # address; can be any object <-- ab_val_field
24
+ ]
25
+ )
26
+
27
+ # Subspace for commands for fetch and delete.
28
+ # We can't use #read and #take because then the requesting client
29
+ # would have to subscribe to the ab_tag subspace.
30
+ define_subspace(
31
+ tag: cmd_tag,
32
+ template: [
33
+ {value: cmd_tag},
34
+ {type: "string"}, # cmd name
35
+ {type: "list"} # arguments
36
+ ]
37
+ )
38
+
39
+ # Subspace for responses to commands. Identify the command this is in
40
+ # response to by copying it (alternately, could use ids).
41
+ define_subspace(
42
+ tag: resp_tag,
43
+ template: [
44
+ {value: resp_tag},
45
+ {type: "string"}, # cmd name
46
+ {type: "list"}, # arguments
47
+ nil # result of query -- type depends on command
48
+ ]
49
+ )
50
+ end
51
+
52
+ ## Could set N_SORTED_SET_SPACE > 1, but lookups are so fast it would
53
+ ## just lead to contention and redundant computation. Redundancy is useful
54
+ ## though.
55
+
56
+ # Inserts are just writes, which are handled by Worker and SortedSetSpace,
57
+ # so this child's app loop only needs to handle special commands: fetch and
58
+ # delete, which are delegated to the SortedSetSpace.
59
+ child tuplespace: [SortedSetSpace, ab_tag, ab_sort_field, ab_val_field],
60
+ subscribe: [ab_tag, cmd_tag], passive: true do
61
+ loop do
62
+ transaction do
63
+ _, cmd, args = take(subspace cmd_tag)
64
+
65
+ case cmd
66
+ when "delete"
67
+ args.each do |name|
68
+ take [ab_tag, name, nil]
69
+ end
70
+
71
+ when "fetch"
72
+ name = args[0]
73
+ _, _, addr = read [ab_tag, name, nil]
74
+ write [resp_tag, name, args, addr]
75
+
76
+ when "next", "prev"
77
+ name = args[0]
78
+ _, name2, addr = read SortedSetTemplate[ab_tag, cmd, name]
79
+ write [resp_tag, name, args, name2, addr]
80
+
81
+ when "first", "last"
82
+ _, name, addr = read SortedSetTemplate[ab_tag, cmd]
83
+ write [resp_tag, name, args, name, addr]
84
+
85
+ else # maybe write an error message in a tuple
86
+ log.error "bad command: #{cmd}"
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+ child subscribe: resp_tag do
93
+ # write some ab entries
94
+ write [ab_tag, "McFirst, Firsty", "123 W. Crescent Terrace"]
95
+ write [ab_tag, "Secondismus, Deuce", "456 S. West Way"]
96
+
97
+ # make some queries
98
+ write [cmd_tag, "first", []]
99
+ *, name, addr = take [resp_tag, "first", [], nil, nil]
100
+ log "first entry: #{name} => #{addr}"
101
+
102
+ write [cmd_tag, "next", [name]]
103
+ *, name, addr = take [resp_tag, "next", [name], nil, nil]
104
+ log "next entry: #{name} => #{addr}"
105
+ end
106
+ end
@@ -0,0 +1,18 @@
1
+ require 'tupelo/app'
2
+
3
+ Tupelo.application do
4
+ local do
5
+ use_subspaces!
6
+
7
+ define_subspace(
8
+ tag: "address books",
9
+ template: {
10
+ book: {type: "string"},
11
+ name: {type: "string"},
12
+ address: nil
13
+ }
14
+ )
15
+
16
+ define_subspace
17
+ end
18
+ end
@@ -0,0 +1,130 @@
1
+ require 'rbtree'
2
+
3
+ class SortedSetTemplate
4
+ class << self
5
+ alias [] new
6
+ end
7
+
8
+ # cmd can be "next", "prev", "first", "last"
9
+ # for next/prev, args is ["name"]
10
+ # for first/last, args is empty
11
+ def initialize tag, cmd, *args
12
+ @tag = tag
13
+ @cmd = cmd
14
+ @args = args
15
+ end
16
+
17
+ def === other
18
+ raise ### should not need this?
19
+ end
20
+
21
+ def find_in rbtree
22
+ case @cmd
23
+ when "first"
24
+ rbtree.first
25
+ ###
26
+ end
27
+ end
28
+
29
+ # A tuple store (in-memory) that is optimized for (key_string, object) pairs.
30
+ # The object may be any serializable object (built up from numbers, booleans,
31
+ # nil, strings, hashes and arrays).
32
+ #
33
+ # Unlike in a key-value store, a given key_string may occur more than once.
34
+ # It is up to the application to decide whether to enforce key uniqueness or
35
+ # not (for example, by taking (k,...) before writing (k,v).
36
+ #
37
+ # This store should be used only by clients that subscribe to a subspace
38
+ # that can be represented as pairs. (See memo2.rb.)
39
+ #
40
+ # This store also manages meta tuples, which it keeps in an array, just like
41
+ # the default Tuplespace class does.
42
+ class SortedSetSpace
43
+ include Enumerable
44
+
45
+ attr_reader :tag, :hash, :metas
46
+
47
+ def initialize tag
48
+ @tag = tag
49
+ clear
50
+ end
51
+
52
+ def clear
53
+ @hash = Hash.new {|h,k| h[k] = []}
54
+ # It's up to the application to enforce that these arrays have size <=1.
55
+ @metas = []
56
+ # We are automatically subscribed to tupelo metadata (subspace defs), so
57
+ # we need to keep them somewhere.
58
+ end
59
+
60
+ def each
61
+ hash.each do |k, vs|
62
+ vs.each do |v|
63
+ yield tag, k, v
64
+ end
65
+ end
66
+ metas.each do |tuple|
67
+ yield tuple
68
+ end
69
+ end
70
+
71
+ def insert tuple
72
+ if tuple.kind_of? Array
73
+ # and tuple.size == 3 and tuple[0] == tag and tuple[1].kind_of? String
74
+ # This is redundant, because of subscribe.
75
+ t, k, v = tuple
76
+ hash[k] << v
77
+
78
+ else
79
+ metas << tuple
80
+ end
81
+ end
82
+
83
+ def delete_once tuple
84
+ if tuple.kind_of? Array
85
+ # and tuple.size == 3 and tuple[0] == tag and tuple[1].kind_of? String
86
+ # This is redundant, because of subscribe.
87
+ t, k, v = tuple
88
+ if hash.key?(k) and hash[k].include? v
89
+ hash[k].delete v
90
+ hash.delete k if hash[k].empty?
91
+ true
92
+ else
93
+ false
94
+ end
95
+
96
+ else
97
+ if i=metas.index(tuple)
98
+ delete_at i
99
+ end
100
+ end
101
+ end
102
+
103
+ def transaction inserts: [], deletes: [], tick: nil
104
+ deletes.each do |tuple|
105
+ delete_once tuple or raise "bug"
106
+ end
107
+
108
+ inserts.each do |tuple|
109
+ insert tuple.freeze ## should be deep_freeze
110
+ end
111
+ end
112
+
113
+ def find_distinct_matches_for templates
114
+ templates.inject([]) do |tuples, template|
115
+ tuples << find_match_for(template, distinct_from: tuples)
116
+ end
117
+ end
118
+
119
+ def find_match_for template, distinct_from: []
120
+ case template
121
+ when SortedSetTemplate
122
+ template.find_in rbtree, distinct_from: distinct_from ###
123
+ else
124
+ # fall back to linear search
125
+ find do |tuple|
126
+ template === tuple and not distinct_from.any? {|t| t.equal? tuple}
127
+ end
128
+ end
129
+ end
130
+ end
@@ -3,10 +3,14 @@ require 'tupelo/client/common'
3
3
  class Tupelo::Client
4
4
  # Include into class that defines #worker and #log.
5
5
  module Api
6
- # If block given, yield matching tuple to the block if one is found
7
- # locally and then yield each new tuple as it arrives.
8
- # Otherwise, return one matching tuple, blocking if necessary.
9
- def read_wait template
6
+ # If no block given, return one matching tuple, blocking if necessary.
7
+ # If block given, yield each matching tuple that is found
8
+ # locally and then yield each new match as it is written to the space.
9
+ # Guaranteed not to miss tuples, even if they arrive and are immediately
10
+ # taken. (Note that simply doing read(template) in a loop would not
11
+ # have this guarantee.)
12
+ # The template defaults to Object, which matches any tuple.
13
+ def read_wait template = Object
10
14
  waiter = Waiter.new(worker.make_template(template), self, !block_given?)
11
15
  worker << waiter
12
16
  if block_given?
@@ -23,13 +27,16 @@ class Tupelo::Client
23
27
  end
24
28
  alias read read_wait
25
29
 
26
- def read_nowait template
30
+ # The template defaults to Object, which matches any tuple.
31
+ def read_nowait template = Object
27
32
  matcher = Matcher.new(worker.make_template(template), self)
28
33
  worker << matcher
29
34
  matcher.wait
30
35
  end
31
36
 
32
- # By default, reads *everything*.
37
+ # Returns all matching tuples currently in the space. The template defaults
38
+ # to Object, which matches any tuple. Does not wait for more tuples to
39
+ # arrive.
33
40
  def read_all template = Object
34
41
  matcher = Matcher.new(worker.make_template(template), self, :all => true)
35
42
  worker << matcher
@@ -507,13 +507,15 @@ class Tupelo::Client
507
507
  end
508
508
 
509
509
  def handle_waiter waiter
510
- tuple = tuplespace.find_match_for waiter.template
511
- if tuple
512
- once = waiter.peek tuple
513
- unless once
510
+ if waiter.once
511
+ tuple = tuplespace.find_match_for waiter.template
512
+ if tuple
513
+ waiter.peek tuple
514
+ else
514
515
  read_waiters << waiter
515
516
  end
516
517
  else
518
+ tuplespace.each {|tuple| waiter.gloms tuple}
517
519
  read_waiters << waiter
518
520
  end
519
521
  end
@@ -1,3 +1,3 @@
1
1
  module Tupelo
2
- VERSION = "0.12"
2
+ VERSION = "0.13"
3
3
  end
@@ -86,6 +86,30 @@ class TestOps < Minitest::Test
86
86
  end
87
87
  end
88
88
 
89
+ def test_read_stream
90
+ writer, reader = make_clients(2)
91
+ a = []
92
+ n = 10; k = 3
93
+
94
+ (0...k).each do |i|
95
+ writer.now {write [i]}
96
+ end
97
+
98
+ reader.will {read([nil]){|t| a << t}}
99
+
100
+ (0...k).each do |i|
101
+ reader.run_until_blocked
102
+ assert_equal [i], a[i]
103
+ end
104
+
105
+ assert_equal [0], a[0]
106
+ (k...n).each do |i|
107
+ writer.now {write [i]}
108
+ reader.run_until_blocked
109
+ assert_equal [i], a[i]
110
+ end
111
+ end
112
+
89
113
  def test_take_existing
90
114
  t = ["foo"]
91
115
  cl = make_clients(2)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tupelo
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.12'
4
+ version: '0.13'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Joel VanderWerf
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-03 00:00:00.000000000 Z
11
+ date: 2013-12-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: atdo
@@ -84,111 +84,119 @@ files:
84
84
  - lib/tupelo/app/trace.rb
85
85
  - lib/tupelo/app/builder.rb
86
86
  - lib/tupelo/client.rb
87
- - lib/tupelo/tuplets/persistent-archiver.rb
88
- - lib/tupelo/tuplets/persistent-archiver/worker.rb
89
- - lib/tupelo/tuplets/persistent-archiver/tuplespace.rb
90
- - lib/tupelo/util/boolean.rb
91
87
  - lib/tupelo/app.rb
92
88
  - lib/tupelo/archiver.rb
89
+ - lib/tupelo/client/worker.rb
90
+ - lib/tupelo/client/common.rb
91
+ - lib/tupelo/client/tuplespace.rb
92
+ - lib/tupelo/client/transaction.rb
93
+ - lib/tupelo/client/atdo.rb
94
+ - lib/tupelo/client/reader.rb
95
+ - lib/tupelo/tuplets/persistent-archiver/worker.rb
96
+ - lib/tupelo/tuplets/persistent-archiver/tuplespace.rb
97
+ - lib/tupelo/tuplets/persistent-archiver.rb
93
98
  - lib/tupelo/archiver/persister.rb
94
99
  - lib/tupelo/archiver/worker.rb
95
100
  - lib/tupelo/archiver/tuplespace.rb
96
101
  - lib/tupelo/archiver/persistent-tuplespace.rb
97
- - lib/tupelo/client/transaction.rb
98
- - lib/tupelo/client/worker.rb
99
- - lib/tupelo/client/reader.rb
100
- - lib/tupelo/client/tuplespace.rb
101
- - lib/tupelo/client/atdo.rb
102
- - lib/tupelo/client/common.rb
102
+ - lib/tupelo/util/boolean.rb
103
103
  - lib/tupelo/version.rb
104
104
  - bench/pipeline.rb
105
105
  - bugs/read-take.rb
106
106
  - bugs/take-write.rb
107
+ - example/pubsub.rb
108
+ - example/timeout-trans.rb
109
+ - example/fish01.rb
110
+ - example/tiny-client.rb
111
+ - example/add.rb
112
+ - example/parallel.rb
113
+ - example/socket-broker.rb
114
+ - example/multi-tier/memo2.rb
115
+ - example/multi-tier/drb.rb
116
+ - example/multi-tier/memo.rb
117
+ - example/multi-tier/kvspace.rb
118
+ - example/multi-tier/http.rb
119
+ - example/multi-tier/multi-sinatras.rb
120
+ - example/app-and-tup.rb
121
+ - example/small.rb
122
+ - example/bounded-retry.rb
123
+ - example/fish.rb
124
+ - example/zk/lock.rb
125
+ - example/concurrent-transactions.rb
126
+ - example/cancel.rb
127
+ - example/map-reduce/map-reduce-v2.rb
128
+ - example/map-reduce/remote-map-reduce.rb
129
+ - example/map-reduce/map-reduce.rb
130
+ - example/tiny-server.rb
131
+ - example/write-wait.rb
132
+ - example/tcp.rb
107
133
  - example/timeout.rb
134
+ - example/read-in-trans.rb
135
+ - example/subspaces/simple.rb
136
+ - example/subspaces/pubsub.rb
137
+ - example/subspaces/addr-book-v1.rb
138
+ - example/subspaces/addr-book-v2.rb
139
+ - example/subspaces/shop/shop-v2.rb
140
+ - example/subspaces/shop/shop-v1.rb
141
+ - example/subspaces/sorted-set-space.rb
142
+ - example/balance-xfer-retry.rb
143
+ - example/take-nowait-caution.rb
144
+ - example/lock-mgr-with-queue.rb
145
+ - example/hash-tuples.rb
146
+ - example/pulse.rb
147
+ - example/transaction-logic.rb
148
+ - example/lease.rb
149
+ - example/chat/chat.rb
150
+ - example/chat/chat-nohistory.rb
151
+ - example/balance-xfer.rb
108
152
  - example/add-dsl.rb
109
- - example/remote.rb
110
- - example/increment.rb
111
- - example/matching.rb
112
- - example/dphil.rb
113
- - example/broker-optimistic.rb
153
+ - example/lock-mgr.rb
154
+ - example/broker-locking.rb
155
+ - example/dphil-optimistic.rb
114
156
  - example/fail-and-retry.rb
115
- - example/load-balancer.rb
116
- - example/read-in-trans.rb
117
- - example/bounded-retry.rb
118
- - example/pregel/remote.rb
119
- - example/pregel/pagerank.rb
157
+ - example/fish0.rb
120
158
  - example/pregel/pregel.rb
121
159
  - example/pregel/distributed.rb
160
+ - example/pregel/pagerank.rb
122
161
  - example/pregel/update.rb
162
+ - example/pregel/remote.rb
163
+ - example/pregel/dist-opt.rb
164
+ - example/dphil-optimistic-v2.rb
165
+ - example/broker-optimistic-v2.rb
166
+ - example/remote.rb
123
167
  - example/take-nowait.rb
124
- - example/boolean-match.rb
125
- - example/lease.rb
126
- - example/broker-locking.rb
127
- - example/transaction-logic.rb
168
+ - example/wait-interrupt.rb
169
+ - example/optimist.rb
128
170
  - example/message-bus.rb
129
- - example/small-simplified.rb
130
- - example/small.rb
131
- - example/lock-mgr.rb
132
- - example/take-nowait-caution.rb
133
- - example/concurrent-transactions.rb
134
- - example/tcp.rb
135
- - example/notify.rb
136
- - example/pulse.rb
137
- - example/chat/chat.rb
138
- - example/hash-tuples.rb
139
171
  - example/balance-xfer-locking.rb
140
- - example/balance-xfer-retry.rb
172
+ - example/increment.rb
173
+ - example/child-of-child.rb
174
+ - example/custom-class.rb
175
+ - example/matching.rb
141
176
  - example/custom-search.rb
142
- - example/app-and-tup.rb
143
- - example/multi-tier/memo2.rb
144
- - example/multi-tier/http.rb
145
- - example/multi-tier/multi-sinatras.rb
146
- - example/multi-tier/kvspace.rb
147
- - example/multi-tier/memo.rb
148
- - example/multi-tier/drb.rb
149
- - example/take-many.rb
150
- - example/subspaces/simple.rb
151
- - example/subspaces/shop/shop-v2.rb
152
- - example/subspaces/shop/shop-v1.rb
153
- - example/subspaces/pubsub.rb
154
- - example/dphil-optimistic.rb
177
+ - example/broker-optimistic.rb
178
+ - example/notify.rb
179
+ - example/small-simplified.rb
180
+ - example/broker-queue.rb
155
181
  - example/async-transaction.rb
156
- - example/wait-interrupt.rb
157
- - example/fish0.rb
158
- - example/zk/lock.rb
182
+ - example/boolean-match.rb
183
+ - example/load-balancer.rb
184
+ - example/take-many.rb
159
185
  - example/deadlock.rb
160
- - example/fish.rb
161
- - example/add.rb
162
- - example/dphil-optimistic-v2.rb
163
- - example/parallel.rb
164
- - example/tiny-client.rb
165
- - example/map-reduce/map-reduce.rb
166
- - example/map-reduce/remote-map-reduce.rb
167
- - example/map-reduce/map-reduce-v2.rb
168
- - example/lock-mgr-with-queue.rb
169
- - example/balance-xfer.rb
170
- - example/cancel.rb
171
- - example/socket-broker.rb
172
- - example/timeout-trans.rb
173
- - example/optimist.rb
174
- - example/tiny-server.rb
175
- - example/pubsub.rb
176
- - example/broker-optimistic-v2.rb
177
- - example/write-wait.rb
178
- - example/custom-class.rb
179
- - test/stress/archiver-load.rb
180
- - test/stress/concurrent-transactions.rb
181
- - test/system/test-archiver.rb
182
- - test/lib/mock-client.rb
183
- - test/lib/time-fuzz.rb
184
- - test/lib/mock-queue.rb
185
- - test/lib/mock-seq.rb
186
+ - example/dphil.rb
186
187
  - test/lib/testable-worker.rb
188
+ - test/lib/mock-seq.rb
187
189
  - test/lib/mock-msg.rb
188
- - test/unit/test-mock-seq.rb
189
- - test/unit/test-mock-queue.rb
190
+ - test/lib/mock-queue.rb
191
+ - test/lib/time-fuzz.rb
192
+ - test/lib/mock-client.rb
193
+ - test/system/test-archiver.rb
190
194
  - test/unit/test-ops.rb
191
195
  - test/unit/test-mock-client.rb
196
+ - test/unit/test-mock-seq.rb
197
+ - test/unit/test-mock-queue.rb
198
+ - test/stress/concurrent-transactions.rb
199
+ - test/stress/archiver-load.rb
192
200
  - bin/tup
193
201
  - bin/tspy
194
202
  homepage: https://github.com/vjoel/tupelo
@@ -223,8 +231,8 @@ signing_key:
223
231
  specification_version: 4
224
232
  summary: Distributed tuplespace
225
233
  test_files:
226
- - test/unit/test-mock-seq.rb
227
- - test/unit/test-mock-queue.rb
228
234
  - test/unit/test-ops.rb
229
235
  - test/unit/test-mock-client.rb
236
+ - test/unit/test-mock-seq.rb
237
+ - test/unit/test-mock-queue.rb
230
238
  has_rdoc: