rims 0.2.1 → 0.2.2

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.
@@ -14,8 +14,8 @@ module RIMS
14
14
  end
15
15
 
16
16
  # optional block is called when a mail store is closed.
17
- def return_pool(**name_args, &block) # yields:
18
- @object_pool.put(self, **name_args, &block)
17
+ def return_pool(&block) # yields:
18
+ @object_pool.put(self, &block)
19
19
  nil
20
20
  end
21
21
  end
@@ -35,27 +35,25 @@ module RIMS
35
35
  end
36
36
 
37
37
  def initialize(&object_factory) # yields: object_pool, object_key, object_lock
38
+ @mutex = Thread::Mutex.new
38
39
  @object_factory = object_factory
39
- @pool_map = {}
40
- @pool_lock = Mutex.new
41
- @object_lock_map = Hash.new{|hash, key| hash[key] = ReadWriteLock.new }
40
+ @pool = {}
42
41
  end
43
42
 
44
43
  def empty?
45
- @pool_map.empty?
44
+ @mutex.synchronize{ @pool.empty? }
46
45
  end
47
46
 
48
47
  # optional block is called when a new object is added to an object pool.
49
- def get(object_key, timeout_seconds: ReadWriteLock::DEFAULT_TIMEOUT_SECONDS) # yields:
50
- object_lock = @pool_lock.synchronize{ @object_lock_map[object_key] }
51
- object_lock.write_synchronize(timeout_seconds) {
52
- if (@pool_lock.synchronize{ @pool_map.key? object_key }) then
53
- ref_count = @pool_lock.synchronize{ @pool_map[object_key] }
48
+ def get(object_key) # yields:
49
+ @mutex.synchronize{
50
+ if (@pool.key? object_key) then
51
+ ref_count = @pool[object_key]
54
52
  else
55
53
  yield if block_given?
56
- object_holder = @object_factory.call(self, object_key, object_lock)
54
+ object_holder = @object_factory.call(self, object_key)
57
55
  ref_count = ReferenceCount.new(0, object_holder)
58
- @pool_lock.synchronize{ @pool_map[object_key] = ref_count }
56
+ @pool[object_key] = ref_count
59
57
  end
60
58
  ref_count.count >= 0 or raise 'internal error'
61
59
  ref_count.count += 1
@@ -64,15 +62,14 @@ module RIMS
64
62
  end
65
63
 
66
64
  # optional block is called when an object is deleted from an object pool.
67
- def put(object_holder, timeout_seconds: ReadWriteLock::DEFAULT_TIMEOUT_SECONDS) # yields:
68
- object_lock = @pool_lock.synchronize{ @object_lock_map[object_holder.object_key] }
69
- object_lock.write_synchronize(timeout_seconds) {
70
- ref_count = @pool_lock.synchronize{ @pool_map[object_holder.object_key] } or raise 'internal error'
65
+ def put(object_holder) # yields:
66
+ @mutex.synchronize{
67
+ ref_count = @pool[object_holder.object_key] or raise 'internal error'
71
68
  ref_count.object_holder.equal? object_holder or raise 'internal error'
72
69
  ref_count.count > 0 or raise 'internal error'
73
70
  ref_count.count -= 1
74
71
  if (ref_count.count == 0) then
75
- @pool_lock.synchronize{ @pool_map.delete(object_holder.object_key) }
72
+ @pool.delete(object_holder.object_key)
76
73
  ref_count.object_destroy
77
74
  yield if block_given?
78
75
  end
@@ -156,7 +156,7 @@ module RIMS
156
156
  @logger.error($!)
157
157
  res << "#{tag} BAD client command syntax error\r\n"
158
158
  rescue
159
- raise if ($!.name =~ /AssertionFailedError/)
159
+ raise if ($!.class.name =~ /AssertionFailedError/)
160
160
  @logger.error('internal server error.')
161
161
  @logger.error($!)
162
162
  res << "#{tag} BAD internal server error\r\n"
@@ -206,7 +206,7 @@ module RIMS
206
206
  unique_user_id = Authentication.unique_user_id(username)
207
207
  logger.debug("unique user ID: #{username} -> #{unique_user_id}") if logger.debug?
208
208
 
209
- mail_store_holder = mail_store_pool.get(unique_user_id, timeout_seconds: write_lock_timeout_seconds) {
209
+ mail_store_holder = mail_store_pool.get(unique_user_id) {
210
210
  logger.info("open mail store: #{unique_user_id} [ #{username} ]")
211
211
  }
212
212
 
@@ -510,7 +510,7 @@ module RIMS
510
510
  end
511
511
  tmp_mail_store_holder = @mail_store_holder
512
512
  ReadWriteLock.write_lock_timeout_detach(@cleanup_write_lock_timeout_seconds, @write_lock_timeout_seconds, logger: @logger) {|timeout_seconds|
513
- tmp_mail_store_holder.return_pool(timeout_seconds: timeout_seconds) {
513
+ tmp_mail_store_holder.return_pool{
514
514
  @logger.info("close mail store: #{tmp_mail_store_holder.unique_user_id}")
515
515
  }
516
516
  }
@@ -1272,7 +1272,7 @@ module RIMS
1272
1272
  @last_user_cache_key_username = nil
1273
1273
  @last_user_cache_value_mail_store_holder = nil
1274
1274
  ReadWriteLock.write_lock_timeout_detach(@cleanup_write_lock_timeout_seconds, @write_lock_timeout_seconds, logger: @logger) {|timeout_seconds|
1275
- mail_store_holder.return_pool(timeout_seconds: timeout_seconds) {
1275
+ mail_store_holder.return_pool{
1276
1276
  @logger.info("close cached mail store to deliver message: #{mail_store_holder.unique_user_id}")
1277
1277
  }
1278
1278
  }
@@ -631,9 +631,9 @@ module RIMS
631
631
  unless (search_key.empty?) then
632
632
  search_key = search_key.dup
633
633
  factory = fetch_next_node(search_key)
634
- cond = factory.call(parse_cached(search_key))
634
+ _cond = factory.call(parse_cached(search_key))
635
635
  else
636
- cond = end_of_cond
636
+ _cond = end_of_cond
637
637
  end
638
638
  end
639
639
  private :parse_cached
@@ -235,6 +235,38 @@ EOF
235
235
  end
236
236
  end
237
237
 
238
+ def db_closed_error
239
+ RuntimeError
240
+ end
241
+
242
+ def db_closed_fetch_error
243
+ db_closed_error
244
+ end
245
+
246
+ def db_closed_store_error
247
+ db_closed_error
248
+ end
249
+
250
+ def db_closed_delete_error
251
+ db_closed_error
252
+ end
253
+
254
+ def db_closed_key_error
255
+ db_closed_error
256
+ end
257
+
258
+ def db_closed_each_key_error
259
+ db_closed_error
260
+ end
261
+
262
+ def db_closed_each_value_error
263
+ db_closed_error
264
+ end
265
+
266
+ def db_closed_each_pair_error
267
+ db_closed_error
268
+ end
269
+
238
270
  def setup
239
271
  @base_dir = 'kvs_test_dir'
240
272
  FileUtils.mkdir_p(@base_dir)
@@ -336,13 +368,13 @@ EOF
336
368
  assert_equal(true, db_closed?)
337
369
 
338
370
  # closed exception
339
- assert_raise(RuntimeError) { @kvs['foo'] }
340
- assert_raise(RuntimeError) { @kvs['foo'] = 'apple' }
341
- assert_raise(RuntimeError) { @kvs.delete('foo') }
342
- assert_raise(RuntimeError) { @kvs.key? 'foo' }
343
- assert_raise(RuntimeError) { @kvs.each_key.to_a }
344
- assert_raise(RuntimeError) { @kvs.each_value.to_a }
345
- assert_raise(RuntimeError) { @kvs.each_pair.to_a }
371
+ assert_raise(db_closed_fetch_error) { @kvs['foo'] }
372
+ assert_raise(db_closed_store_error) { @kvs['foo'] = 'apple' }
373
+ assert_raise(db_closed_delete_error) { @kvs.delete('foo') }
374
+ assert_raise(db_closed_key_error) { @kvs.key? 'foo' }
375
+ assert_raise(db_closed_each_key_error) { @kvs.each_key.to_a }
376
+ assert_raise(db_closed_each_value_error) { @kvs.each_value.to_a }
377
+ assert_raise(db_closed_each_pair_error) { @kvs.each_pair.to_a }
346
378
  end
347
379
  end
348
380
 
@@ -1,7 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
 
3
3
  module RIMS
4
- VERSION = '0.2.1'
4
+ VERSION = '0.2.2'
5
5
  MAILBOX_DATA_STRUCTURE_VERSION = 'mailbox.2'
6
6
  end
7
7
 
@@ -0,0 +1,131 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'rims'
4
+ require 'test/unit'
5
+
6
+ module RIMS::Test
7
+ class ServerResponseChannelTest < Test::Unit::TestCase
8
+ def setup
9
+ @channel = RIMS::ServerResponseChannel.new
10
+ end
11
+
12
+ def test_pub_sub_fetch_message
13
+ pub1, sub1 = @channel.make_pub_sub_pair(0)
14
+ pub2, sub2 = @channel.make_pub_sub_pair(0)
15
+ pub3, sub3 = @channel.make_pub_sub_pair(0)
16
+
17
+ pub1.publish('msg1')
18
+ assert_equal(false, sub1.message?)
19
+ assert_equal(true, sub2.message?)
20
+ assert_equal(true, sub3.message?)
21
+
22
+ pub2.publish('msg2')
23
+ assert_equal(true, sub1.message?)
24
+ assert_equal(true, sub2.message?)
25
+ assert_equal(true, sub3.message?)
26
+
27
+ pub3.publish('msg3')
28
+ assert_equal(true, sub1.message?)
29
+ assert_equal(true, sub2.message?)
30
+ assert_equal(true, sub3.message?)
31
+
32
+ assert_equal(%w[ msg2 msg3 ], sub1.enum_for(:fetch).to_a)
33
+ assert_equal(%w[ msg1 msg3 ], sub2.enum_for(:fetch).to_a)
34
+ assert_equal(%w[ msg1 msg2 ], sub3.enum_for(:fetch).to_a)
35
+
36
+ assert_equal(false, sub1.message?)
37
+ assert_equal(false, sub2.message?)
38
+ assert_equal(false, sub3.message?)
39
+ end
40
+
41
+ def test_pub_sub_fetch_no_message
42
+ _, sub = @channel.make_pub_sub_pair(0)
43
+ assert_equal(false, sub.message?)
44
+ assert_equal([], sub.enum_for(:fetch).to_a)
45
+ end
46
+
47
+ def test_pub_sub_detach
48
+ pub1, sub1 = @channel.make_pub_sub_pair(0)
49
+ pub2, sub2 = @channel.make_pub_sub_pair(0)
50
+ pub3, sub3 = @channel.make_pub_sub_pair(0)
51
+
52
+ pub3.detach
53
+ sub3.detach
54
+
55
+ pub1.publish('msg1')
56
+ pub2.publish('msg2')
57
+
58
+ error = assert_raise(RuntimeError) { pub3.publish('msg3') }
59
+ assert_match(/detached/, error.message)
60
+
61
+ assert_equal(%w[ msg2 ], sub1.enum_for(:fetch).to_a)
62
+ assert_equal(%w[ msg1 ], sub2.enum_for(:fetch).to_a)
63
+ assert_equal([], sub3.enum_for(:fetch).to_a)
64
+ end
65
+
66
+ def test_pub_sub_different_mailboxes
67
+ mbox0_pub1, mbox0_sub1 = @channel.make_pub_sub_pair(0)
68
+ mbox0_pub2, mbox0_sub2 = @channel.make_pub_sub_pair(0)
69
+ mbox1_pub1, mbox1_sub1 = @channel.make_pub_sub_pair(1)
70
+ mbox1_pub2, mbox1_sub2 = @channel.make_pub_sub_pair(1)
71
+
72
+ mbox0_pub1.publish('mbox0:msg1')
73
+ mbox0_pub2.publish('mbox0:msg2')
74
+
75
+ assert_equal(%w[ mbox0:msg2 ], mbox0_sub1.enum_for(:fetch).to_a)
76
+ assert_equal(%w[ mbox0:msg1 ], mbox0_sub2.enum_for(:fetch).to_a)
77
+ assert_equal([], mbox1_sub1.enum_for(:fetch).to_a)
78
+ assert_equal([], mbox1_sub2.enum_for(:fetch).to_a)
79
+
80
+ mbox1_pub1.publish('mbox1:msg1')
81
+ mbox1_pub2.publish('mbox1:msg2')
82
+
83
+ assert_equal([], mbox0_sub1.enum_for(:fetch).to_a)
84
+ assert_equal([], mbox0_sub2.enum_for(:fetch).to_a)
85
+ assert_equal(%w[ mbox1:msg2 ], mbox1_sub1.enum_for(:fetch).to_a)
86
+ assert_equal(%w[ mbox1:msg1 ], mbox1_sub2.enum_for(:fetch).to_a)
87
+ end
88
+
89
+ def test_pub_sub_idle
90
+ pub, _ = @channel.make_pub_sub_pair(0)
91
+ _, sub = @channel.make_pub_sub_pair(0)
92
+
93
+ pub.publish('msg1')
94
+ sub.idle_interrupt
95
+ assert_equal([ %w[ msg1 ] ], sub.enum_for(:idle_wait).to_a)
96
+
97
+ pub.publish('msg2')
98
+ pub.publish('msg3')
99
+ sub.idle_interrupt
100
+ assert_equal([ %w[ msg2 msg3 ] ], sub.enum_for(:idle_wait).to_a)
101
+ end
102
+
103
+ def test_pub_sub_idle_chunks
104
+ pub, _ = @channel.make_pub_sub_pair(0)
105
+ _, sub = @channel.make_pub_sub_pair(0)
106
+
107
+ t = Thread.new{ sub.enum_for(:idle_wait).to_a }
108
+
109
+ pub.publish('msg1')
110
+ t.wakeup
111
+ sleep(0.1)
112
+
113
+ pub.publish('msg2')
114
+ pub.publish('msg3')
115
+ sub.idle_interrupt
116
+
117
+ assert_equal([ %w[ msg1 ], %w[ msg2 msg3 ] ], t.value)
118
+ end
119
+
120
+ def test_pub_sub_idle_no_message
121
+ _, sub = @channel.make_pub_sub_pair(0)
122
+ sub.idle_interrupt
123
+ assert_equal([], sub.enum_for(:idle_wait).to_a)
124
+ end
125
+ end
126
+ end
127
+
128
+ # Local Variables:
129
+ # mode: Ruby
130
+ # indent-tabs-mode: nil
131
+ # End:
@@ -107,10 +107,12 @@ module RIMS::Test
107
107
 
108
108
  s = @db['foo']
109
109
  @db['foo'] = s.chop
110
- assert_raise(RuntimeError) { @kvs['foo'] }
110
+ error = assert_raise(RuntimeError) { @kvs['foo'] }
111
+ assert_match(/checksum error/, error.message)
111
112
 
112
113
  @db['foo'] = 'Hello world.'
113
- assert_raise(RuntimeError) { @kvs['foo'] }
114
+ error = assert_raise(RuntimeError) { @kvs['foo'] }
115
+ assert_match(/checksum format error/, error.message)
114
116
  end
115
117
  end
116
118
  end
@@ -108,7 +108,7 @@ module RIMS::Test
108
108
  begin
109
109
  assert_config(load_libraries: %w[ prime ]) {|conf|
110
110
  conf.setup_load_libraries
111
- assert($LOADED_FEATURES.any?{|name| name =~ /prime/})
111
+ assert($LOADED_FEATURES.any?{|name| name =~ /prime/})
112
112
  }
113
113
  rescue
114
114
  exit!(1)
@@ -448,7 +448,8 @@ module RIMS::Test
448
448
  assert_equal(false, (@db.msg_exist? 1))
449
449
  assert_equal(true, (@db.msg_exist? 2))
450
450
 
451
- assert_raise(RuntimeError) { @db.del_msg(1) }
451
+ error = assert_raise(RuntimeError) { @db.del_msg(1) }
452
+ assert_match(/not found a message text/, error.message)
452
453
  end
453
454
  end
454
455
 
@@ -531,8 +532,10 @@ module RIMS::Test
531
532
  assert_equal(deleted, @db.msg_flag_deleted(uid))
532
533
  end
533
534
 
534
- assert_raise(RuntimeError) { @db.expunge_msg(1) }
535
- assert_raise(RuntimeError) { @db.expunge_msg(2) }
535
+ error = assert_raise(RuntimeError) { @db.expunge_msg(1) }
536
+ assert_match(/not found a message uid/, error.message)
537
+ error = assert_raise(RuntimeError) { @db.expunge_msg(2) }
538
+ assert_match(/not deleted flag/, error.message)
536
539
  end
537
540
  end
538
541
 
@@ -572,12 +575,13 @@ module RIMS::Test
572
575
  @cksum_kvs['baz'] = 'orange'
573
576
 
574
577
  count = 0
575
- assert_raise(RuntimeError) {
578
+ error = assert_raise(RuntimeError) {
576
579
  @db.test_read_all{|read_error|
577
580
  assert_kind_of(RuntimeError, read_error)
578
581
  count += 1
579
582
  }
580
583
  }
584
+ assert_match(/checksum format error/, error.message)
581
585
  assert_equal(1, count)
582
586
 
583
587
  @cksum_kvs['foo'] = 'apple'; @kvs['foo'] = 'apple'
@@ -585,12 +589,13 @@ module RIMS::Test
585
589
  @cksum_kvs['baz'] = 'orange'; @kvs['baz'] = 'orange'
586
590
 
587
591
  count = 0
588
- assert_raise(RuntimeError) {
592
+ error = assert_raise(RuntimeError) {
589
593
  @db.test_read_all{|read_error|
590
594
  assert_kind_of(RuntimeError, read_error)
591
595
  count += 1
592
596
  }
593
597
  }
598
+ assert_match(/checksum format error/, error.message)
594
599
  assert_equal(2, count)
595
600
  end
596
601
  end
@@ -73,7 +73,8 @@ module RIMS::Test
73
73
 
74
74
  @kvs['meta'].delete('msg_id2date-1')
75
75
  assert_instance_of(Time, @meta_db.msg_date(0))
76
- assert_raise(RuntimeError) { @meta_db.msg_date(1) }
76
+ error = assert_raise(RuntimeError) { @meta_db.msg_date(1) }
77
+ assert_match(/not found a message date/, error.message)
77
78
  assert_instance_of(Time, @meta_db.msg_date(2))
78
79
 
79
80
  @meta_db.recovery_phase1_msg_scan(@msg_db, logger: @logger)
@@ -635,7 +636,8 @@ module RIMS::Test
635
636
 
636
637
  # recovery phase 2
637
638
  assert_equal({}, @meta_db.msg_mbox_uid_mapping(3))
638
- assert_raise(RuntimeError) { @meta_db.msg_date(3) }
639
+ error = assert_raise(RuntimeError) { @meta_db.msg_date(3) }
640
+ assert_match(/not found a message date/, error.message)
639
641
 
640
642
  # recovery phase 3
641
643
  assert_equal(5, @meta_db.uidvalidity)
@@ -672,7 +674,8 @@ module RIMS::Test
672
674
  # recovery phase 1,8
673
675
  @msg_db.add_msg(3, 'apple')
674
676
  assert_equal({}, @meta_db.msg_mbox_uid_mapping(3))
675
- assert_raise(RuntimeError) { @meta_db.msg_date(3) }
677
+ error = assert_raise(RuntimeError) { @meta_db.msg_date(3) }
678
+ assert_match(/not found a message date/, error.message)
676
679
 
677
680
  # recovery phase 2,5,8
678
681
  mbox_uid_map = Marshal.load(@kvs['meta']['msg_id2mbox-0'])
@@ -34,19 +34,21 @@ module RIMS::Test
34
34
  end
35
35
 
36
36
  def test_read_lock_timeout
37
- assert_raise(RIMS::ReadLockTimeoutError) {
37
+ error = assert_raise(RIMS::ReadLockTimeoutError) {
38
38
  @lock.write_synchronize{
39
39
  @lock.read_synchronize(0) {}
40
40
  }
41
41
  }
42
+ assert_equal('read-lock wait timeout', error.message)
42
43
  end
43
44
 
44
45
  def test_write_lock_timeout
45
- assert_raise(RIMS::WriteLockTimeoutError) {
46
+ error = assert_raise(RIMS::WriteLockTimeoutError) {
46
47
  @lock.write_synchronize{
47
48
  @lock.write_synchronize(0) {}
48
49
  }
49
50
  }
51
+ assert_equal('write-lock wait timeout', error.message)
50
52
  end
51
53
 
52
54
  def calculate_threa_work_seconds