higgs 0.1.4 → 0.1.5

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.
@@ -1,15 +1,14 @@
1
1
  # = transactional storage core
2
2
  #
3
3
  # Author:: $Author: toki $
4
- # Date:: $Date: 2007-11-11 11:07:25 +0900 (Sun, 11 Nov 2007) $
5
- # Revision:: $Revision: 681 $
4
+ # Date:: $Date: 2008-01-14 00:55:53 +0900 (Mon, 14 Jan 2008) $
5
+ # Revision:: $Revision: 742 $
6
6
  #
7
7
  # == license
8
8
  # :include:LICENSE
9
9
  #
10
10
 
11
11
  require 'digest'
12
- require 'forwardable'
13
12
  require 'higgs/block'
14
13
  require 'higgs/cache'
15
14
  require 'higgs/flock'
@@ -24,9 +23,8 @@ module Higgs
24
23
  # = transactional storage core
25
24
  class Storage
26
25
  # for ident(1)
27
- CVS_ID = '$Id: storage.rb 681 2007-11-11 02:07:25Z toki $'
26
+ CVS_ID = '$Id: storage.rb 742 2008-01-13 15:55:53Z toki $'
28
27
 
29
- extend Forwardable
30
28
  include Exceptions
31
29
 
32
30
  class Error < HiggsError
@@ -193,6 +191,9 @@ module Higgs
193
191
  @panic = false
194
192
  @shutdown = false
195
193
 
194
+ @cnum_lock = Mutex.new
195
+ @saved_change_number = nil
196
+
196
197
  init_options(options)
197
198
 
198
199
  init_completed = false
@@ -591,6 +592,7 @@ module Higgs
591
592
  eoa = @index.eoa
592
593
 
593
594
  begin
595
+ @cnum_lock.synchronize{ @saved_change_number = @index.change_number }
594
596
  @index.succ!
595
597
  @logger.debug("index succ: #{@index.change_number}") if @logger.debug?
596
598
  commit_log << { :ope => :succ, :cnum => @index.change_number }
@@ -770,6 +772,7 @@ module Higgs
770
772
  @logger.error("panic: failed to commit.")
771
773
  @logger.error($!) if $!
772
774
  end
775
+ @cnum_lock.synchronize{ @saved_change_number = nil }
773
776
  end
774
777
 
775
778
  @logger.debug("completed raw_write_and_commit.") if @logger.debug?
@@ -1107,12 +1110,13 @@ module Higgs
1107
1110
  value
1108
1111
  end
1109
1112
 
1110
- def string_only(key)
1111
- properties = fetch_properties(key) or raise IndexError, "not exist properties at key: #{key}"
1112
- properties['system_properties']['string_only']
1113
+ def identity(key)
1114
+ @index.identity(key)
1113
1115
  end
1114
1116
 
1115
- def_delegator :@index, :identity
1117
+ def change_number
1118
+ @cnum_lock.synchronize{ @saved_change_number || @index.change_number }
1119
+ end
1116
1120
 
1117
1121
  def data_change_number(key)
1118
1122
  i = @index[key] and i[:d][:cnum] || -1
@@ -1133,6 +1137,12 @@ module Higgs
1133
1137
  @index.key? key
1134
1138
  end
1135
1139
 
1140
+ def keys(order_by_pos=false)
1141
+ keys = @index.keys
1142
+ keys.sort!{|a, b| @index[a][:d][:pos] <=> @index[b][:d][:pos] } if order_by_pos
1143
+ keys
1144
+ end
1145
+
1136
1146
  def each_key
1137
1147
  check_read
1138
1148
  @index.each_key do |key|
@@ -1152,19 +1162,11 @@ module Higgs
1152
1162
 
1153
1163
  def verify(out=nil, verbose_level=1)
1154
1164
  check_read
1155
-
1156
- keys = @index.keys
1157
- keys.sort!{|a, b|
1158
- @index[a][:d][:pos] <=> @index[b][:d][:pos]
1159
- }
1160
-
1161
- for key in keys
1165
+ for key in keys(true)
1162
1166
  if (out && verbose_level >= 1) then
1163
1167
  out << "check #{key}\n"
1164
1168
  end
1165
-
1166
1169
  data = fetch(key)
1167
-
1168
1170
  if (out && verbose_level >= 2) then
1169
1171
  out << " #{data.length} bytes\n"
1170
1172
  properties = fetch_properties(key) or raise PanicError, "not exist properties at key: #{key}"
@@ -1174,7 +1176,6 @@ module Higgs
1174
1176
  end
