rims 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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