ruby-qdbm 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/villa.rb ADDED
@@ -0,0 +1,816 @@
1
+ #=================================================================================================
2
+ # Ruby API of Villa, the advanced API of QDBM
3
+ # Copyright (C) 2000-2006 Mikio Hirabayashi
4
+ # This file is part of QDBM, Quick Database Manager.
5
+ # QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU
6
+ # Lesser General Public License as published by the Free Software Foundation; either version
7
+ # 2.1 of the License or any later version. QDBM is distributed in the hope that it will be
8
+ # useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
10
+ # details.
11
+ # You should have received a copy of the GNU Lesser General Public License along with QDBM; if
12
+ # not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
13
+ # 02111-1307 USA.
14
+ #=================================================================================================
15
+
16
+
17
+ require 'mod_villa'
18
+ require 'thread'
19
+
20
+
21
+ ##
22
+ # require 'villa'
23
+ # The library `villa' should be included in application codes.
24
+ # An instance of the class `Villa' is used as a database handle.
25
+ # `Villa' performs Mix-in of `Enumerable'.
26
+ # Each method of `Villa' throws an exception of `Villa::EANY' or its sub classes when an error
27
+ # occurs: `Villa::ENOERR', `Villa::EFATAL', `Villa::EMODE', `Villa::EBROKEN', `Villa::EKEEP',
28
+ # `Villa::ENOITEM', `Villa::EALLOC', `Villa::EMAP', `Villa::EOPEN', `Villa::ECLOSE',
29
+ # `Villa::ETRUNC', `Villa::ESYNC', `Villa::ESTAT', `Villa::ESEEK', `Villa::EREAD',
30
+ # `Villa::EWRITE', `Villa::ELOCK', `Villa::EUNLINK', `Villa::EMKDIR', `Villa::ERMDIR' and
31
+ # `Villa::EMISC'.
32
+ #
33
+ class Villa
34
+ include Mod_Villa, Enumerable
35
+ #----------------------------------------------------------------
36
+ # class constants
37
+ #----------------------------------------------------------------
38
+ MyMutex = Mutex::new()
39
+ #----------------------------------------------------------------
40
+ # class methods
41
+ #----------------------------------------------------------------
42
+ public
43
+ ##
44
+ # villa = Villa::new(name, omode, cmode)
45
+ # Constructor: Get a database handle.
46
+ # `name' specifies the name of a database file.
47
+ # `omode' specifies the connection mode: `Villa::OWRITER' as a writer, `Villa::OREADER' as a
48
+ # reader. If the mode is `Villa::OWRITER', the following may be added by bitwise or:
49
+ # `Villa::OCREAT', which means it creates a new database if not exist, `Villa::OTRUNC', which
50
+ # means it creates a new database regardless if one exists, `Villa::OZCOMP', which means
51
+ # leaves in the database are compressed with ZLIB, `Villa::OYCOMP', which means leaves in the
52
+ # database are compressed with LZO, `Villa::OXCOMP', which means leaves in the database are
53
+ # compressed with BZIP2. Both of `Villa::OREADER' and `Villa::OWRITER' can be added to by
54
+ # bitwise or: `Villa::ONOLCK', which means it opens a database file without file locking, or
55
+ # `Villa::OLCKNB', which means locking is performed without blocking. If it is omitted,
56
+ # `Villa::OREADER' is specified.
57
+ # `cmode' specifies the comparing function: `Villa::CMPLEX' comparing keys in lexical order,
58
+ # `Villa::CMPDEC' comparing keys as decimal strings, `Villa::CMPOBJ' comparing keys as
59
+ # serialized objects implementing the method `<=>'. The comparing function should be kept
60
+ # same in the life of a database. If `Villa::CMPOBJ' is used, such methods as `put', `out',
61
+ # `get' and so on can treat not only instances of `String' but also any serializable and
62
+ # comparable object.
63
+ # If so, objects being stored are serialized and objects being retrieved are deserialized.
64
+ # The return value is the database handle.
65
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
66
+ # If a block parameter is given, this method works as an iterator. A database handle is
67
+ # opened and passed via the first argument of the block. The database handle is surely
68
+ # closed when the block is over.
69
+ # While connecting as a writer, an exclusive lock is invoked to the database file.
70
+ # While connecting as a reader, a shared lock is invoked to the database file. The thread
71
+ # blocks until the lock is achieved. `Villa::OZCOMP', `Villa::OYCOMP', and `Villa::OXCOMP'
72
+ # are available only if QDBM was built each with ZLIB, LZO, and BZIP2 enabled. If
73
+ # `Villa::ONOLCK' is used, the application is responsible for exclusion control.
74
+ #
75
+ #@ DEFINED IMPLICITLY
76
+ ##
77
+ # villa = Villa::open(name, omode, cmode)
78
+ # Constructor: An alias of `new'.
79
+ #
80
+ #@ DEFINED OUTSIDE
81
+ #----------------------------------------------------------------
82
+ # private methods
83
+ #----------------------------------------------------------------
84
+ private
85
+ #=
86
+ # initialize(name, omode, cmode)
87
+ # Method: Called implicitly by the constructor.
88
+ #
89
+ def initialize(name, omode = OREADER, cmode = CMPLEX)
90
+ @silent = false
91
+ MyMutex.synchronize() do
92
+ @index = mod_open(name, omode, cmode)
93
+ @name = name
94
+ @cmode = cmode
95
+ @tranmutex = Mutex::new()
96
+ end
97
+ if(iterator?)
98
+ begin
99
+ yield(self)
100
+ ensure
101
+ close()
102
+ end
103
+ end
104
+ self
105
+ end
106
+ #=
107
+ # clone()
108
+ # Method: Forbidden to use.
109
+ #
110
+ def clone
111
+ raise(VillaError)
112
+ end
113
+ #=
114
+ # dup()
115
+ # Method: Forbidden to use.
116
+ #
117
+ alias dup clone
118
+ #----------------------------------------------------------------
119
+ # public methods
120
+ #----------------------------------------------------------------
121
+ public
122
+ ##
123
+ # bool = villa.close()
124
+ # Method: Close the database handle.
125
+ # The return value is always true.
126
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
127
+ # Because the region of a closed handle is released, it becomes impossible to use the handle.
128
+ # Updating a database is assured to be written when the handle is closed. If a writer opens
129
+ # a database but does not close it appropriately, the database will be broken. If the
130
+ # transaction is activated and not committed, it is aborted.
131
+ #
132
+ def close()
133
+ MyMutex.synchronize() do
134
+ begin
135
+ mod_close(@index)
136
+ ensure
137
+ @index = -1
138
+ end
139
+ end
140
+ end
141
+ ##
142
+ # villa.silent = bool
143
+ # Method: Set the flag whether to repress frequent exceptions.
144
+ # The return value is the assigned value.
145
+ #
146
+ def silent=(value)
147
+ @silent = value ? true : false
148
+ mod_setsilent(@index, silent ? 1 : 0)
149
+ @silent
150
+ end
151
+ def silent
152
+ @silent
153
+ end
154
+ ##
155
+ # bool = villa.put(key, val, dmode)
156
+ # Method: Store a record.
157
+ # `key' specifies a key. Although it must be an instance of String, binary data is okey.
158
+ # `val' specifies a value. Although it must be an instance of String, binary data is okey.
159
+ # `dmode' specifies behavior when the key overlaps, by the following values: `Villa::DOVER',
160
+ # which means the specified value overwrites the existing one, `Villa::DKEEP', which means the
161
+ # existing value is kept, `Villa::DCAT', which means the specified value is concatenated at the
162
+ # end of the existing value, `Villa::DDUP', which means duplication of keys is allowed and the
163
+ # specified value is added as the last one, `Villa::DDUPR', which means duplication of keys is
164
+ # allowed and the specified value is added as the first one. If it is omitted, `Villa::DOVER'
165
+ # is specified.
166
+ # The return value is always true. However, if the silent flag is true and replace is
167
+ # cancelled, false is returned instead of exception.
168
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or replace
169
+ # is cancelled.
170
+ # The cursor becomes unavailable due to updating database.
171
+ #
172
+ def put(key, val, dmode = DOVER)
173
+ if(@cmode == CMPOBJ)
174
+ key = Marshal.dump(key)
175
+ val = Marshal.dump(val)
176
+ end
177
+ mod_put(@index, key, val, dmode)
178
+ end
179
+ ##
180
+ # bool = villa.store(key, val)
181
+ # Method: An alias of `put'.
182
+ #
183
+ alias store put
184
+ ##
185
+ # villa[key] = val
186
+ # Method: An alias of `put'.
187
+ #
188
+ alias []= put
189
+ ##
190
+ # bool = villa.out(key)
191
+ # Method: Delete a record.
192
+ # `key' specifies a key. Although it must be an instance of String, binary data is okey.
193
+ # The return value is always true. However, if the silent flag is true and no record
194
+ # corresponds, false is returned instead of exception.
195
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or no record
196
+ # corresponds.
197
+ # When the key of duplicated records is specified, the value of the first record of the same
198
+ # key is selected. The cursor becomes unavailable due to updating database.
199
+ #
200
+ def out(key)
201
+ if(@cmode == CMPOBJ)
202
+ key = Marshal.dump(key)
203
+ end
204
+ mod_out(@index, key)
205
+ end
206
+ ##
207
+ # bool = villa.delete(key)
208
+ # Method: An alias of `out'.
209
+ #
210
+ alias delete out
211
+ ##
212
+ # bool = villa.clear()
213
+ # Method: Delete all records.
214
+ # The return value is always true.
215
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
216
+ #
217
+ def clear
218
+ MyMutex.synchronize() do
219
+ begin
220
+ while(rnum() > 0)
221
+ curfirst();
222
+ out(curkey())
223
+ end
224
+ rescue ENOITEM
225
+ end
226
+ end
227
+ true
228
+ end
229
+ ##
230
+ # str = villa.get(key)
231
+ # Method: Retrieve a record.
232
+ # `key' specifies a key. Although it must be an instance of String, binary data is okey.
233
+ # The return value is an instance of the value of the corresponding record. If the silent flag
234
+ # is true and no record corresponds, nil is returned instead of exception.
235
+ # When the key of duplicated records is specified, the first record of the same key is
236
+ # deleted.
237
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or no record
238
+ # corresponds.
239
+ #
240
+ def get(key)
241
+ if(@cmode == CMPOBJ)
242
+ key = Marshal.dump(key)
243
+ end
244
+ val = mod_get(@index, key)
245
+ if(@cmode == CMPOBJ && val)
246
+ val = Marshal.load(val)
247
+ end
248
+ val
249
+ end
250
+ ##
251
+ # str = villa.fetch(key, defval)
252
+ # Method: Retrieve a record.
253
+ # `key' specifies a key. Although it must be an instance of String, binary data is okey.
254
+ # `defval' specifies the default value used when no record corresponds. If it is omitted, nil
255
+ # is specified.
256
+ # The return value is an instance of the value of the corresponding record, or the default
257
+ # value if no record corresponds.
258
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
259
+ #
260
+ def fetch(key, defval = nil)
261
+ if @silent
262
+ if val = mod_get(@index, key)
263
+ if(@cmode == CMPOBJ)
264
+ val = Marshal.load(val)
265
+ end
266
+ val
267
+ else
268
+ defval
269
+ end
270
+ else
271
+ begin
272
+ val = mod_get(@index, key)
273
+ if(@cmode == CMPOBJ)
274
+ val = Marshal.load(val)
275
+ end
276
+ val
277
+ rescue ENOITEM
278
+ defval
279
+ end
280
+ end
281
+ end
282
+ ##
283
+ # str = villa[key]
284
+ # Method: An alias of `fetch'.
285
+ #
286
+ alias [] fetch
287
+ ##
288
+ # num = villa.vsiz(key)
289
+ # Method: Get the size of the value of a record.
290
+ # `key' specifies a key. Although it must be an instance of String, binary data is okey.
291
+ # The return value is the size of the value of the corresponding record. If the silent flag
292
+ # is true and no record corresponds, -1 is returned instead of exception. If multiple records
293
+ # correspond, the size of the first is returned.
294
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
295
+ #
296
+ def vsiz(key)
297
+ if(@cmode == CMPOBJ)
298
+ key = Marshal.dump(key)
299
+ end
300
+ mod_vsiz(@index, key)
301
+ end
302
+ ##
303
+ # num = villa.vnum(key)
304
+ # Method: Get the number of records corresponding a key.
305
+ # `key' specifies a key. Although it must be an instance of String, binary data is okey.
306
+ # The return value is the size of the value of the corresponding record. If no record
307
+ # corresponds, 0 is returned.
308
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
309
+ #
310
+ def vnum(key)
311
+ if(@cmode == CMPOBJ)
312
+ key = Marshal.dump(key)
313
+ end
314
+ mod_vnum(@index, key)
315
+ end
316
+ ##
317
+ # bool = villa.curfirst()
318
+ # Method: Move the cursor to the first record.
319
+ # The return value is always true. However, if the silent flag is true and no record
320
+ # corresponds, false is returned instead of exception.
321
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or there is
322
+ # no record in the database.
323
+ #
324
+ def curfirst()
325
+ mod_curfirst(@index)
326
+ end
327
+ ##
328
+ # bool = villa.curlast()
329
+ # Method: Move the cursor to the last record.
330
+ # The return value is always true. However, if the silent flag is true and no record
331
+ # corresponds, false is returned instead of exception.
332
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or there is
333
+ # no record in the database.
334
+ #
335
+ def curlast()
336
+ mod_curlast(@index)
337
+ end
338
+ ##
339
+ # bool = villa.curprev()
340
+ # Method: Move the cursor to the previous record.
341
+ # The return value is always true. However, if the silent flag is true and no record
342
+ # corresponds, false is returned instead of exception.
343
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or there is
344
+ # no previous record.
345
+ #
346
+ def curprev()
347
+ mod_curprev(@index)
348
+ end
349
+ ##
350
+ # bool = villa.curnext()
351
+ # Method: Move the cursor to the next record.
352
+ # The return value is always true. However, if the silent flag is true and no record
353
+ # corresponds, false is returned instead of exception.
354
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or there is
355
+ # no next record.
356
+ #
357
+ def curnext()
358
+ mod_curnext(@index)
359
+ end
360
+ ##
361
+ # bool = villa.curjump(key, jmode)
362
+ # Method: Move the cursor to a position around a record.
363
+ # `key' specifies a key. Although it must be an instance of String, binary data is okey.
364
+ # `jmode' specifies detail adjustment: `Villa::JFORWARD', which means that the cursor is set
365
+ # to the first record of the same key and that the cursor is set to the next substitute if
366
+ # completely matching record does not exist, `Villa::JBACKWARD', which means that the cursor
367
+ # is set to the last record of the same key and that the cursor is set to the previous
368
+ # substitute if completely matching record does not exist. If it is omitted, `Villa::JFORWARD'
369
+ # is specified.
370
+ # The return value is always true. However, if the silent flag is true and no record
371
+ # corresponds, false is returned instead of exception.
372
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or there is
373
+ # no record corresponding the condition.
374
+ #
375
+ def curjump(key, jmode = JFORWARD)
376
+ if(@cmode == CMPOBJ)
377
+ key = Marshal.dump(key)
378
+ end
379
+ mod_curjump(@index, key, jmode)
380
+ end
381
+ ##
382
+ # str = villa.curkey()
383
+ # Method: Get the key of the record where the cursor is.
384
+ # The return value is the key of the corresponding record. If the silent flag is true and no
385
+ # record corresponds, nil is returned instead of exception.
386
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or no record
387
+ # corresponds to the cursor.
388
+ #
389
+ def curkey()
390
+ key = mod_curkey(@index)
391
+ if(@cmode == CMPOBJ && key)
392
+ key = Marshal.load(key)
393
+ end
394
+ key
395
+ end
396
+ ##
397
+ # str = villa.curval()
398
+ # Method: Get the value of the record where the cursor is.
399
+ # The return value is the value of the corresponding record. If the silent flag is true and no
400
+ # record corresponds, nil is returned instead of exception.
401
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or no record
402
+ # corresponds to the cursor.
403
+ #
404
+ def curval()
405
+ val = mod_curval(@index)
406
+ if(@cmode == CMPOBJ && val)
407
+ val = Marshal.load(val)
408
+ end
409
+ val
410
+ end
411
+ ##
412
+ # bool = villa.curput(val, cpmode);
413
+ # Method: Insert a record around the cursor.
414
+ # `val' specifies a value. Although it must be an instance of String, binary data is okey.
415
+ # `cpmode' specifies detail adjustment: `Villa::CPCURRENT', which means that the value of the
416
+ # current record is overwritten, `Villa::CPBEFORE', which means that a new record is inserted
417
+ # before the current record, `Villa::CPAFTER', which means that a new record is inserted after
418
+ # the current record. If it is omitted, `Villa::CPCURRENT' is specified.
419
+ # The return value is always true. However, if the silent flag is true and no record
420
+ # corresponds to the cursor, false is returned instead of exception.
421
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or no record
422
+ # corresponds to the cursor.
423
+ # After insertion, the cursor is moved to the inserted record.
424
+ #
425
+ def curput(val, cpmode = CPCURRENT)
426
+ if(@cmode == CMPOBJ)
427
+ val = Marshal.dump(val)
428
+ end
429
+ mod_curput(@index, val, cpmode)
430
+ end
431
+ ##
432
+ # bool = villa.curout();
433
+ # Method: Delete the record where the cursor is.
434
+ # The return value is always true. However, if the silent flag is true and no record
435
+ # corresponds to the cursor, false is returned instead of exception.
436
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or no record
437
+ # corresponds to the cursor.
438
+ # After deletion, the cursor is moved to the next record if possible.
439
+ #
440
+ def curout()
441
+ mod_curout(@index)
442
+ end
443
+ ##
444
+ # bool = villa.settuning(lrecmax, nidxmax, lcnum, ncnum)
445
+ # Method: Set the tuning parameters for performance.
446
+ # `lrecmax' specifies the max number of records in a leaf node of B+ tree. If it is not more
447
+ # than 0, the default value is specified.
448
+ # `nidxmax' specifies the max number of indexes in a non-leaf node of B+ tree. If it is not
449
+ # more than 0, the default value is specified.
450
+ # `lcnum' specifies the max number of caching leaf nodes. If it is not more than 0, the
451
+ # default value is specified.
452
+ # `ncnum' specifies the max number of caching non-leaf nodes. If it is not more than 0, the
453
+ # default value is specified.
454
+ # The return value is always true.
455
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
456
+ # The default setting is equivalent to `vlsettuning(49, 192, 1024, 512)'. Because tuning
457
+ # parameters are not saved in a database, you should specify them every opening a database.
458
+ #
459
+ def settuning(lrecmax, nidxmax, lcnum, ncnum)
460
+ mod_settuning(@index, lrecmax, nidxmax, lcnum, ncnum)
461
+ end
462
+ ##
463
+ # bool = villa.sync()
464
+ # Method: Synchronize updating contents with the file and the device.
465
+ # The return value is always true.
466
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
467
+ # This method is useful when another process uses the connected database file. This method
468
+ # should not be used while the transaction is activated.
469
+ #
470
+ def sync()
471
+ mod_sync(@index)
472
+ end
473
+ ##
474
+ # bool = villa.optimize()
475
+ # Method: Optimize the database.
476
+ # The return value is always true.
477
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
478
+ # In an alternating succession of deleting and storing with overwrite or concatenate,
479
+ # dispensable regions accumulate. This method is useful to do away with them. This method
480
+ # should not be used while the transaction is activated.
481
+ #
482
+ def optimize()
483
+ mod_optimize(@index)
484
+ end
485
+ ##
486
+ # num = villa.fsiz()
487
+ # Method: Get the size of the database file.
488
+ # The return value is the size of the database file.
489
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
490
+ # Because of the I/O buffer, the return value may be less than the real size.
491
+ #
492
+ def fsiz()
493
+ mod_fsiz(@index)
494
+ end
495
+ ##
496
+ # num = villa.rnum()
497
+ # Method: Get the number of the records stored in the database.
498
+ # The return value is the number of the records stored in the database.
499
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
500
+ #
501
+ def rnum()
502
+ mod_rnum(@index)
503
+ end
504
+ ##
505
+ # num = villa.length()
506
+ # Method: An alias of `rnum'.
507
+ #
508
+ alias length rnum
509
+ ##
510
+ # num = villa.size()
511
+ # Method: An alias of `rnum'.
512
+ #
513
+ alias size rnum
514
+ ##
515
+ # bool = villa.writable()
516
+ # Method: Check whether the database handle is a writer or not.
517
+ # The return value is true if the handle is a writer, false if not.
518
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
519
+ #
520
+ def writable()
521
+ mod_writable(@index)
522
+ end
523
+ ##
524
+ # bool = villa.fatalerror()
525
+ # Method: Check whether the database has a fatal error or not.
526
+ # The return value is true if the database has a fatal error, false if not.
527
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
528
+ #
529
+ def fatalerror()
530
+ mod_fatalerror(@index)
531
+ end
532
+ ##
533
+ # bool = villa.tranbegin()
534
+ # Method: Begin the transaction.
535
+ # The return value is always true.
536
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
537
+ # If a thread is already in the transaction, the other threads block until the prius is out
538
+ # of the transaction. Only one transaction can be activated with a database handle at the
539
+ # same time.
540
+ #
541
+ def tranbegin()
542
+ @tranmutex.lock()
543
+ MyMutex.synchronize() do
544
+ begin
545
+ mod_tranbegin(@index)
546
+ rescue
547
+ @tranmutex.unlock()
548
+ raise()
549
+ end
550
+ end
551
+ end
552
+ ##
553
+ # bool = villa.trancommit()
554
+ # Method: Commit the transaction.
555
+ # The return value is always true.
556
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
557
+ # Updating a database in the transaction is fixed when it is committed successfully. Any
558
+ # other thread except for the one which began the transaction should not call this method.
559
+ #
560
+ def trancommit()
561
+ begin
562
+ mod_trancommit(@index)
563
+ ensure
564
+ @tranmutex.unlock()
565
+ end
566
+ end
567
+ ##
568
+ # bool = villa.tranabort()
569
+ # Method: Abort the transaction.
570
+ # The return value is always true.
571
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
572
+ # Updating a database in the transaction is discarded when it is aborted. The state of the
573
+ # database is rollbacked to before transaction. Any other thread except for the one which
574
+ # began the transaction should not call this method.
575
+ #
576
+ def tranabort()
577
+ begin
578
+ mod_tranabort(@index)
579
+ ensure
580
+ @tranmutex.unlock()
581
+ end
582
+ end
583
+ ##
584
+ # villa.transaction() do ... end
585
+ # Iterator Method: Perform an iterator block in the transaction.
586
+ # The specified iterator block is performed in the transaction. If the block returns true,
587
+ # the transaction is committed. If the block returns false or raises any exception, the
588
+ # transaction is aborted.
589
+ #
590
+ def transaction()
591
+ tranbegin()
592
+ begin
593
+ cmt = yield()
594
+ rescue
595
+ cmt = false
596
+ raise()
597
+ ensure
598
+ if(cmt)
599
+ trancommit()
600
+ else
601
+ tranabort()
602
+ end
603
+ end
604
+ end
605
+ ##
606
+ # villa.each() do |key, val| ... end
607
+ # Iterator Method: Iterate a process with a pair of a key and a value of each record.
608
+ #
609
+ def each()
610
+ MyMutex.synchronize() do
611
+ curfirst()
612
+ while(true)
613
+ begin
614
+ break unless key = curkey()
615
+ val = curval()
616
+ yield(key, val)
617
+ curnext()
618
+ rescue ENOITEM
619
+ break
620
+ end
621
+ end
622
+ curfirst()
623
+ end
624
+ self
625
+ end
626
+ ##
627
+ # villa.each_pair() do |key, val| ... end
628
+ # Iterator Method: An alias of `each'.
629
+ #
630
+ alias each_pair each
631
+ ##
632
+ # villa.each_key() do |key| ... end
633
+ # Iterator Method: Iterate a process with a key of each record.
634
+ #
635
+ def each_key()
636
+ MyMutex.synchronize() do
637
+ curfirst()
638
+ while(true)
639
+ begin
640
+ break unless key = curkey()
641
+ curnext()
642
+ yield(key)
643
+ rescue ENOITEM
644
+ break
645
+ end
646
+ end
647
+ curfirst()
648
+ end
649
+ self
650
+ end
651
+ ##
652
+ # villa.each_value() do |val| ... end
653
+ # Iterator Method: Iterate a process with a value of each record.
654
+ #
655
+ def each_value()
656
+ MyMutex.synchronize() do
657
+ curfirst()
658
+ while(true)
659
+ begin
660
+ break unless val = curval()
661
+ curnext()
662
+ yield(val)
663
+ rescue ENOITEM
664
+ break
665
+ end
666
+ end
667
+ curfirst()
668
+ end
669
+ self
670
+ end
671
+ ##
672
+ # ary = villa.keys()
673
+ # Method: Get an array of all keys.
674
+ # The return value is an array of all keys.
675
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
676
+ #
677
+ def keys()
678
+ ary = Array::new(rnum())
679
+ MyMutex.synchronize() do
680
+ begin
681
+ curfirst()
682
+ 0.upto(ary.length - 1) do |i|
683
+ ary[i] = curkey()
684
+ curnext()
685
+ end
686
+ curfirst()
687
+ rescue ENOITEM
688
+ end
689
+ end
690
+ ary
691
+ end
692
+ ##
693
+ # ary = villa.values()
694
+ # Method: Get an array of all values.
695
+ # The return value is an array of all values.
696
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs.
697
+ #
698
+ def values()
699
+ ary = Array::new(rnum())
700
+ MyMutex.synchronize() do
701
+ begin
702
+ curfirst()
703
+ 0.upto(ary.length - 1) do |i|
704
+ ary[i] = curval()
705
+ curnext()
706
+ end
707
+ curfirst()
708
+ rescue ENOITEM
709
+ end
710
+ end
711
+ ary
712
+ end
713
+ ##
714
+ # str = villa.index(val)
715
+ # Method: Retrieve a record with a value.
716
+ # `val' specifies a value. Although it must be an instance of String, binary data is okey.
717
+ # The return value is the key of the record with the specified value.
718
+ # An exception of `Villa::EANY' or its sub classes is thrown if an error occurs or no record
719
+ # corresponds.
720
+ # If two or more records correspond, the first found record is selected.
721
+ #
722
+ def index(val)
723
+ key = nil
724
+ MyMutex.synchronize() do
725
+ curfirst()
726
+ while(true)
727
+ break unless tmp = curval()
728
+ if(tmp == val)
729
+ key = curkey()
730
+ break
731
+ end
732
+ curnext()
733
+ end
734
+ curfirst()
735
+ end
736
+ key
737
+ end
738
+ ##
739
+ # num = villa.to_int()
740
+ # Method: An alias of `rnum'.
741
+ #
742
+ alias to_int rnum
743
+ ##
744
+ # num = villa.to_i()
745
+ # Method: An alias of `to_int'.
746
+ #
747
+ alias to_i to_int
748
+ ##
749
+ # str = villa.to_str()
750
+ # Method: Get string standing for the instance.
751
+ #
752
+ def to_str
753
+ if(@index != -1)
754
+ sprintf("#<Villa:%#x:name=%s:state=open:rnum=%d>",
755
+ object_id(), @name, rnum())
756
+ else
757
+ sprintf("#<Villa:%#x:name=%s:state=closed>", object_id(), @name)
758
+ end
759
+ end
760
+ ##
761
+ # str = villa.to_s()
762
+ # Method: An alias of `to_str'.
763
+ #
764
+ alias to_s to_str
765
+ ##
766
+ # ary = villa.to_ary()
767
+ # Method: Get an array of alternation of each pair of a key and a value.
768
+ #
769
+ def to_ary
770
+ ary = Array::new(rnum())
771
+ i = 0
772
+ each() do |key, val|
773
+ ary[i] = [key, val]
774
+ i += 1
775
+ end
776
+ ary
777
+ end
778
+ ##
779
+ # ary = villa.to_a()
780
+ # Method: An alias of `to_ary'.
781
+ #
782
+ alias to_a to_ary
783
+ ##
784
+ # hash = villa.to_hash()
785
+ # Method: Get a hash storing all records.
786
+ #
787
+ def to_hash
788
+ hash = Hash::new()
789
+ each() do |key, val|
790
+ hash[key] || hash[key] = val
791
+ end
792
+ hash
793
+ end
794
+ ##
795
+ # hash = villa.to_h()
796
+ # Method: An alias of `to_hash'.
797
+ #
798
+ alias to_h to_hash
799
+ ##
800
+ # str = villa.inspect()
801
+ # Method: An alias of `to_str'.
802
+ #
803
+ alias inspect to_str
804
+ end
805
+
806
+
807
+ #----------------------------------------------------------------
808
+ # Alias definition of class methods
809
+ #----------------------------------------------------------------
810
+ class << Villa
811
+ alias open new
812
+ end
813
+
814
+
815
+
816
+ # END OF FILE