1175
1177
  end
1176
1178
  end
1177
-
1178
1179
  nil
1179
1180
  end
1180
1181
 
@@ -1,8 +1,8 @@
1
1
  # = multi-thread utilities
2
2
  #
3
3
  # Author:: $Author: toki $
4
- # Date:: $Date: 2007-11-14 01:42:21 +0900 (Wed, 14 Nov 2007) $
5
- # Revision:: $Revision: 686 $
4
+ # Date:: $Date: 2008-01-14 00:55:53 +0900 (Mon, 14 Jan 2008) $
5
+ # Revision:: $Revision: 742 $
6
6
  #
7
7
  # == license
8
8
  # :include:LICENSE
@@ -15,7 +15,7 @@ require 'thread'
15
15
  module Higgs
16
16
  class Latch
17
17
  # for ident(1)
18
- CVS_ID = '$Id: thread.rb 686 2007-11-13 16:42:21Z toki $'
18
+ CVS_ID = '$Id: thread.rb 742 2008-01-13 15:55:53Z toki $'
19
19
 
20
20
  def initialize
21
21
  @lock = Mutex.new
@@ -43,7 +43,7 @@ module Higgs
43
43
 
44
44
  class CountDownLatch
45
45
  # for ident(1)
46
- CVS_ID = '$Id: thread.rb 686 2007-11-13 16:42:21Z toki $'
46
+ CVS_ID = '$Id: thread.rb 742 2008-01-13 15:55:53Z toki $'
47
47
 
48
48
  def initialize(count)
49
49
  @count = count
@@ -55,7 +55,7 @@ module Higgs
55
55
  @lock.synchronize{
56
56
  if (@count > 0) then
57
57
  @count -= 1
58
- @cond.broadcast
58
+ @cond.broadcast if (@count == 0)
59
59
  end
60
60
  }
61
61
  nil
@@ -73,7 +73,7 @@ module Higgs
73
73
 
74
74
  class Barrier
75
75
  # for ident(1)
76
- CVS_ID = '$Id: thread.rb 686 2007-11-13 16:42:21Z toki $'
76
+ CVS_ID = '$Id: thread.rb 742 2008-01-13 15:55:53Z toki $'
77
77
 
78
78
  def initialize(count)
79
79
  @count = count
@@ -102,7 +102,7 @@ module Higgs
102
102
 
103
103
  class SharedWork
104
104
  # for ident(1)
105
- CVS_ID = '$Id: thread.rb 686 2007-11-13 16:42:21Z toki $'
105
+ CVS_ID = '$Id: thread.rb 742 2008-01-13 15:55:53Z toki $'
106
106
 
107
107
  def initialize(&work)
108
108
  unless (work) then
@@ -191,7 +191,7 @@ module Higgs
191
191
 
192
192
  class ReadWriteLock
193
193
  # for ident(1)
194
- CVS_ID = '$Id: thread.rb 686 2007-11-13 16:42:21Z toki $'
194
+ CVS_ID = '$Id: thread.rb 742 2008-01-13 15:55:53Z toki $'
195
195
 
196
196
  def initialize
197
197
  @lock = Mutex.new
@@ -201,8 +201,13 @@ module Higgs
201
201
  @count_of_standby_writers = 0
202
202
  @priority_to_writer = true
203
203
  @writing = false
204
+ @read_lock = ReadLock.new(self)
205
+ @write_lock = WriteLock.new(self)
204
206
  end
205
207
 
208
+ attr_reader :read_lock
209
+ attr_reader :write_lock
210
+
206
211
  def __read_lock__
