ruby-qdbm 0.1

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.
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