207
212
  @lock.synchronize{
208
213
  while (@writing || (@priority_to_writer && @count_of_standby_writers > 0))
@@ -313,14 +318,6 @@ module Higgs
313
318
  def_delegator :@rw_lock, :__write_unlock__, :unlock
314
319
  end
315
320
 
316
- def read_lock
317
- ReadLock.new(self)
318
- end
319
-
320
- def write_lock
321
- WriteLock.new(self)
322
- end
323
-
324
321
  def to_a
325
322
  [ read_lock, write_lock ]
326
323
  end
@@ -328,7 +325,7 @@ module Higgs
328
325
 
329
326
  class Pool
330
327
  # for ident(1)
331
- CVS_ID = '$Id: thread.rb 686 2007-11-13 16:42:21Z toki $'
328
+ CVS_ID = '$Id: thread.rb 742 2008-01-13 15:55:53Z toki $'
332
329
 
333
330
  class ShutdownException < Exceptions::ShutdownException
334
331
  end
@@ -1,8 +1,8 @@
1
1
  # = transaction manager
2
2
  #
3
3
  # Author:: $Author: toki $
4
- # Date:: $Date: 2007-11-06 00:55:14 +0900 (Tue, 06 Nov 2007) $
5
- # Revision:: $Revision: 674 $
4
+ # Date:: $Date: 2008-01-20 22:28:02 +0900 (Sun, 20 Jan 2008) $
5
+ # Revision:: $Revision: 745 $
6
6
  #
7
7
  # == license
8
8
  # :include:LICENSE
@@ -17,7 +17,7 @@ require 'singleton'
17
17
  module Higgs
18
18
  class TransactionManager
19
19
  # for ident(1)
20
- CVS_ID = '$Id: tman.rb 674 2007-11-05 15:55:14Z toki $'
20
+ CVS_ID = '$Id: tman.rb 745 2008-01-20 13:28:02Z toki $'
21
21
 
22
22
  include Exceptions
23
23
 
@@ -92,6 +92,7 @@ module Higgs
92
92
  if (@read_only == :standby && ! @jlog_apply_dir) then
93
93
  raise ArgumentError, "need for `:jlog_apply_dir' parameter in standby mode"
94
94
  end
95
+ @mvcc_cache = MVCCCache.new
95
96
  @master_cache = SharedWorkCache.new(@master_cache) {|key|
96
97
  (id = @storage.unique_data_id(key) and @secondary_cache[id]) or
97
98
  (value = @storage.fetch(key) and @secondary_cache[@storage.unique_data_id(key)] = value.freeze)
@@ -103,36 +104,23 @@ module Higgs
103
104
  def transaction(read_only=@read_only)
104
105
  r = nil
105
106
  @lock_manager.transaction(read_only) {|lock_handler|
106
- begin
107
- if (TransactionManager.in_transaction?) then
108
- raise 'nested transaction forbidden'
109
- end
107
+ @mvcc_cache.transaction(@storage.change_number) {|snapshot|
110
108
  if (read_only) then
111
- tx = ReadOnlyTransactionContext.new(lock_handler, @storage, @master_cache, @secondary_cache, @decode, @encode)
109
+ tx = ReadOnlyTransactionContext.new(lock_handler, @storage, snapshot, @master_cache, @secondary_cache, @decode, @encode)
112
110
  else
113
111
  if (@read_only) then
114
112
  raise NotWritableError, 'not writable'
115
113
  end
116
- tx = ReadWriteTransactionContext.new(lock_handler, @storage, @master_cache, @secondary_cache, @decode, @encode)
114
+ tx = ReadWriteTransactionContext.new(lock_handler, @storage, snapshot, @master_cache, @secondary_cache, @decode, @encode)
117
115
  end
118
116
  Thread.current[:higgs_current_transaction] = tx
119
117
  r = yield(tx)
120
118
  tx.commit unless read_only
121
- ensure
122
- Thread.current[:higgs_current_transaction] = nil
123
- end
119
+ }
124
120
  }
125
121
  r
126
122
  end
127
123
 
128
- def self.in_transaction?
129
- ! Thread.current[:higgs_current_transaction].nil?
130
- end
131
-
132
- def self.current_transaction
133
- Thread.current[:higgs_current_transaction]
134
- end
135
-
136
124
  def apply_journal_log(not_delete=false)
137
125
  @lock_manager.exclusive{
138
126
  if (@read_only != :standby) then
@@ -163,7 +151,7 @@ module Higgs
163
151
 
164
152
  class TransactionContext
165
153
  # for ident(1)
166
- CVS_ID = '$Id: tman.rb 674 2007-11-05 15:55:14Z toki $'
154
+ CVS_ID = '$Id: tman.rb 745 2008-01-20 13:28:02Z toki $'
167
155
 
168
156
  include Enumerable
169
157
 
@@ -172,30 +160,37 @@ module Higgs
172
160
  end
173
161
  private :deep_copy
174
162
 
175
- def initialize(lock_handler, storage, master_cache, secondary_cache, decode, encode)
163
+ def string_only(key)
164
+ @snapshot.fetch(key, :string_only) {
165
+ properties = @storage.fetch_properties(key) and
166
+ properties['system_properties']['string_only']
167
+ }
168
+ end
169
+ private :string_only
170
+
171
+ def initialize(lock_handler, storage, snapshot, master_cache, secondary_cache, decode, encode)
176
172
  @lock_handler = lock_handler
177
173
  @storage = storage
174
+ @snapshot = snapshot
178
175
  @master_cache = master_cache
179
176
  @secondary_cache = secondary_cache
180
177
  @decode = decode
181
178
  @encode = encode
182
179
 
183
180
  @local_data_cache = Hash.new{|hash, key|
184
- if (@storage.key? key) then
185
- if (@storage.string_only(key)) then
186
- hash[key] = @master_cache[key]
181
+ if (@snapshot.key? @storage, key) then
182
+ if (string_only(key)) then
183
+ hash[key] = @snapshot.fetch(key, :data) { @master_cache[key] }
187
184
  else
188
- hash[key] = @decode.call(@master_cache[key])
185
+ hash[key] = @decode.call(@snapshot.fetch(key, :data) { @master_cache[key] })
189
186
  end
190
187
  end
191
188
  }
192
189
 
193
190
  @local_properties_cache = Hash.new{|hash, key|
194
- if (properties = @storage.fetch_properties(key)) then
195
- hash[key] = deep_copy(properties)
196
- else
197
- hash[key] = { 'system_properties' => {}, 'custom_properties' => {} }
198
- end
191
+ hash[key] = @snapshot.fetch(key, :properties) {
192
+ deep_copy(@storage.fetch_properties(key))
193
+ } || { 'system_properties' => {}, 'custom_properties' => {} }
199
194
  }
200
195
 
201
196
  @locked_map = {}
@@ -205,23 +200,29 @@ module Higgs
205
200
  @ope_map = {}
206
201
  end
207
202
 
203
+ def change_number
204
+ @snapshot.change_number
205
+ end
206
+
208
207
  def locked?(key)
209
208
  @locked_map[key]
210
209
  end
211
210
 
212
211
  def lock(key)
213
212
  unless (@locked_map[key]) then
214
- @lock_handler.lock(key)
213
+ cnum = @snapshot.fetch(key, :data_change_number) {
214
+ @storage.data_change_number(key)
215
+ }
216
+ @lock_handler.lock(key, :data, cnum)
217
+
218
+ cnum = @snapshot.fetch(key, :properties_change_number) {
219
+ @storage.properties_change_number(key)
220
+ }
221
+ @lock_handler.lock(key, :properties, cnum)
222
+
215
223
  @locked_map[key] = true
216
224
  end
217
- nil
218
- end
219
225
 
220
- def unlock(key)
221
- if (@locked_map[key]) then
222
- @lock_handler.unlock(key)
223
- @locked_map[key] = false
224
- end
225
226
  nil
226
227
  end
227
228
 
@@ -268,7 +269,7 @@ module Higgs
268
269
  if (@local_data_cache.key? key) then
269
270
  return true
270
271
  end
271
- if (@storage.key? key) then
272
+ if (@snapshot.key? @storage, key) then
272
273
  return true
273
274
  end
274
275
  end
@@ -286,7 +287,7 @@ module Higgs
286
287
  yield(key)
287
288
  end
288
289
  end
289
- @storage.each_key do |key|
290
+ @snapshot.each_key(@storage) do |key|
290
291
  lock(key)
291
292
  if (@ope_map[key] != :delete) then
292
293
  unless (@local_data_cache.key? key) then
@@ -356,11 +357,11 @@ module Higgs
356
357
  if (properties = @local_properties_cache[key]) then
357
358
  case (name)
358
359
  when :identity
359
- @storage.identity(key)
360
+ @snapshot.fetch(key, :identity) { @storage.identity(key) }
360
361
  when :data_change_number
361
- @storage.data_change_number(key)
362
+ @snapshot.fetch(key, :data_change_number) { @storage.data_change_number(key) }
362
363
  when :properties_change_number
363
- @storage.properties_change_number(key)
364
+ @snapshot.fetch(key, :properties_change_number) { @storage.properties_change_number(key) }
364
365
  when Symbol
365
366
  properties['system_properties'][name.to_s]
366
367
  when String
@@ -416,11 +417,11 @@ module Higgs
416
417
  if (self.key? key) then # lock
417
418
  case (name)
418
419
  when :identity
419
- return @storage.identity(key) != nil
420
+ return @snapshot.fetch(key, :identity) { @storage.identity(key) } != nil
420
421
  when :data_change_number
421
- return @storage.data_change_number(key) != nil
422
+ return @snapshot.fetch(key, :data_change_number) { @storage.data_change_number(key) } != nil
422
423
  when :properties_change_number
423
- return @storage.properties_change_number(key) != nil
424
+ return @snapshot.fetch(key, :properties_change_number) { @storage.properties_change_number(key) } != nil
424
425
  when Symbol
425
426
  return (@local_properties_cache[key]['system_properties'].key? name.to_s)
426
427
  when String
@@ -436,13 +437,13 @@ module Higgs
436
437
  unless (self.key? key) then # lock
437
438
  raise IndexError, "not exist properties at key: #{key}"
438
439
  end
439
- if (value = @storage.identity(key)) then
440
+ if (value = @snapshot.fetch(key, :identity) { @storage.identity(key) }) then
440
441
  yield(:identity, value)
441
442
  end
442
- if (value = @storage.data_change_number(key)) then
443
+ if (value = @snapshot.fetch(key, :data_change_number) { @storage.data_change_number(key) }) then
443
444
  yield(:data_change_number, value)
444
445
  end
445
- if (value = @storage.properties_change_number(key)) then
446
+ if (value = @snapshot.fetch(key, :properties_change_number) { @storage.properties_change_number(key) }) then
446
447
  yield(:properties_change_number, value)
447
448
  end
448
449
  @local_properties_cache[key]['system_properties'].each_pair do |name, value|
@@ -507,22 +508,77 @@ module Higgs
507
508
 
508
509
  def commit
509
510
  write_list = write_list()
510
- unless (write_list.empty?) then
511
- @storage.write_and_commit(write_list)
511
+ if (write_list.empty?) then
512
+ return
513
+ end
514
+
515
+ @lock_handler.critical{
516
+ @lock_handler.check_collision{|key, type|
517
+ case (type)
518
+ when :data
519
+ @storage.data_change_number(key)
520
+ when :properties
521
+ @storage.properties_change_number(key)
522
+ else
523
+ raise "unknown type: #{type}"
524
+ end
525
+ }
526
+
527
+ old_write_list = []
512
528
  for ope, key, value in write_list
513
529
  case (ope)
514
530
  when :write
515
- @master_cache.delete(key)
531
+ if (@storage.key? key) then
532
+ properties = Marshal.load(Marshal.dump(@storage.fetch_properties(key)))
533
+ old_write_list << [ :value, key, :data, @master_cache[key] ]
534
+ old_write_list << [ :value, key, :properties, properties ]
535
+ old_write_list << [ :value, key, :identity, @storage.identity(key) ]
536
+ old_write_list << [ :value, key, :string_only, properties['system_properties']['string_only'] ]
537
+ old_write_list << [ :value, key, :data_change_number, @storage.data_change_number(key) ]
538
+ old_write_list << [ :value, key, :properties_change_number, @storage.properties_change_number(key) ]
539
+ else
540
+ old_write_list << [ :none, key ]
541
+ end
542
+ when :system_properties, :custom_properties
543
+ if (@storage.key? key) then
544
+ properties = Marshal.load(Marshal.dump(@storage.fetch_properties(key)))
545
+ old_write_list << [ :value, key, :properties, properties ]
546
+ old_write_list << [ :value, key, :properties_change_number, @storage.properties_change_number(key) ]
547
+ else
548
+ old_write_list << [ :none, key ]
549
+ end
516
550
  when :delete
551
+ if (@storage.key? key) then
552
+ properties = Marshal.load(Marshal.dump(@storage.fetch_properties(key)))
553
+ old_write_list << [ :value, key, :data, @master_cache[key] ]
554
+ old_write_list << [ :value, key, :properties, properties ]
555
+ old_write_list << [ :value, key, :identity, @storage.identity(key) ]
556
+ old_write_list << [ :value, key, :string_only, properties['system_properties']['string_only'] ]
557
+ old_write_list << [ :value, key, :data_change_number, @storage.data_change_number(key) ]
558
+ old_write_list << [ :value, key, :properties_change_number, @storage.properties_change_number(key) ]
559
+ end
560
+ else
561
+ raise "unknown operation: #{ope}"
562
+ end
563
+ end
564
+ @snapshot.write_old_values(old_write_list)
565
+
566
+ for ope, key, value in write_list
567
+ case (ope)
568
+ when :write, :delete
517
569
  @master_cache.delete(key)
518
- @secondary_cache.delete(key)
519
570
  end
520
571
  @local_properties_cache.delete(key)
521
572
  end
522
573
  @update_system_properties.clear
523
574
  @update_custom_properties.clear
524
575
  @ope_map.clear
525
- end
576
+
577
+ @storage.write_and_commit(write_list)
578
+ @snapshot.ref_count_down
579
+ @snapshot.ref_count_up(@storage.change_number)
580
+ }
581
+
526
582
  nil
527
583
  end
528
584