pax_global_header00006660000000000000000000000064115471402130014510gustar00rootroot0000000000000052 comment=6aa8054e022fa38055fd441de98b65fd392b8dcb ruby-bdb-0.6.6/000077500000000000000000000000001154714021300132275ustar00rootroot00000000000000ruby-bdb-0.6.6/.gitignore000066400000000000000000000002471154714021300152220ustar00rootroot00000000000000*.html Makefile bdbxml2/bdbxml_features.h bdbxml[12]/*.html bdbxml[12]/*.so bdbxml[12]/docs/*.html docs/*.html src/Makefile src/bdb.so src/bdb_features.h src/mkmf.log ruby-bdb-0.6.6/Changes000066400000000000000000000160631154714021300145300ustar00rootroot00000000000000 -- 0.1.1 first alpha release -- 0.1.2 * error are now BDB::Fatal, BDB::Lock (rather than BDBFatal, ...) * remove BDBKeyExist : it return Qfalse if it fail, or the value inserted * #put return the value * change rb_eFatal in bdb_eFatal * option for array_base (0 or 1) * corrected flags27 * support for bt_compare, bt_prefix, dup_compare, h_hash (see func.rb) * can store nil (like 1.6, a["aa"] = nil don't delete the key) * add #dup_count (count), #get_dup (dup) for BDB::Common * add #partial_clear (same than #clear_partial) * corrected #put for set_partial * remove bdb_recno_length (don't do what I want) * corrected #close (thread_local_aset) * corrected BDB::Unknown (it created object of class BDB::Unknown) * remove shift for Common (only for Recno and Queue) * corrected #length for bdb < 3 with BDB::TXN * add test for RUNIT (only Btree, Hash, Recno) * tested with 3.1.17 * add methods fetch, store, reject!, reject, member?, index, indexes (like 1.5) * add initialize -- 0.1.3 * Queue pad automatically the value (for put && get) * partial_get (set) is strange ??? * add Queue#pad * re_pad return a character (not an int) * corrected nil for Queue * add test for Queue * corrected 2 bugs (thanks Takaaki Tateishi ) - struct timeval - rb_struct_define -- 0.1.4 * corrected rb_iterate() -- 0.1.5 * corrected (thanks Phillipe Lucas ) - db_get_both() - flag --disable-thread to compile on some "stupid" system * add #invert, #clear, #update, #replace -- 0.1.6 * support for 3.2.9 : Thanks Rick Ohnemus * corrected flags for DUP_SORT * add BDB::Env.set_flags for 3.2.9 * 3.2.9 : bt_compare, bt_prefix, dup_compare, h_hash take now 3 args -- 0.1.7 * BDB::Env#remove is now a class method * corrected Lock for DB < 3 * added Log * tests for Log * error BDB::LockError, BDB::LockHeld, BDB::LockGranted, BDB::LockDead -- 0.1.8 * protected env against GC for Log, Lock * added BDB::Recnum -- 0.1.9 * corrected DB_SET_BOTH (Thanks "Peter J. Kernan" ) * added warning for BDB::Unknown and Recnum, Recno * corrected re-definition of RECNUM -- 0.2.0 * better interface with Marshal (experimental) -- 0.2.1 * new syntax "marshal" => Marshal (or any module with #load, #dump) * tested with 3.3.11 * txn_prepare take now an extra argument with 3.3.11 * secondary index for 3.3.11 (see #associate) * partial implementation of #pget -- 0.2.2 * corrected set_rpc_server for 3.3.11 * added support for bulk retrieval (#each, #each_value, #each_key) 3.3.11 -- 0.2.3 * search libdb3 before libdb (src/extconf.rb) (Thanks "Akinori MUSHA" ) * BDB::Common::remove for >= 3 * BDB::Common::truncate alias of BDB::Common::clear * BDB::Env#recover && BDB::Txn#discard for >= 3.3.11 * BDB::Common#each_dup, BDB::Common#each_dup_value, BDB::Common#duplicates * BDB::Common#each_primary, BDB::Common#reverse_each_primary 3.3.11 -- 0.2.4 * delegator also for #each, #each_dup, #duplicates, etc * #get_dup (without delegator) -- 0.2.5 * corrected lg_max, lg_bsize (Thanks Joseph McDonald ) * added Cursor#pget * added some tests for secondary indexes * corrected constants -- 0.2.6 * corrected lock_get (Thanks Darrin Thompson ) * lock_vec now return always an array with (lockid for GET, nil for PUT) -- 0.2.7 * corrected an error for Recnum#indexes * corrected Recnum#unshift (length) * corrected Recnum#delete_at * set_q_extendsize (Queue), set_tx_timestamp * support for 4.0 * replication (not tested) * set_{txn,lock,}timeout * options for Env::begin * corrected a stupid bug introduced in 0.2.6 -- 0.2.8 * corrected stat for winxx * accept 'extend Marshal' * corrected bug with gc (test_dump) * protected against old class -- 0.2.9 * stupid bug with free() * added -R for Solaris 2 (Thanks Amos Gouaux ) -- 0.3.0 * added --with-uniquename to extconf.rb (Thanks Matt Armstrong ) * rep_process_message return [code, cdata, envid] * added Common#filename, Common#database (Common#subname), Env#home * example for replication * txn_begin (argv++) * add flags to Common#stat * add Common#verify (>= 3.3.11) * corrected no_thread for Common::open -- 0.3.1 * added --with-db-version to extconf.rb (Thanks "Akinori MUSHA" ) * patch from "akira yamada" (Thanks) - examples/cursor.rb - BDB::Queue#stat (-1) - test suite : specification of assert was changed * tests for RUNIT/Test::Unit * filter function like P language (bdb_{store,fetch}_{key,value}) -- 0.3.2 * stupid bug with GC * Common#select (1.7.2) * switch on model allocate/initialize (IDLI) * ::open == ::new + block * 1.7.2 Recnum#map, #insert * first modifications for xdb * patch for tests (Thanks "WATANABE Hirofumi" ) * flatten! ===> txn.begin(a, b, c) {|t, a1, b1, c1| } -- 0.3.3 * typo in bdb_select (Thanks "Fritz Heinrichmeyer " ) * support for db-4.1.16 - set_append_recno - cache_priority, cache_priority= - set_encrypt - dbremove, dbrename * new BDB::Txn::open_db * BDB::ENV, BDB::Common : "set_feedback", feedback= for db >= 3. * documentation : make rd2; make rdoc * experimental bdbxml for DbXml (not yet released) --- 0.3.4 * set_rep_limit, set_app_dispatch for db 4.1.16 * BDB::Common::[] * better (???) interface to transaction for 4.1.16 * Lsn#env * corrected set_fetch_value * complete support for AUTO_COMMIT * added "flags" for #each, #cursor. new #write_cursor (Thanks Darrin Thompson ) --- 0.3.5 * INT2NUM(DB_RMW) rather than INT2FIX() (Thanks Darrin Thompson ) * adapted for 4.1.24 (DB_CURLSN is removed) --- 0.3.8 * adapted for 1.8.0 --- 0.3.9 * better interface at exit * dbconfig for <= 2 --- 0.4.0 * adapted for debian (extconf.rb) --- 0.4.8 * corrected various bug with 1.8.0 * corrected lock_id_free, marshal with recnum (Thanks YAEGASHI Takeshi ) - added method Lockid#close --- 0.4.9 * adapted (???) for win32 * corrected app_dispatch, env_stat * corrected #fetch * corrected Log * protected internal cursors * change return value for Queue#push (return indices) * adapted for 4.2.50 * added Common#conf, Env#conf (4.2.50) * corrected Common#select * corrected Log#log_get --- 0.5.2 * corrected #duplicates and added Btree#{reverse_}each_by_prefix (Thanks Satoru Takabayashi ) * corrected #begin (flatten!) for 1.9 --- 0.5.3 * compile for 4.3 * BDB::Sequence (not tested) --- 0.5.5 * store_nil_as_null (see README.en) * patch bdb_TXN (Thanks akira yamada ) --- 0.5.8 * patch #associate (Thanks Dan Janowsky * adapted to db 4.4 --- 0.5.9 * rb_frame_last_func(), GetWriteFile() (Thanks akira yamada ) --- 0.6.2 * patch from Akinori MUSHA --- 0.6.3 * updated for dbxml-2.4 --- 0.6.4 * update for db 4.7 --- 0.6.5 * massive compatibility fixes * introduced --enable-db-xml for use with bdbxml2 --- 0.6.6 * ruby 1.9 support ruby-bdb-0.6.6/README.en000066400000000000000000000025061154714021300145130ustar00rootroot00000000000000 This is an interface to Berkeley DB, distributed by Sleepycat (http://www.sleepycat.com/) * Prerequisite db >= 2 (some functionnality like join are not available with db < 2.6) For Berkeley DB 1.85 and 1.86 see bdb1 * Installation ruby extconf.rb make make install You may need to specify : --with-db-include= --with-db-lib= --with-db-dir= --enable-db-xml --help Example : ruby extconf.rb --with-db-dir=/home/ts/local * WARNING With bdb >= 0.5.5 `nil' is stored as an empty string (when marshal is not used). Open the database with "store_nil_as_null" => true if you want the old behavior (`nil' stored as `\000') * examples examples/basic.rb simple access method examples/recno.rb access to flat file examples/cursor.rb direct cursor access examples/txn.rb transaction examples/join.rb join (need db >= 2.6) examples/log.rb log file * Documentation : see bdb.rd and bdb.html * Tests : if you have rubyunit, or testunit make test * Copying This extension module is copyrighted free software by Guy Decoux You can redistribute it and/or modify it under the same term as Ruby. Guy Decoux ruby-bdb-0.6.6/bdb.rd000066400000000000000000000075451154714021300143200ustar00rootroot00000000000000=begin = BDB (()) Berkeley DB is an embedded database system that supports keyed access to data. Developers may choose to store data in any of several different storage structures to satisfy the requirements of a particular application. In database terminology, these storage structures and the code that operates on them are called access methods. == ............................................................... With bdb >= 0.5.5 ((|nil|)) is stored as an empty string (when marshal is not used). Open the database with "store_nil_as_null" => true if you want the old behavior (((|nil|)) stored as `\000') == ............................................................... The library includes support for the following access methods: * B+tree: Stores keys in sorted order, using a default function that does lexicographical ordering of keys. * Hashing: Stores records in a hash table for fast searches based on strict equality, using a default that hashes on the key as a bit string. Extended Linear Hashing modifies the hash function used by the table as new records are inserted, in order to keep buckets underfull in the steady state. * Fixed and Variable-Length Records: Stores fixed- or variable-length records in sequential order. Record numbers may be immutable, requiring that new records be added only at the end of the database, or mutable, permitting new records to be inserted between existing records. (()) Berkeley DB environment is an encapsulation of one or more databases, log files and shared information about the database environment such as shared memory buffer cache pages. Acces Methods * (()) these are the common methods for BDB::Btree, BDB::Hash, BDB::Recno, BDB::Queue * (()) methods for BDB::Recnum (()) A sequence is created with BDB::Common::create_sequence or BDB::Common::open_sequence (only with db >= 4.3) (()) The transaction subsystem makes operations atomic, consistent, isolated, and durable in the face of system and application failures. The subsystem requires that the data be properly logged and locked in order to attain these properties. Berkeley DB contains all the components necessary to transaction-protect the Berkeley DB access methods and other forms of data may be protected if they are logged and locked appropriately. (()) A database cursor is a sequential pointer to the database entries. It allows traversal of the database and access to duplicate keyed entries. Cursors are used for operating on collections of records, for iterating over a database, and for saving handles to individual records, so that they can be modified after they have been read. See also iterators in (()) (()) The lock subsystem provides interprocess and intraprocess concurrency control mechanisms. While the locking system is used extensively by the Berkeley DB access methods and transaction system, it may also be used as a stand-alone subsystem to provide concurrency control to any set of designated resources. (()) The logging subsystem is the logging facility used by Berkeley DB. It is largely Berkeley DB specific, although it is potentially useful outside of the Berkeley DB package for applications wanting write-ahead logging support. Applications wanting to use the log for purposes other than logging file modifications based on a set of open file descriptors will almost certainly need to make source code modifications to the Berkeley DB code base. =end ruby-bdb-0.6.6/bdbxml1/000077500000000000000000000000001154714021300145605ustar00rootroot00000000000000ruby-bdb-0.6.6/bdbxml1/Changes000066400000000000000000000016071154714021300160570ustar00rootroot00000000000000 * ::rename, ::remove : added flags * new Con::set_name --- adapted for 1.0.11 * removed #encoding * added Document#query * adapted for 1.8 * corrected #index, #get_index * added #indexes, #declare_index * #to_a, #each for Nodes --- adapted for 1.0.14 * XML::Index * changed XML::Container#index * constant XML::Name[], XML::Namespace[] * XML::Container#context, XML::UpdateContext * XML::Container#open? --- adapted for 1.1.0 * constant XML::CHKSUM_SHA1, XML::ENCRYPT for Container::new * corrected XML::Document#query * added XML::Results#to_a, #size * changed XML::NodeList#to_s --- 0.4.5 * added --with-bdb-objs for Mac OS X (Thanks Richard Kilmer ) * corrected b.rb --- adapted for 1.1.1 * removed List, it return now Node * Document::query(Xpath) --- adapted for 1.1.2 (1.2.0) * corrected Container#open? * added XML::Modify, Document#modify, Container#modify ruby-bdb-0.6.6/bdbxml1/README.en000066400000000000000000000023161154714021300160430ustar00rootroot00000000000000 This is an interface to Berkeley DB XML, distributed by Sleepycat (http://www.sleepycat.com/products/xml.shtml) * Installation .... first build bdb which is in '../src', and use this version of bdb for use with bdbxml .... modify './myconfig' to adapt it to your configuration IMPORTANT : you must use a version of xercesc compiled *without* threads .... This version must be used with [db-4.1.25, DbXml 1.1.0] .... ruby extconf.rb make make install .... if you want to make a shared version which use the object files from ../src, specify the flag --with-bdb-objs when you run extconf.rb ruby extconf.rb --with-bdb-objs make make install Use this option if you work on Mac OS X : read also http://www.opendarwin.org/pipermail/hackers/2003-January/000389.html http://www.opendarwin.org/pipermail/hackers/2003-January/000391.html http://www.mail-archive.com/darwin-gcc3@opensource.apple.com/msg00044.html * Documentation : make rd2 make rdoc * Copying This extension module is copyrighted free software by Guy Decoux You can redistribute it and/or modify it under the same term as Ruby. Guy Decoux ruby-bdb-0.6.6/bdbxml1/b.rb000077500000000000000000000015671154714021300153420ustar00rootroot00000000000000#!/usr/bin/ruby -I../src $LOAD_PATH.unshift "../src" require 'bdbxml' p BDB::XML::Name env = BDB::Env.new("tmp", BDB::CREATE | BDB::INIT_TRANSACTION) doc = env.open_xml("toto", "a") doc.each {|x| p x } index = doc.index index.add("http://moulon.inra.fr/", "reference", "node-attribute-equality-string") doc.index = index bdb = env.open_db(BDB::Btree, "tutu", nil, "a") 2.times do |i| doc.push("title nb #{i}") bdb[i] = "bdb#{i}" end env.begin(doc, bdb) do |txn, doc1, bdb1| 2.times do |i| bdb1[i+2] = "bdb#{i+2}" doc1.push("title nb #{i+2}") end puts "=========================================" doc1.each {|x| p x } bdb1.each {|k,v| p "#{k} -- #{v}" } # implicit txn.abort end puts "=========================================" doc.each {|x| p x } bdb.each {|k,v| p "#{k} -- #{v}" } ruby-bdb-0.6.6/bdbxml1/bdbxml.cc000066400000000000000000001772361154714021300163570ustar00rootroot00000000000000#include "bdbxml.h" static VALUE xb_eFatal, xb_cTxn, xb_cEnv, xb_cRes; static VALUE xb_cCon, xb_cDoc, xb_cCxt, xb_cPat, xb_cTmp; static VALUE xb_cInd, xb_cUpd, xb_cMod; #if defined(DBXML_DOM_XERCES2) #if BDBXML_VERSION < 10101 static VALUE xb_cNol, xb_cNod; #else static VALUE xb_cNod; #endif #endif static ID id_current_env; static VALUE xb_s_new(int argc, VALUE *argv, VALUE obj) { VALUE res = rb_funcall2(obj, rb_intern("allocate"), 0, 0); rb_obj_call_init(res, argc, argv); return res; } static VALUE xb_int_close(VALUE obj) { return rb_funcall2(obj, rb_intern("close"), 0, 0); } static VALUE xb_s_open(int argc, VALUE *argv, VALUE obj) { VALUE res = rb_funcall2(obj, rb_intern("new"), argc, argv); if (rb_block_given_p()) { return rb_ensure(RMF(rb_yield), res, RMF(xb_int_close), res); } return res; } static void xb_doc_free(xdoc *doc) { if (doc->doc) { delete doc->doc; } } static void xb_doc_mark(xdoc *doc) { rb_gc_mark(doc->uri); rb_gc_mark(doc->prefix); } static VALUE xb_doc_s_alloc(VALUE obj) { xdoc *doc; VALUE res = Data_Make_Struct(obj, xdoc, (RDF)xb_doc_mark, (RDF)xb_doc_free, doc); doc->doc = new XmlDocument(); return res; } static VALUE xb_doc_content_set(VALUE, VALUE); static VALUE xb_doc_init(int argc, VALUE *argv, VALUE obj) { VALUE a; if (rb_scan_args(argc, argv, "01", &a)) { xb_doc_content_set(obj, a); } return obj; } static VALUE xb_doc_name_get(VALUE obj) { xdoc *doc; Data_Get_Struct(obj, xdoc, doc); return rb_tainted_str_new2(doc->doc->getName().c_str()); } static VALUE xb_doc_name_set(VALUE obj, VALUE a) { xdoc *doc; char *str = StringValuePtr(a); Data_Get_Struct(obj, xdoc, doc); PROTECT(doc->doc->setName(str)); return a; } static VALUE xb_doc_content_get(VALUE obj) { xdoc *doc; std::string str; Data_Get_Struct(obj, xdoc, doc); doc->doc->getContentAsString(str); return rb_tainted_str_new2(str.c_str()); } static VALUE xb_doc_content_set(VALUE obj, VALUE a) { xdoc *doc; char *str = NULL; Data_Get_Struct(obj, xdoc, doc); str = StringValuePtr(a); PROTECT(doc->doc->setContent(str)); return a; } static VALUE xb_xml_val(XmlValue *, VALUE); static XmlValue xb_val_xml(VALUE); static VALUE xb_doc_get(int argc, VALUE *argv, VALUE obj) { VALUE a, b, c; xdoc *doc; XmlValue val = ""; bool result; std::string uri = ""; std::string name; Data_Get_Struct(obj, xdoc, doc); if (TYPE(doc->uri) == T_STRING) { uri = StringValuePtr(doc->uri); } switch (rb_scan_args(argc, argv, "12", &a, &b, &c)) { case 3: if (!NIL_P(c) && TYPE(c) != T_CLASS) { rb_raise(xb_eFatal, "expected a class object"); } if (c == rb_cTrueClass || c == rb_cFalseClass) { val = true; } else if (RTEST(rb_funcall(rb_cNumeric, rb_intern(">="), 1, c))) { val = 12.0; } else if (NIL_P(c) || c == rb_cNilClass || RTEST(rb_funcall(rb_cString, rb_intern(">="), 1, c))) { val = ""; } else { rb_raise(xb_eFatal, "invalid class object"); } // ... // case 2: if (!NIL_P(a)) { uri = StringValuePtr(a); } name = StringValuePtr(b); break; case 1: name = StringValuePtr(a); break; } PROTECT(result = doc->doc->getMetaData(uri, name, val)); if (result) { return xb_xml_val(&val, 0); } return rb_str_new2(""); } static VALUE xb_doc_set(int argc, VALUE *argv, VALUE obj) { xdoc *doc; VALUE a, b, c, d; std::string uri = ""; std::string prefix = ""; std::string name; Data_Get_Struct(obj, xdoc, doc); if (TYPE(doc->uri) == T_STRING) { uri = StringValuePtr(doc->uri); } if (TYPE(doc->prefix) == T_STRING) { prefix = StringValuePtr(doc->prefix); } switch (rb_scan_args(argc, argv, "22", &a, &b, &c, &d)) { case 4: uri = StringValuePtr(a); prefix = StringValuePtr(b); name = StringValuePtr(c); break; case 3: prefix = StringValuePtr(a); name = StringValuePtr(b); d = c; break; case 2: name = StringValuePtr(a); d = b; break; } doc->doc->setMetaData(uri, prefix, name, xb_val_xml(d)); return b; } static VALUE xb_doc_id_get(VALUE obj) { xdoc *doc; Data_Get_Struct(obj, xdoc, doc); return INT2FIX(doc->doc->getID()); } static VALUE xb_doc_uri_get(VALUE obj) { xdoc *doc; Data_Get_Struct(obj, xdoc, doc); if (TYPE(doc->uri) == T_STRING) { return rb_str_dup(doc->uri); } return rb_str_new2(""); } static VALUE xb_doc_uri_set(VALUE obj, VALUE a) { xdoc *doc; Check_Type(a, T_STRING); Data_Get_Struct(obj, xdoc, doc); doc->uri = rb_str_dup(a); return obj; } static VALUE xb_doc_prefix_get(VALUE obj) { xdoc *doc; Data_Get_Struct(obj, xdoc, doc); if (TYPE(doc->prefix) == T_STRING) { return rb_str_dup(doc->prefix); } return rb_str_new2(""); } static VALUE xb_doc_prefix_set(VALUE obj, VALUE a) { xdoc *doc; Check_Type(a, T_STRING); Data_Get_Struct(obj, xdoc, doc); doc->prefix = rb_str_dup(a); return obj; } #if defined(DBXML_DOM_XERCES2) #include #include #include #include #include #include #include #include #include #include #include #define XCNQ XERCES_CPP_NAMESPACE_QUALIFIER const char *serialiseNode(XCNQ DOMNode *toWrite) { std::ostringstream result; char *tmp; char *nodeName = XCNQ XMLString::transcode(toWrite->getNodeName()); char *nodeValue = XCNQ XMLString::transcode(toWrite->getNodeValue()); switch (toWrite->getNodeType()) { case XCNQ DOMNode::DOCUMENT_NODE: { result << "\n"; XCNQ DOMNode *child = toWrite->getFirstChild(); while (child != 0) { result << serialiseNode(child); child = child->getNextSibling(); } break; } case XCNQ DOMNode::DOCUMENT_TYPE_NODE: { XCNQ DOMDocumentType *docTypeNode = (XCNQ DOMDocumentType *)toWrite; result << "getName(); char *pubID = XCNQ XMLString::transcode(docTypeNode->getPublicId()); char *sysID = XCNQ XMLString::transcode(docTypeNode->getSystemId()); if (pubID != NULL && pubID[0] != 0) { result << " PUBLIC \"" << pubID << "\" \"" << sysID << "\""; } else { if (sysID != NULL && sysID[0] != 0) { result << " SYSTEM \"" << sysID << "\""; } } XCNQ XMLString::release(&pubID); XCNQ XMLString::release(&sysID); result << ">"; rb_warning("A DOCTYPE tag was output, contents of tag will be empty"); break; } case XCNQ DOMNode::ELEMENT_NODE: { result << "<" << nodeName; XCNQ DOMNamedNodeMap *attributes = toWrite->getAttributes(); int attrCount = attributes->getLength(); for (int i = 0; i < attrCount; i++) { XCNQ DOMNode *attribute = attributes->item(i); tmp = XCNQ XMLString::transcode(attribute->getNodeName()); result << " " << tmp; XCNQ XMLString::release(&tmp); tmp = XCNQ XMLString::transcode(attribute->getNodeValue()); result << "=\"" << tmp; XCNQ XMLString::release(&tmp); result << "\""; } if (toWrite->hasChildNodes()) { result << ">"; XCNQ DOMNode *child = toWrite->getFirstChild(); while (child != 0) { result << serialiseNode(child); child = child->getNextSibling(); } result << ""; } else { result << "/>"; } break; } case XCNQ DOMNode::ATTRIBUTE_NODE: tmp = XCNQ XMLString::transcode(toWrite->getNamespaceURI()); if (tmp && tmp[0]) { result << "{" << tmp << "}"; XCNQ XMLString::release(&tmp); } result << nodeName << "=\"" << nodeValue << "\""; break; case XCNQ DOMNode::TEXT_NODE: result << nodeValue; break; case XCNQ DOMNode::ENTITY_REFERENCE_NODE: { XCNQ DOMNode *child = toWrite->getFirstChild(); while (child != 0) { result << serialiseNode(child); child = child->getNextSibling(); } break; } case XCNQ DOMNode::PROCESSING_INSTRUCTION_NODE: result << ""; break; case XCNQ DOMNode::CDATA_SECTION_NODE: result << ""; break; case XCNQ DOMNode::COMMENT_NODE: result << ""; break; case XCNQ DOMNode::DOCUMENT_FRAGMENT_NODE: if (toWrite->hasChildNodes()) { XCNQ DOMNode *child = toWrite->getFirstChild(); while (child != 0) { result << serialiseNode(child); child = child->getNextSibling(); } } break; default: rb_warning("Unrecognized node type: %d", toWrite->getNodeType()); break; } XCNQ XMLString::release(&nodeName); XCNQ XMLString::release(&nodeValue); return result.str().c_str(); } static VALUE xb_nod_to_s(VALUE obj) { XCNQ DOMNode *node; Data_Get_Struct(obj, XCNQ DOMNode, node); return rb_str_new2(serialiseNode(node)); } static VALUE xb_nod_inspect(VALUE obj) { return rb_str_inspect(xb_nod_to_s(obj)); } static void xb_nol_free(xnol *nol) { ::free(nol); } #if BDBXML_VERSION < 10101 #if defined(DBXML_DOM_XERCES2) static void xb_nol_mark(xnol *nol) { rb_gc_mark(nol->cxt_val); } #endif static VALUE xb_nol_size(VALUE obj) { xnol *nol; Data_Get_Struct(obj, xnol, nol); return INT2NUM(nol->nol->getLength()); } static VALUE xb_nol_get(VALUE obj, VALUE a) { xnol *nol; XCNQ DOMNode *item; int index; Data_Get_Struct(obj, xnol, nol); index = NUM2INT(a); if (index < 0) { index += nol->nol->getLength(); } if (index < 0) { return Qnil; } item = nol->nol->item(index); if (item == NULL) { return Qnil; } return Data_Wrap_Struct(xb_cNod, 0, 0, item); } static VALUE xb_nol_each(VALUE obj) { int i = 0; VALUE item; while ((item = xb_nol_get(obj, INT2NUM(i))) != Qnil) { rb_yield(item); i += 1; } return Qnil; } static VALUE xb_nol_to_ary(VALUE obj) { int i = 0; VALUE item, res; res = rb_ary_new(); while ((item = xb_nol_get(obj, INT2NUM(i))) != Qnil) { rb_ary_push(res, item); i += 1; } return res; } static VALUE xb_nol_inspect(VALUE obj) { return rb_funcall2(xb_nol_to_ary(obj), rb_intern("inspect"), 0, 0); } static VALUE xb_nol_to_str(VALUE obj) { return rb_funcall2(xb_nol_to_ary(obj), rb_intern("to_s"), 0, 0); } #endif #endif static VALUE xb_xml_val(XmlValue *val, VALUE cxt_val) { VALUE res; xdoc *doc; #if defined(DBXML_DOM_XERCES2) && BDBXML_VERSION < 10101 xnol *nol; #endif xcxt *cxt; XmlQueryContext *qcxt = 0; if (cxt_val) { Data_Get_Struct(cxt_val, xcxt, cxt); qcxt = cxt->cxt; } if (val->isNull()) { return Qnil; } switch (val->getType(qcxt)) { case XmlValue::STRING: res = rb_tainted_str_new2(val->asString(qcxt).c_str()); break; case XmlValue::NUMBER: res = rb_float_new(val->asNumber(qcxt)); break; case XmlValue::BOOLEAN: res = (val->asBoolean(qcxt))?Qtrue:Qfalse; break; case XmlValue::DOCUMENT: res = Data_Make_Struct(xb_cDoc, xdoc, (RDF)xb_doc_mark, (RDF)xb_doc_free, doc); doc->doc = new XmlDocument(val->asDocument(qcxt)); break; #if defined(DBXML_DOM_XERCES2) #if BDBXML_VERSION < 10101 case XmlValue::NODELIST: res = Data_Make_Struct(xb_cNol, xnol, (RDF)xb_nol_mark, (RDF)xb_nol_free, nol); nol->nol = val->asNodeList(qcxt); nol->cxt_val = cxt_val; break; case XmlValue::ATTRIBUTE: res = Data_Wrap_Struct(xb_cNod, 0, 0, val->asAttribute(qcxt)); break; #else case XmlValue::NODE: res = Data_Wrap_Struct(xb_cNod, 0, 0, val->asNode(qcxt)); break; #endif #endif case XmlValue::VARIABLE: rb_raise(xb_eFatal, "a context is required"); break; default: rb_raise(xb_eFatal, "Unknown type"); break; } return res; } static XmlValue xb_val_xml(VALUE a) { XmlValue val; xdoc *doc; #if defined(DBXML_DOM_XERCES2) xnol *nol; #endif if (NIL_P(a)) { return XmlValue(); } switch (TYPE(a)) { case T_STRING: val = XmlValue(StringValuePtr(a)); break; case T_FIXNUM: case T_FLOAT: case T_BIGNUM: val = XmlValue(NUM2DBL(a)); break; case T_TRUE: val = XmlValue(true); break; case T_FALSE: val = XmlValue(false); break; case T_DATA: if (RDATA(a)->dfree == (RDF)xb_doc_free) { Data_Get_Struct(a, xdoc, doc); val = XmlValue(*(doc->doc)); break; } #if defined(DBXML_DOM_XERCES2) if (RDATA(a)->dfree == (RDF)xb_nol_free) { Data_Get_Struct(a, xnol, nol); val = XmlValue(nol->nol); break; } #endif /* ... */ default: val = XmlValue(StringValuePtr(a)); break; } return val; } static void xb_pat_free(XmlQueryExpression *pat) { delete pat; } static VALUE xb_pat_to_str(VALUE obj) { XmlQueryExpression *pat; Data_Get_Struct(obj, XmlQueryExpression, pat); return rb_tainted_str_new2(pat->getXPathQuery().c_str()); } static void xb_cxt_free(xcxt *cxt) { delete cxt->cxt; } static VALUE xb_cxt_s_alloc(VALUE obj) { VALUE res; xcxt *cxt; res = Data_Make_Struct(obj, xcxt, 0, (RDF)xb_cxt_free, cxt); cxt->cxt = new XmlQueryContext(); return res; } static VALUE xb_cxt_init(int argc, VALUE *argv, VALUE obj) { xcxt *cxt; XmlQueryContext::ReturnType rt; XmlQueryContext::EvaluationType et; VALUE a, b; Data_Get_Struct(obj, xcxt, cxt); switch (rb_scan_args(argc, argv, "02", &a, &b)) { case 2: et = XmlQueryContext::EvaluationType(NUM2INT(b)); PROTECT(cxt->cxt->setEvaluationType(et)); /* ... */ case 1: if (!NIL_P(a)) { rt = XmlQueryContext::ReturnType(NUM2INT(a)); PROTECT(cxt->cxt->setReturnType(rt)); } } return obj; } static VALUE xb_cxt_name_set(VALUE obj, VALUE a, VALUE b) { xcxt *cxt; char *pre, *uri; Data_Get_Struct(obj, xcxt, cxt); if (NIL_P(b)) { cxt->cxt->removeNamespace(StringValuePtr(a)); return a; } pre = StringValuePtr(a); uri = StringValuePtr(b); PROTECT(cxt->cxt->setNamespace(pre, uri)); return obj; } static VALUE xb_cxt_name(VALUE obj) { xcxt *cxt; VALUE res; Data_Get_Struct(obj, xcxt, cxt); res = Data_Wrap_Struct(xb_cTmp, 0, 0, cxt); rb_define_singleton_method(res, "[]=", RMF(xb_cxt_name_set), 2); return res; } static VALUE xb_cxt_name_get(VALUE obj, VALUE a) { xcxt *cxt; Data_Get_Struct(obj, xcxt, cxt); return rb_tainted_str_new2(cxt->cxt->getNamespace(StringValuePtr(a)).c_str()); } static VALUE xb_cxt_name_del(VALUE obj, VALUE a) { xcxt *cxt; Data_Get_Struct(obj, xcxt, cxt); cxt->cxt->removeNamespace(StringValuePtr(a)); return a; } static VALUE xb_cxt_clear(VALUE obj) { xcxt *cxt; Data_Get_Struct(obj, xcxt, cxt); cxt->cxt->clearNamespaces(); return obj; } static VALUE xb_cxt_get(VALUE obj, VALUE a) { xcxt *cxt; XmlValue val; Data_Get_Struct(obj, xcxt, cxt); cxt->cxt->getVariableValue(StringValuePtr(a), val); if (val.isNull()) { return Qnil; } return xb_xml_val(&val, obj); } static VALUE xb_cxt_set(VALUE obj, VALUE a, VALUE b) { xcxt *cxt; XmlValue val = xb_val_xml(b); VALUE res = xb_cxt_get(obj, a); Data_Get_Struct(obj, xcxt, cxt); cxt->cxt->setVariableValue(StringValuePtr(a), val); return res; } static VALUE xb_cxt_return_get(VALUE obj) { xcxt *cxt; Data_Get_Struct(obj, xcxt, cxt); return INT2NUM(cxt->cxt->getReturnType()); } static VALUE xb_cxt_return_set(VALUE obj, VALUE a) { xcxt *cxt; XmlQueryContext::ReturnType rt; Data_Get_Struct(obj, xcxt, cxt); rt = XmlQueryContext::ReturnType(NUM2INT(a)); PROTECT(cxt->cxt->setReturnType(rt)); return a; } static VALUE xb_cxt_eval_get(VALUE obj) { xcxt *cxt; Data_Get_Struct(obj, xcxt, cxt); return INT2NUM(cxt->cxt->getEvaluationType()); } static VALUE xb_cxt_eval_set(VALUE obj, VALUE a) { xcxt *cxt; XmlQueryContext::EvaluationType et; Data_Get_Struct(obj, xcxt, cxt); et = XmlQueryContext::EvaluationType(NUM2INT(a)); PROTECT(cxt->cxt->setEvaluationType(et)); return a; } #if BDBXML_VERSION >= 10200 static VALUE xb_cxt_meta_get(VALUE obj) { xcxt *cxt; Data_Get_Struct(obj, xcxt, cxt); return cxt->cxt->getWithMetaData()?Qtrue:Qfalse; } static VALUE xb_cxt_meta_set(VALUE obj, VALUE a) { xcxt *cxt; Data_Get_Struct(obj, xcxt, cxt); PROTECT(cxt->cxt->setWithMetaData(RTEST(a))); return a; } #endif static void xb_res_free(xres *xes) { delete xes->res; ::free(xes); } static void xb_res_mark(xres *xes) { rb_gc_mark(xes->txn_val); rb_gc_mark(xes->cxt_val); } static VALUE xb_res_search(VALUE obj) { xres *xes; XmlValue val; XmlDocument document; xdoc *doc; bool result; DbTxn *txn = 0; VALUE res = Qnil, tmp; XmlQueryContext::ReturnType rt; Data_Get_Struct(obj, xres, xes); if (xes->txn_val) { bdb_TXN *txnst; GetTxnDBErr(xes->txn_val, txnst, xb_eFatal); txn = static_cast(txnst->txn_cxx); } if (!rb_block_given_p()) { res = rb_ary_new(); } rt = XmlQueryContext::ResultValues; if (xes->cxt_val) { xcxt *cxt; Data_Get_Struct(xes->cxt_val, xcxt, cxt); rt = cxt->cxt->getReturnType(); } try { xes->res->reset(); } catch (...) {} while (true) { tmp = Qnil; switch (rt) { case XmlQueryContext::ResultValues: PROTECT(result = xes->res->next(txn, val)); if (result) { tmp = xb_xml_val(&val, xes->cxt_val); } break; case XmlQueryContext::ResultDocuments: PROTECT(result = xes->res->next(txn, document)); if (result) { tmp = Data_Make_Struct(xb_cDoc, xdoc, (RDF)xb_doc_mark, (RDF)xb_doc_free, doc); doc->doc = new XmlDocument(document); } break; case XmlQueryContext::ResultDocumentsAndValues: PROTECT(result = xes->res->next(txn, document, val)); if (result) { tmp = Data_Make_Struct(xb_cDoc, xdoc, (RDF)xb_doc_mark, (RDF)xb_doc_free, doc); doc->doc = new XmlDocument(document); tmp = rb_assoc_new(tmp, xb_xml_val(&val, xes->cxt_val)); } break; } if (NIL_P(tmp)) { break; } if (NIL_P(res)) { rb_yield(tmp); } else { rb_ary_push(res, tmp); } } if (NIL_P(res)) { return obj; } return res; } static VALUE xb_res_each(VALUE obj) { if (!rb_block_given_p()) { rb_raise(rb_eArgError, "block not supplied"); } return xb_res_search(obj); } static VALUE xb_res_size(VALUE obj) { xres *xes; size_t siz; Data_Get_Struct(obj, xres, xes); try { siz = xes->res->size(); } catch (...) { return Qnil; } return INT2NUM(siz); } struct xb_eiv { xcon *con; }; static void xb_con_mark(xcon *con) { rb_gc_mark(con->env_val); rb_gc_mark(con->txn_val); rb_gc_mark(con->name); } static void xb_con_i_close(xcon *con, int flags, bool protect) { bdb_ENV *envst; bdb_TXN *txnst; if (!con->closed) { if (RTEST(con->txn_val)) { int opened = 0; Data_Get_Struct(con->txn_val, bdb_TXN, txnst); opened = bdb_ary_delete(&txnst->db_ary, con->ori_val); if (!opened) { opened = bdb_ary_delete(&txnst->db_assoc, con->ori_val); } if (opened) { if (txnst->options & BDB_TXN_COMMIT) { rb_funcall2(con->txn_val, rb_intern("commit"), 0, 0); } else { rb_funcall2(con->txn_val, rb_intern("abort"), 0, 0); } } } else { if (con->env_val) { Data_Get_Struct(con->env_val, bdb_ENV, envst); bdb_ary_delete(&envst->db_ary, con->ori_val); } if (protect) { try { con->con->close(flags); } catch (...) {} } else { con->closed = Qtrue; PROTECT(con->con->close(flags)); } } } con->closed = true; } static VALUE con_free(VALUE tmp) { xcon *con = (xcon *)tmp; if (!con->closed && con->con) { xb_con_i_close(con, 0, true); if (!NIL_P(con->closed)) { delete con->con; } } return Qnil; } static void xb_con_free(xcon *con) { rb_protect(con_free, (VALUE)con, 0); ::free(con); } static VALUE xb_con_s_alloc(VALUE obj) { xcon *con; VALUE res; res = Data_Make_Struct(obj, xcon, (RDF)xb_con_mark, (RDF)xb_con_free, con); con->ori_val = res; #ifndef BDB_NO_THREAD con->flag |= DB_THREAD; #endif return res; } static VALUE xb_con_s_new(int argc, VALUE *argv, VALUE obj) { DbEnv *envcc = NULL; bdb_ENV *envst = NULL; bdb_TXN *txnst = NULL; int flags = 0, pagesize = 0, nargc; char *name = NULL; xcon *con; VALUE res; VALUE init = Qtrue; res = rb_funcall2(obj, rb_intern("allocate"), 0, 0); Data_Get_Struct(res, xcon, con); nargc = argc; if (argc && TYPE(argv[argc - 1]) == T_HASH) { VALUE env = Qfalse; VALUE v, f = argv[argc - 1]; if ((v = rb_hash_aref(f, rb_str_new2("txn"))) != RHASH(f)->ifnone) { if (!rb_obj_is_kind_of(v, xb_cTxn)) { rb_raise(xb_eFatal, "argument of txn must be a transaction"); } GetTxnDBErr(v, txnst, xb_eFatal); env = txnst->env; con->txn_val = v; } else if ((v = rb_hash_aref(f, rb_str_new2("env"))) != RHASH(f)->ifnone) { if (!rb_obj_is_kind_of(v, xb_cEnv)) { rb_raise(xb_eFatal, "argument of env must be an environnement"); } env = v; GetEnvDBErr(env, envst, id_current_env, xb_eFatal); } if (env) { con->env_val = env; GetEnvDBErr(env, envst, id_current_env, xb_eFatal); if (envst->options & BDB_NO_THREAD) { con->flag &= ~DB_THREAD; } envcc = static_cast(envst->envp->app_private); } if ((v = rb_hash_aref(f, rb_str_new2("flags"))) != RHASH(f)->ifnone) { flags = NUM2INT(v); } if ((v = rb_hash_aref(f, rb_str_new2("set_pagesize"))) != RHASH(f)->ifnone) { pagesize = NUM2INT(v); } if ((v = rb_hash_aref(f, INT2NUM(rb_intern("__ts__no__init__")))) != RHASH(f)->ifnone) { if (RTEST(v)) { init = Qnil; } else { init = Qfalse; } } nargc--; } if (nargc) { SafeStringValue(argv[0]); con->name = rb_str_dup(argv[0]); name = StringValuePtr(argv[0]); } PROTECT(con->con = new XmlContainer(envcc, name, flags)); if (pagesize) { PROTECT(con->con->setPageSize(pagesize)); } if (!NIL_P(init)) { rb_obj_call_init(res, nargc, argv); if (RTEST(init)) { if (txnst) { bdb_ary_push(&txnst->db_ary, res); } else if (envst) { bdb_ary_push(&envst->db_ary, res); } } } return res; } static VALUE xb_con_i_options(VALUE obj, VALUE conobj) { VALUE key, value; char *options; xcon *con; Data_Get_Struct(conobj, xcon, con); key = rb_ary_entry(obj, 0); value = rb_ary_entry(obj, 1); key = rb_obj_as_string(key); options = StringValuePtr(key); if (strcmp(options, "thread") == 0) { switch (value) { case Qtrue: con->flag &= ~DB_THREAD; break; case Qfalse: con->flag |= DB_THREAD; break; default: rb_raise(xb_eFatal, "thread value must be true or false"); } } return Qnil; } static VALUE xb_con_init(int argc, VALUE *argv, VALUE obj) { xcon *con; DbTxn *txn = 0; int flags = 0; int mode = 0; VALUE a, b, c, hash_arg; GetConTxn(obj, con, txn); hash_arg = Qnil; if (argc && TYPE(argv[argc - 1]) == T_HASH) { hash_arg = argv[argc - 1]; argc--; } switch (rb_scan_args(argc, argv, "12", &a, &b, &c)) { case 3: mode = NUM2INT(c); /* ... */ case 2: if (NIL_P(b)) { flags = 0; } else if (TYPE(b) == T_STRING) { if (strcmp(StringValuePtr(b), "r") == 0) flags = DB_RDONLY; else if (strcmp(StringValuePtr(b), "r+") == 0) flags = 0; else if (strcmp(StringValuePtr(b), "w") == 0 || strcmp(StringValuePtr(b), "w+") == 0) flags = DB_CREATE | DB_TRUNCATE; else if (strcmp(StringValuePtr(b), "a") == 0 || strcmp(StringValuePtr(b), "a+") == 0) flags = DB_CREATE; else { rb_raise(xb_eFatal, "flags must be r, r+, w, w+, a or a+"); } } else { flags = NUM2INT(b); } } if (flags & DB_TRUNCATE) { rb_secure(2); } if (flags & DB_CREATE) { rb_secure(4); } if (rb_safe_level() >= 4) { flags |= DB_RDONLY; } if (!txn && con->env_val) { bdb_ENV *envst = NULL; GetEnvDBErr(con->env_val, envst, id_current_env, xb_eFatal); if (envst->options & BDB_AUTO_COMMIT) { flags |= DB_AUTO_COMMIT; con->flag |= BDB_AUTO_COMMIT; } } if (con->flag & DB_THREAD) { flags |= DB_THREAD; } PROTECT2(con->con->open(txn, flags, mode), con->closed = Qnil); return obj; } static VALUE xb_con_close(int argc, VALUE *argv, VALUE obj) { VALUE a; xcon *con; int flags = 0; if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4) { rb_raise(rb_eSecurityError, "Insecure: can't close the container"); } Data_Get_Struct(obj, xcon, con); if (!con->closed && con->con) { if (rb_scan_args(argc, argv, "01", &a)) { flags = NUM2INT(a); } xb_con_i_close(con, flags, false); delete con->con; } return Qnil; } static VALUE xb_env_open_xml(int argc, VALUE *argv, VALUE obj) { int nargc; VALUE *nargv; if (argc && TYPE(argv[argc - 1]) == T_HASH) { nargc = argc; nargv = argv; } else { nargc = argc + 1; nargv = ALLOCA_N(VALUE, nargc); MEMCPY(nargv, argv, VALUE, argc); nargv[argc] = rb_hash_new(); } if (rb_obj_is_kind_of(obj, xb_cEnv)) { rb_hash_aset(nargv[nargc - 1], rb_tainted_str_new2("env"), obj); } else { rb_hash_aset(nargv[nargc - 1], rb_tainted_str_new2("txn"), obj); } return xb_con_s_new(nargc, nargv, xb_cCon); } static VALUE xb_con_env(VALUE obj) { xcon *con; Data_Get_Struct(obj, xcon, con); if (con->closed || !con->con) { rb_raise(xb_eFatal, "closed container"); } if (RTEST(con->env_val)) { return con->env_val; } return Qnil; } static VALUE xb_con_env_p(VALUE obj) { xcon *con; Data_Get_Struct(obj, xcon, con); if (con->closed || !con->con) { rb_raise(xb_eFatal, "closed container"); } return RTEST(con->env_val); } static VALUE xb_con_txn(VALUE obj) { xcon *con; Data_Get_Struct(obj, xcon, con); if (con->closed || !con->con) { rb_raise(xb_eFatal, "closed container"); } if (RTEST(con->txn_val)) { return con->txn_val; } return Qnil; } static VALUE xb_con_txn_p(VALUE obj) { xcon *con; Data_Get_Struct(obj, xcon, con); if (con->closed || !con->con) { rb_raise(xb_eFatal, "closed container"); } return RTEST(con->txn_val); } static void xb_ind_free(XmlIndexSpecification *ind) { delete ind; } static VALUE xb_con_index(VALUE obj) { xcon *con; DbTxn *txn; XmlIndexSpecification ind; GetConTxn(obj, con, txn); PROTECT(ind = con->con->getIndexSpecification(txn)); return Data_Wrap_Struct(xb_cInd, 0, xb_ind_free, new XmlIndexSpecification(ind)); } static VALUE xb_con_index_set(VALUE obj, VALUE a) { xcon *con; DbTxn *txn; XmlIndexSpecification *ind; if (TYPE(a) != T_DATA || RDATA(a)->dfree != xb_ind_free) { a = rb_funcall2(xb_cInd, rb_intern("new"), 1, &a); } GetConTxn(obj, con, txn); Data_Get_Struct(a, XmlIndexSpecification, ind); PROTECT(con->con->setIndexSpecification(txn, *ind)); return a; } static VALUE xb_ind_s_alloc(VALUE obj) { return Data_Wrap_Struct(obj, 0, xb_ind_free, new XmlIndexSpecification()); } static VALUE xb_ind_add(int argc, VALUE *argv, VALUE obj) { XmlIndexSpecification *ind; char *as, *bs, *cs; Data_Get_Struct(obj, XmlIndexSpecification, ind); if (argc == 2) { bs = StringValuePtr(argv[0]); cs = StringValuePtr(argv[1]); PROTECT(ind->addIndex("", bs, cs)); } else { if (argc != 3) { rb_raise(xb_eFatal, "invalid number of arguments (%d for 3)", argc); } as = StringValuePtr(argv[0]); bs = StringValuePtr(argv[1]); cs = StringValuePtr(argv[2]); PROTECT(ind->addIndex(as, bs, cs)); } return obj; } static VALUE xb_ind_init(int argc, VALUE *argv, VALUE obj) { VALUE val, tmp; int i; if (!argc) { return obj; } if (argc != 1) { rb_raise(rb_eArgError, "invalid number of arguments (%d for 1)", argc); } tmp = rb_Array(argv[0]); for (i = 0; i < RARRAY_LEN(tmp); ++i) { val = rb_Array(RARRAY_PTR(tmp)[i]); xb_ind_add(RARRAY_LEN(val), RARRAY_PTR(val), obj); } return obj; } static VALUE xb_ind_replace(int argc, VALUE *argv, VALUE obj) { XmlIndexSpecification *ind; char *as, *bs, *cs; Data_Get_Struct(obj, XmlIndexSpecification, ind); if (argc == 2) { bs = StringValuePtr(argv[0]); cs = StringValuePtr(argv[1]); PROTECT(ind->replaceIndex("", bs, cs)); } else { if (argc != 3) { rb_raise(xb_eFatal, "invalid number of arguments (%d for 3)", argc); } as = StringValuePtr(argv[0]); bs = StringValuePtr(argv[1]); cs = StringValuePtr(argv[2]); PROTECT(ind->replaceIndex(as, bs, cs)); } return obj; } static VALUE xb_ind_delete(int argc, VALUE *argv, VALUE obj) { XmlIndexSpecification *ind; char *as, *bs, *cs; Data_Get_Struct(obj, XmlIndexSpecification, ind); if (argc == 2) { bs = StringValuePtr(argv[0]); cs = StringValuePtr(argv[1]); PROTECT(ind->deleteIndex("", bs, cs)); } else { if (argc != 3) { rb_raise(xb_eFatal, "invalid number of arguments (%d for 3)", argc); } as = StringValuePtr(argv[0]); bs = StringValuePtr(argv[1]); cs = StringValuePtr(argv[2]); PROTECT(ind->deleteIndex(as, bs, cs)); } return obj; } static VALUE xb_ind_each(VALUE obj) { XmlIndexSpecification *ind; std::string uri, name, index; VALUE ret; Data_Get_Struct(obj, XmlIndexSpecification, ind); PROTECT(ind->reset()); while (ind->next(uri, name, index)) { ret = rb_ary_new2(3); rb_ary_push(ret, rb_tainted_str_new2(uri.c_str())); rb_ary_push(ret, rb_tainted_str_new2(name.c_str())); rb_ary_push(ret, rb_tainted_str_new2(index.c_str())); rb_yield(ret); } return Qnil; } static VALUE xb_ind_find(int argc, VALUE *argv, VALUE obj) { XmlIndexSpecification *ind; char *uri, *name; std::string index; Data_Get_Struct(obj, XmlIndexSpecification, ind); if (argc == 1) { name = StringValuePtr(argv[0]); uri = ""; } else { if (argc != 2) { rb_raise(xb_eFatal, "invalid number of arguments (%d for 2)", argc); } uri = StringValuePtr(argv[0]); name = StringValuePtr(argv[1]); } if (ind->find(uri, name, index)) { return rb_tainted_str_new2(index.c_str()); } return Qnil; } static VALUE xb_ind_to_a(VALUE obj) { XmlIndexSpecification *ind; std::string uri, name, index; VALUE ret, res; Data_Get_Struct(obj, XmlIndexSpecification, ind); PROTECT(ind->reset()); res = rb_ary_new(); while (ind->next(uri, name, index)) { ret = rb_ary_new2(3); rb_ary_push(ret, rb_tainted_str_new2(uri.c_str())); rb_ary_push(ret, rb_tainted_str_new2(name.c_str())); rb_ary_push(ret, rb_tainted_str_new2(index.c_str())); rb_ary_push(res, ret); } return res; } static VALUE xb_con_name(VALUE obj) { xcon *con; Data_Get_Struct(obj, xcon, con); return rb_tainted_str_new2(con->con->getName().c_str()); } static VALUE xb_con_name_set(VALUE obj, VALUE a) { xcon *con; std::string str; Data_Get_Struct(obj, xcon, con); str = StringValuePtr(a); PROTECT(con->con->setName(str)); return obj; } static VALUE xb_con_get(int argc, VALUE *argv, VALUE obj) { xcon *con; DbTxn *txn; xdoc *doc; VALUE a, b, res; int flags = 0; if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { flags = NUM2INT(b); } u_int32_t id = NUM2INT(a); GetConTxn(obj, con, txn); res = Data_Make_Struct(xb_cDoc, xdoc, (RDF)xb_doc_mark, (RDF)xb_doc_free, doc); PROTECT(doc->doc = new XmlDocument(con->con->getDocument(txn, id, flags))); return res; } static VALUE xb_int_update(int argc, VALUE *argv, VALUE obj, XmlUpdateContext *upd) { xcon *con; xdoc *doc; DbTxn *txn; VALUE a; rb_secure(4); GetConTxn(obj, con, txn); if (rb_scan_args(argc, argv, "10", &a) != 1) { rb_raise(rb_eArgError, "invalid number of arguments (%d for 1)", argc); } if (TYPE(a) != T_DATA || RDATA(a)->dfree != (RDF)xb_doc_free) { a = xb_s_new(1, &a, xb_cDoc); } Data_Get_Struct(a, xdoc, doc); PROTECT(con->con->updateDocument(txn, *(doc->doc), upd)); return a; } static VALUE xb_con_update(int argc, VALUE *argv, VALUE obj) { return xb_int_update(argc, argv, obj, 0); } static VALUE xb_int_push(int argc, VALUE *argv, VALUE obj, XmlUpdateContext *upd) { xcon *con; DbTxn *txn = NULL; xdoc *doc; u_int32_t id; VALUE a, b; int flags = 0; rb_secure(4); GetConTxn(obj, con, txn); if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { flags = NUM2INT(b); } if (TYPE(a) != T_DATA || RDATA(a)->dfree != (RDF)xb_doc_free) { a = xb_s_new(1, &a, xb_cDoc); } Data_Get_Struct(a, xdoc, doc); PROTECT(id = con->con->putDocument(txn, *(doc->doc), upd, flags)); return INT2NUM(id); } static VALUE xb_con_push(int argc, VALUE *argv, VALUE obj) { return xb_int_push(argc, argv, obj, 0); } static VALUE xb_con_add(VALUE obj, VALUE a) { xb_con_push(1, &a, obj); return obj; } static VALUE xb_con_parse(int argc, VALUE *argv, VALUE obj) { xcon *con; DbTxn *txn; VALUE a, b; std::string str; XmlQueryExpression *pat; xcxt *cxt; XmlQueryContext tmp, *qcxt; GetConTxn(obj, con, txn); if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { if (TYPE(b) != T_DATA || RDATA(b)->dfree != (RDF)xb_cxt_free) { rb_raise(xb_eFatal, "Expected a Context object"); } Data_Get_Struct(b, xcxt, cxt); qcxt = cxt->cxt; } else { tmp = XmlQueryContext(); qcxt = &tmp; } str = StringValuePtr(a); PROTECT(pat = new XmlQueryExpression(con->con->parseXPathExpression(txn, str, qcxt))); return Data_Wrap_Struct(xb_cPat, 0, (RDF)xb_pat_free, pat); } static bool xb_test_txn(VALUE env, DbTxn **txn) { #if BDBXML_VERSION < 10101 bdb_ENV *envst; DbEnv *envcc; if (env) { GetEnvDBErr(env, envst, id_current_env, xb_eFatal); if (envst->options & BDB_AUTO_COMMIT) { envcc = static_cast(envst->envp->app_private); PROTECT(envcc->txn_begin(0, txn, 0)); return true; } } #endif return false; } static VALUE xb_doc_query(int argc, VALUE *argv, VALUE obj) { xdoc *doc; xres *xes; VALUE a, b, res; std::string str; xcxt *cxt; XmlQueryContext *qcxt = 0; Data_Get_Struct(obj, xdoc, doc); if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { if (TYPE(b) != T_DATA || RDATA(b)->dfree != (RDF)xb_cxt_free) { rb_raise(xb_eFatal, "Expected a Context object"); } Data_Get_Struct(b, xcxt, cxt); qcxt = cxt->cxt; } if (NIL_P(b)) { b = Qfalse; } #if BDBXML_VERSION > 10100 if (TYPE(a) == T_DATA && RDATA(a)->dfree == (RDF)xb_pat_free) { XmlQueryExpression *query; if (argc != 1) { rb_raise(rb_eArgError, "invalid number of arguments %d (for 1)", argc); } res = Data_Make_Struct(xb_cRes, xres, (RDF)xb_res_mark, (RDF)xb_res_free, xes); Data_Get_Struct(a, XmlQueryExpression, query); PROTECT(xes->res = new XmlResults(doc->doc->queryWithXPath(*query))); return res; } #endif str = StringValuePtr(a); res = Data_Make_Struct(xb_cRes, xres, (RDF)xb_res_mark, (RDF)xb_res_free, xes); xes->cxt_val = b; PROTECT(xes->res = new XmlResults(doc->doc->queryWithXPath(str, qcxt))); return res; } static VALUE xb_con_query(int argc, VALUE *argv, VALUE obj) { xcon *con; DbTxn *txn = NULL; xres *xes; VALUE a, b, c, res; char *str = 0; int flags = 0; XmlQueryExpression *pat; xcxt *cxt; XmlQueryContext *qcxt = 0; bool temporary = false; GetConTxn(obj, con, txn); switch (rb_scan_args(argc, argv, "12", &a, &b, &c)) { case 3: if (NIL_P(b)) { b = Qfalse; } else { if (TYPE(b) != T_DATA || RDATA(b)->dfree != (RDF)xb_cxt_free) { rb_raise(xb_eFatal, "Expected a Context object"); } Data_Get_Struct(b, xcxt, cxt); qcxt = cxt->cxt; } flags = NUM2INT(c); break; case 2: if (TYPE(b) == T_DATA && RDATA(b)->dfree == (RDF)xb_cxt_free) { Data_Get_Struct(b, xcxt, cxt); qcxt = cxt->cxt; } else { flags = NUM2INT(b); b = Qfalse; } break; case 1: b = Qfalse; break; } res = Data_Make_Struct(xb_cRes, xres, (RDF)xb_res_mark, (RDF)xb_res_free, xes); xes->txn_val = con->txn_val; xes->cxt_val = b; if (!txn) { temporary = xb_test_txn(con->env_val, &txn); } if (TYPE(a) == T_DATA && RDATA(a)->dfree == (RDF)xb_pat_free) { if (argc == 2) { rb_warning("a Context is useless with an XPath"); } Data_Get_Struct(a, XmlQueryExpression, pat); PROTECT(xes->res = new XmlResults(con->con->queryWithXPath(txn, *pat, flags))); } else { str = StringValuePtr(a); PROTECT(xes->res = new XmlResults(con->con->queryWithXPath(txn, str, qcxt, flags))); } if (temporary) { PROTECT(txn->commit(0)); } return res; } static VALUE xb_con_search(int argc, VALUE *argv, VALUE obj) { int nargc; VALUE *nargv; if (argc == 1 || (argc == 2 && FIXNUM_P(argv[1]))) { xcxt *cxt; VALUE res; res = Data_Make_Struct(xb_cCxt, xcxt, 0, (RDF)xb_cxt_free, cxt); cxt->cxt = new XmlQueryContext(); cxt->cxt->setEvaluationType(XmlQueryContext::Lazy); if (argc == 2) { cxt->cxt->setReturnType(XmlQueryContext::ReturnType(NUM2INT(argv[1]))); nargv = argv; } else { nargv = ALLOCA_N(VALUE, 2); nargv[0] = argv[0]; } nargc = 2; nargv[1] = res; } else { nargc = argc; nargv = argv; } return xb_res_search(xb_con_query(nargc, nargv, obj)); } static VALUE xb_con_each(VALUE obj) { VALUE query = rb_str_new2("//*"); if (!rb_block_given_p()) { rb_raise(rb_eArgError, "block not supplied"); } return xb_con_search(1, &query, obj); } static VALUE xb_int_delete(int argc, VALUE *argv, VALUE obj, XmlUpdateContext *upd) { xcon *con; DbTxn *txn = NULL; xdoc *doc; VALUE a, b; int flags = 0; rb_secure(4); GetConTxn(obj, con, txn); if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { flags = NUM2INT(b); } if (TYPE(a) == T_DATA && RDATA(a)->dfree == (RDF)xb_doc_free) { Data_Get_Struct(a, xdoc, doc); PROTECT(con->con->deleteDocument(txn, *(doc->doc), upd, flags)); } else { u_int32_t id = NUM2INT(a); PROTECT(con->con->deleteDocument(txn, id, upd, flags)); } return obj; } static VALUE xb_con_delete(int argc, VALUE *argv, VALUE obj) { return xb_int_delete(argc, argv, obj, 0); } static VALUE xb_con_i_alloc(VALUE obj, VALUE name) { int argc; VALUE klass, argv[2]; argc = 2; argv[0] = name; argv[1] = rb_hash_new(); rb_hash_aset(argv[1], INT2NUM(rb_intern("__ts__no__init__")), Qtrue); klass = obj; if (rb_obj_is_kind_of(obj, xb_cTxn)) { argc = 2; klass = xb_cCon; rb_hash_aset(argv[1], rb_tainted_str_new2("txn"), obj); } return rb_funcall2(klass, rb_intern("new"), argc, argv); } static VALUE xb_con_remove(int argc, VALUE *argv, VALUE obj) { VALUE a, b, c; int flags = 0; xcon *con; DbTxn *txn = NULL; rb_secure(2); if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { flags = NUM2INT(b); } SafeStringValue(a); c = xb_con_i_alloc(obj, a); GetConTxn(c, con, txn); PROTECT(con->con->remove(txn, flags)); return Qnil; } static VALUE xb_con_rename(int argc, VALUE *argv, VALUE obj) { VALUE a, b, c, d; int flags = 0; xcon *con; char *str; DbTxn *txn = NULL; rb_secure(2); if (rb_scan_args(argc, argv, "21", &a, &b, &c) == 3) { flags = NUM2INT(c); } SafeStringValue(a); d = xb_con_i_alloc(obj, a); SafeStringValue(b); str = StringValuePtr(b); GetConTxn(d, con, txn); PROTECT(con->con->rename(txn, str, flags)); return Qnil; } static VALUE xb_con_s_name(VALUE obj, VALUE a, VALUE b) { VALUE c; xcon *con; DbTxn *txn; std::string str; SafeStringValue(a); c = xb_con_i_alloc(obj, a); GetConTxn(c, con, txn); str = StringValuePtr(b); PROTECT(con->con->setName(str)); return Qnil; } static VALUE xb_con_dump(int argc, VALUE *argv, VALUE obj) { xcon *con; VALUE a, b, c; u_int32_t flags = 0; DbTxn *txn = NULL; if (rb_scan_args(argc, argv, "21", &a, &b, &c) == 3) { flags = NUM2INT(c); } c = xb_con_i_alloc(obj, a); GetConTxn(c, con, txn); Check_Type(b, T_STRING); char *name = StringValuePtr(b); std::ofstream out(name); PROTECT2(con->con->dump(&out, flags), out.close()); out.close(); return Qnil; } static VALUE xb_con_load(int argc, VALUE *argv, VALUE obj) { xcon *con; VALUE a, b, c, d; u_int32_t flags = 0; unsigned long lineno = 0; DbTxn *txn = NULL; switch (rb_scan_args(argc, argv, "22", &a, &b, &c, &d)) { case 4: flags = NUM2INT(d); /* ... */ case 3: lineno = NUM2INT(c); } c = xb_con_i_alloc(obj, a); GetConTxn(c, con, txn); Check_Type(b, T_STRING); char *name = StringValuePtr(b); std::ifstream in(name); PROTECT2(con->con->load(&in, &lineno, flags), in.close()); in.close(); return Qnil; } static VALUE xb_con_verify(VALUE obj, VALUE a) { xcon *con; std::ofstream out; DbTxn *txn = NULL; a = xb_con_i_alloc(obj, a); GetConTxn(a, con, txn); PROTECT(con->con->verify(&out, 0)); return Qnil; } static VALUE xb_con_verify_salvage(int argc, VALUE *argv, VALUE obj) { xcon *con; VALUE a, b, c; u_int32_t flags = 0; DbTxn *txn = NULL; if (rb_scan_args(argc, argv, "21", &a, &b, &c) == 2) { flags = NUM2INT(c); } c = xb_con_i_alloc(obj, a); GetConTxn(c, con, txn); flags |= DB_SALVAGE; Check_Type(b, T_STRING); char *name = StringValuePtr(b); std::ofstream out(name); PROTECT2(con->con->verify(&out, flags), out.close()); out.close(); return Qnil; } static VALUE xb_con_is_open(VALUE obj) { xcon *con; Data_Get_Struct(obj, xcon, con); if (con->closed || !con->con || !con->con->isOpen()) { return Qfalse; } return Qtrue; } static void xb_upd_free(xupd *upd) { delete upd->upd; ::free(upd); } static void xb_upd_mark(xupd *upd) { rb_gc_mark(upd->con); } static VALUE xb_con_context(VALUE obj) { xcon *con; DbTxn *txn; xupd *upd; VALUE res; GetConTxn(obj, con, txn); res = Data_Make_Struct(xb_cUpd, xupd, xb_upd_mark, xb_upd_free, upd); upd->con = obj; upd->upd = new XmlUpdateContext(*con->con); if (rb_block_given_p()) { return rb_yield(res); } return res; } static VALUE xb_upd_push(int argc, VALUE *argv, VALUE obj) { xupd *upd; Data_Get_Struct(obj, xupd, upd); return xb_int_push(argc, argv, upd->con, upd->upd); } static VALUE xb_upd_add(VALUE obj, VALUE a) { xb_upd_push(1, &a, obj); return obj; } static VALUE xb_upd_delete(int argc, VALUE *argv, VALUE obj) { xupd *upd; Data_Get_Struct(obj, xupd, upd); return xb_int_delete(argc, argv, upd->con, upd->upd); } static VALUE xb_upd_update(int argc, VALUE *argv, VALUE obj) { xupd *upd; Data_Get_Struct(obj, xupd, upd); return xb_int_update(argc, argv, upd->con, upd->upd); } static VALUE xb_int_set(VALUE obj, VALUE a, VALUE b, XmlUpdateContext *upd) { VALUE c = xb_con_get(1, &a, obj); return xb_int_update(1, &c, obj, upd); } static VALUE xb_con_set(VALUE obj, VALUE a, VALUE b) { return xb_int_set(obj, a, b, 0); } static VALUE xb_upd_set(VALUE obj, VALUE a, VALUE b) { xupd *upd; Data_Get_Struct(obj, xupd, upd); return xb_int_set(upd->con, a, b, upd->upd); } static VALUE xb_i_txn(VALUE obj, int *flags) { VALUE key, value; char *options; key = rb_ary_entry(obj, 0); value = rb_ary_entry(obj, 1); key = rb_obj_as_string(key); options = StringValuePtr(key); if (strcmp(options, "flags") == 0) { *flags = NUM2INT(value); } return Qnil; } static VALUE xb_env_s_new(int argc, VALUE *argv, VALUE obj) { DbEnv *env = new DbEnv(0); DB_ENV *envd = env->get_DB_ENV(); envd->app_private = static_cast(env); return bdb_env_s_rslbl(argc, argv, obj, envd); } static VALUE xb_env_begin(int argc, VALUE *argv, VALUE obj) { DbTxn *p = NULL; struct txn_rslbl txnr; DbTxn *q = NULL; VALUE env; bdb_ENV *envst; DbEnv *env_cxx; int flags = 0; if (argc) { if (TYPE(argv[argc - 1]) == T_HASH) { rb_iterate(RMFS(rb_each), argv[argc - 1], RMF(xb_i_txn), (VALUE)&flags); } if (FIXNUM_P(argv[0])) { flags = NUM2INT(argv[0]); } flags &= ~BDB_TXN_COMMIT; } if (rb_obj_is_kind_of(obj, xb_cTxn)) { bdb_TXN *txnst; GetTxnDBErr(obj, txnst, xb_eFatal); p = static_cast(txnst->txn_cxx); env = txnst->env; } else { env = obj; } GetEnvDBErr(env, envst, id_current_env, xb_eFatal); env_cxx = static_cast(envst->envp->app_private); PROTECT(env_cxx->txn_begin(p, &q, flags)); txnr.txn_cxx = static_cast(q); txnr.txn = q->get_DB_TXN(); return bdb_env_rslbl_begin((VALUE)&txnr, argc, argv, obj); } #if BDBXML_VERSION >= 10102 static void xb_mod_free(XmlModify *mod) { if (mod) { delete mod; } } static VALUE xb_mod_s_alloc(VALUE obj) { return Data_Wrap_Struct(obj, 0, xb_mod_free, 0); } static VALUE xb_mod_init(int argc, VALUE *argv, VALUE obj) { XmlQueryExpression *expression = 0; std::string xpath; XmlModify::ModificationType operation; XmlModify::XmlObject type = XmlModify::None; std::string name = "", content = ""; int32_t location = -1; XmlQueryContext *context = 0; XmlModify *modify; xcxt *cxt; VALUE a, b, c, d, e, f, g; switch(rb_scan_args(argc, argv, "25", &a, &b, &c, &d, &e, &f, &g)) { case 7: if (TYPE(g) != T_DATA || RDATA(g)->dfree != (RDF)xb_cxt_free) { rb_raise(xb_eFatal, "Expected a Context object"); } Data_Get_Struct(g, xcxt, cxt); context = cxt->cxt; /* ... */ case 6: location = NUM2INT(f); /* ... */ case 5: if (!NIL_P(e)) { content = StringValuePtr(e); } /* ... */ case 4: if (!NIL_P(d)) { name = StringValuePtr(d); } /* ... */ case 3: if (!NIL_P(c)) { type = XmlModify::XmlObject(NUM2INT(c)); } } operation = XmlModify::ModificationType(NUM2INT(b)); if (TYPE(a) == T_DATA && (RDF)RDATA(a)->dfree == xb_pat_free) { Data_Get_Struct(a, XmlQueryExpression, expression); } else { xpath = StringValuePtr(a); } if (expression) { PROTECT(modify = new XmlModify(*expression, operation, type, name, content, location)); } else { PROTECT(modify = new XmlModify(xpath, operation, type, name, content, location, context)); } DATA_PTR(obj) = modify; return obj; } static VALUE xb_mod_count(VALUE obj) { XmlModify *modify; int result = 0; Data_Get_Struct(obj, XmlModify, modify); if (modify) { PROTECT(result = modify->getNumModifications()); } return INT2NUM(result); } static VALUE xb_mod_encoding(VALUE obj, VALUE a) { XmlModify *modify; Data_Get_Struct(obj, XmlModify, modify); if (modify) { PROTECT(modify->setNewEncoding(StringValuePtr(a))); } return a; } static VALUE xb_con_modify(int argc, VALUE *argv, VALUE obj) { xcon *con; DbTxn *txn; VALUE a, b, c; const XmlModify *modify; XmlUpdateContext *context = 0; u_int32_t flags = 0; GetConTxn(obj, con, txn); switch(rb_scan_args(argc, argv, "12", &a, &b, &c)) { case 3: flags = NUM2INT(c); /* ... */ case 2: if (!NIL_P(b)) { xupd *upd; if (TYPE(b) != T_DATA || RDATA(b)->dfree != (RDF)xb_upd_free) { rb_raise(rb_eArgError, "Expected an update context"); } Data_Get_Struct(b, xupd, upd); context = upd->upd; } } if (TYPE(a) != T_DATA || RDATA(a)->dfree != (RDF)xb_mod_free) { rb_raise(xb_eFatal, "Expected a Modify object"); } Data_Get_Struct(a, XmlModify, modify); if (modify) { PROTECT(con->con->modifyDocument(txn, *modify, context, flags)); } return obj; } static VALUE xb_doc_modify(VALUE obj, VALUE a) { xdoc *doc; XmlModify *modify; Data_Get_Struct(obj, xdoc, doc); if (TYPE(a) != T_DATA || RDATA(a)->dfree != (RDF)xb_mod_free) { rb_raise(xb_eFatal, "Expected a Modify object"); } Data_Get_Struct(a, XmlModify, modify); if (modify) { PROTECT(doc->doc->modifyDocument(*modify)); } return obj; } #endif extern "C" { static VALUE xb_con_txn_dup(VALUE obj, VALUE a) { xcon *con; VALUE res; bdb_TXN *txnst; VALUE argv[2]; GetTxnDBErr(a, txnst, xb_eFatal); Data_Get_Struct(obj, xcon, con); argv[0] = con->name; argv[1] = rb_hash_new(); rb_hash_aset(argv[1], INT2NUM(rb_intern("__ts__no__init__")), Qfalse); res = xb_env_open_xml(2, argv, a); return res; } static VALUE xb_con_txn_close(VALUE obj, VALUE commit, VALUE real) { if (!real) { xcon *con; Data_Get_Struct(obj, xcon, con); con->closed = Qtrue; } else { xb_con_close(0, 0, obj); } return Qnil; } static void xb_const_set(VALUE hash, const char *cvalue, char *ckey) { VALUE key, value; key = rb_str_new2(ckey); rb_obj_freeze(key); value = rb_str_new2(cvalue); rb_obj_freeze(value); rb_hash_aset(hash, key, value); } void Init_bdbxml() { int major, minor, patch; VALUE version; #ifdef BDB_LINK_OBJ extern void Init_bdb(); #endif static VALUE xb_mDb, xb_mXML; #if defined(DBXML_DOM_XERCES2) static VALUE xb_mDom; #endif if (rb_const_defined_at(rb_cObject, rb_intern("BDB"))) { rb_raise(rb_eNameError, "module already defined"); } #ifdef BDB_LINK_OBJ Init_bdb(); #else rb_require("bdb"); #endif id_current_env = rb_intern("bdb_current_env"); xb_mDb = rb_const_get(rb_cObject, rb_intern("BDB")); major = NUM2INT(rb_const_get(xb_mDb, rb_intern("VERSION_MAJOR"))); minor = NUM2INT(rb_const_get(xb_mDb, rb_intern("VERSION_MINOR"))); patch = NUM2INT(rb_const_get(xb_mDb, rb_intern("VERSION_PATCH"))); if (major != DB_VERSION_MAJOR || minor != DB_VERSION_MINOR || patch != DB_VERSION_PATCH) { rb_raise(rb_eNotImpError, "\nBDB::XML needs compatible versions of BDB\n\tyou have BDB::XML version %d.%d.%d and BDB version %d.%d.%d\n", DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH, major, minor, patch); } version = rb_tainted_str_new2(dbxml_version(&major, &minor, &patch)); if (major != DBXML_VERSION_MAJOR || minor != DBXML_VERSION_MINOR || patch != DBXML_VERSION_PATCH) { rb_raise(rb_eNotImpError, "\nBDB::XML needs compatible versions of DbXml\n\tyou have DbXml.hpp version %d.%d.%d and libdbxml version %d.%d.%d\n", DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH, major, minor, patch); } xb_eFatal = rb_const_get(xb_mDb, rb_intern("Fatal")); xb_cEnv = rb_const_get(xb_mDb, rb_intern("Env")); rb_define_singleton_method(xb_cEnv, "new", RMF(xb_env_s_new), -1); rb_define_singleton_method(xb_cEnv, "create", RMF(xb_env_s_new), -1); rb_define_method(xb_cEnv, "open_xml", RMF(xb_env_open_xml), -1); rb_define_method(xb_cEnv, "begin", RMF(xb_env_begin), -1); rb_define_method(xb_cEnv, "txn_begin", RMF(xb_env_begin), -1); rb_define_method(xb_cEnv, "transaction", RMF(xb_env_begin), -1); DbXml::setLogLevel(DbXml::LEVEL_ALL, false); xb_cTxn = rb_const_get(xb_mDb, rb_intern("Txn")); rb_define_method(xb_cTxn, "open_xml", RMF(xb_env_open_xml), -1); rb_define_method(xb_cTxn, "begin", RMF(xb_env_begin), -1); rb_define_method(xb_cTxn, "txn_begin", RMF(xb_env_begin), -1); rb_define_method(xb_cTxn, "transaction", RMF(xb_env_begin), -1); rb_define_method(xb_cTxn, "rename_xml", RMF(xb_con_rename), -1); rb_define_method(xb_cTxn, "remove_xml", RMF(xb_con_remove), -1); xb_mXML = rb_define_module_under(xb_mDb, "XML"); rb_define_const(xb_mXML, "VERSION", version); rb_define_const(xb_mXML, "VERSION_MAJOR", INT2FIX(major)); rb_define_const(xb_mXML, "VERSION_MINOR", INT2FIX(minor)); rb_define_const(xb_mXML, "VERSION_PATCH", INT2FIX(patch)); #ifdef DBXML_CHKSUM_SHA1 rb_define_const(xb_mXML, "CHKSUM_SHA1", INT2NUM(DBXML_CHKSUM_SHA1)); #endif #ifdef DBXML_ENCRYPT rb_define_const(xb_mXML, "ENCRYPT", INT2NUM(DBXML_ENCRYPT)); #endif { VALUE name = rb_hash_new(); rb_define_const(xb_mXML, "Name", name); xb_const_set(name, metaDataName_name, "name"); xb_const_set(name, metaDataName_default, "default"); xb_const_set(name, metaDataName_content, "content"); xb_const_set(name, metaDataName_id, "id"); xb_const_set(name, metaDataName_uri_id, "uri_id"); xb_const_set(name, metaDataName_uri_default, "uri_default"); rb_obj_freeze(name); name = rb_hash_new(); rb_define_const(xb_mXML, "Namespace", name); xb_const_set(name, metaDataNamespace_uri, "uri"); xb_const_set(name, metaDataNamespace_prefix, "prefix"); xb_const_set(name, metaDataNamespace_prefix_debug, "prefix_debug"); rb_obj_freeze(name); } xb_cCon = rb_define_class_under(xb_mXML, "Container", rb_cObject); rb_include_module(xb_cCon, rb_mEnumerable); #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_define_alloc_func(xb_cCon, RMFS(xb_con_s_alloc)); #else rb_define_singleton_method(xb_cCon, "allocate", RMFS(xb_con_s_alloc), 0); #endif rb_define_singleton_method(xb_cCon, "new", RMF(xb_con_s_new), -1); rb_define_singleton_method(xb_cCon, "open", RMF(xb_con_s_new), -1); rb_define_singleton_method(xb_cCon, "set_name", RMF(xb_con_s_name), 2); rb_define_singleton_method(xb_cCon, "rename", RMF(xb_con_rename), -1); rb_define_singleton_method(xb_cCon, "remove", RMF(xb_con_remove), -1); rb_define_singleton_method(xb_cCon, "dump", RMF(xb_con_dump), -1); rb_define_singleton_method(xb_cCon, "load", RMF(xb_con_load), -1); rb_define_singleton_method(xb_cCon, "verify", RMF(xb_con_verify), 1); rb_define_singleton_method(xb_cCon, "salvage", RMF(xb_con_verify_salvage), -1); rb_define_singleton_method(xb_cCon, "verify_and_salvage", RMF(xb_con_verify_salvage), -1); rb_define_private_method(xb_cCon, "initialize", RMF(xb_con_init), -1); rb_define_private_method(xb_cCon, "__txn_dup__", RMF(xb_con_txn_dup), 1); rb_define_private_method(xb_cCon, "__txn_close__", RMF(xb_con_txn_close), 2); rb_define_method(xb_cCon, "environment", RMF(xb_con_env), 0); rb_define_method(xb_cCon, "env", RMF(xb_con_env), 0); rb_define_method(xb_cCon, "environment?", RMF(xb_con_env_p), 0); rb_define_method(xb_cCon, "env?", RMF(xb_con_env_p), 0); rb_define_method(xb_cCon, "has_environment?", RMF(xb_con_env_p), 0); rb_define_method(xb_cCon, "has_env?", RMF(xb_con_env_p), 0); rb_define_method(xb_cCon, "transaction", RMF(xb_con_txn), 0); rb_define_method(xb_cCon, "txn", RMF(xb_con_txn), 0); rb_define_method(xb_cCon, "transaction?", RMF(xb_con_txn_p), 0); rb_define_method(xb_cCon, "txn?", RMF(xb_con_txn_p), 0); rb_define_method(xb_cCon, "in_transaction?", RMF(xb_con_txn_p), 0); rb_define_method(xb_cCon, "in_txn?", RMF(xb_con_txn_p), 0); rb_define_method(xb_cCon, "index", RMF(xb_con_index), 0); rb_define_method(xb_cCon, "index=", RMF(xb_con_index_set), 1); rb_define_method(xb_cCon, "name", RMF(xb_con_name), 0); rb_define_method(xb_cCon, "name=", RMF(xb_con_name_set), 1); rb_define_method(xb_cCon, "[]", RMF(xb_con_get), -1); rb_define_method(xb_cCon, "get", RMF(xb_con_get), -1); rb_define_method(xb_cCon, "push", RMF(xb_con_push), -1); rb_define_method(xb_cCon, "<<", RMF(xb_con_add), 1); rb_define_method(xb_cCon, "update", RMF(xb_con_update), -1); rb_define_method(xb_cCon, "[]=", RMF(xb_con_set), 2); rb_define_method(xb_cCon, "parse", RMF(xb_con_parse), -1); rb_define_method(xb_cCon, "query", RMF(xb_con_query), -1); rb_define_method(xb_cCon, "delete", RMF(xb_con_delete), -1); rb_define_method(xb_cCon, "close", RMF(xb_con_close), -1); rb_define_method(xb_cCon, "search", RMF(xb_con_search), -1); rb_define_method(xb_cCon, "each", RMF(xb_con_each), 0); rb_define_method(xb_cCon, "open?", RMF(xb_con_is_open), 0); rb_define_method(xb_cCon, "is_open?", RMF(xb_con_is_open), 0); rb_define_method(xb_cCon, "context", RMF(xb_con_context), 0); rb_define_method(xb_cCon, "update_context", RMF(xb_con_context), 0); #if BDBXML_VERSION >= 10102 rb_define_method(xb_cCon, "modify", RMF(xb_con_modify), -1); #endif xb_cInd = rb_define_class_under(xb_mXML, "Index", rb_cObject); #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_define_alloc_func(xb_cInd, RMFS(xb_ind_s_alloc)); #else rb_define_singleton_method(xb_cInd, "allocate", RMFS(xb_ind_s_alloc), 0); #endif rb_define_singleton_method(xb_cInd, "new", RMF(xb_s_new), -1); rb_define_private_method(xb_cInd, "initialize", RMF(xb_ind_init), -1); rb_define_method(xb_cInd, "add", RMF(xb_ind_add), -1); rb_define_method(xb_cInd, "delete", RMF(xb_ind_delete), -1); rb_define_method(xb_cInd, "replace", RMF(xb_ind_replace), -1); rb_define_method(xb_cInd, "each", RMF(xb_ind_each), 0); rb_define_method(xb_cInd, "find", RMF(xb_ind_find), -1); rb_define_method(xb_cInd, "to_a", RMF(xb_ind_to_a), 0); xb_cUpd = rb_define_class_under(xb_mXML, "UpdateContext", rb_cObject); rb_undef_method(CLASS_OF(xb_cUpd), "allocate"); rb_undef_method(CLASS_OF(xb_cUpd), "new"); rb_define_method(xb_cUpd, "[]", RMF(xb_con_get), -1); rb_define_method(xb_cUpd, "get", RMF(xb_con_get), -1); rb_define_method(xb_cUpd, "[]=", RMF(xb_upd_set), 2); rb_define_method(xb_cUpd, "push", RMF(xb_upd_push), -1); rb_define_method(xb_cUpd, "<<", RMF(xb_upd_add), 1); rb_define_method(xb_cUpd, "delete", RMF(xb_upd_delete), -1); rb_define_method(xb_cUpd, "update", RMF(xb_upd_update), -1); xb_cTmp = rb_define_class_under(xb_mXML, "Tmp", rb_cData); rb_undef_method(CLASS_OF(xb_cTmp), "allocate"); rb_undef_method(CLASS_OF(xb_cTmp), "new"); rb_define_method(xb_cTmp, "[]", RMF(xb_cxt_name_get), 1); rb_define_method(xb_cTmp, "[]=", RMF(xb_cxt_name_set), 2); xb_cDoc = rb_define_class_under(xb_mXML, "Document", rb_cObject); #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_define_alloc_func(xb_cDoc, RMFS(xb_doc_s_alloc)); #else rb_define_singleton_method(xb_cDoc, "allocate", RMFS(xb_doc_s_alloc), 0); #endif rb_define_singleton_method(xb_cDoc, "new", RMF(xb_s_new), -1); rb_define_private_method(xb_cDoc, "initialize", RMF(xb_doc_init), -1); rb_define_method(xb_cDoc, "name", RMF(xb_doc_name_get), 0); rb_define_method(xb_cDoc, "name=", RMF(xb_doc_name_set), 1); rb_define_method(xb_cDoc, "content", RMF(xb_doc_content_get), 0); rb_define_method(xb_cDoc, "content=", RMF(xb_doc_content_set), 1); rb_define_method(xb_cDoc, "[]", RMF(xb_doc_get), -1); rb_define_method(xb_cDoc, "[]=", RMF(xb_doc_set), -1); rb_define_method(xb_cDoc, "get", RMF(xb_doc_get), -1); rb_define_method(xb_cDoc, "set", RMF(xb_doc_set), -1); rb_define_method(xb_cDoc, "get_metadata", RMF(xb_doc_get), -1); rb_define_method(xb_cDoc, "set_metadata", RMF(xb_doc_set), -1); rb_define_method(xb_cDoc, "id", RMF(xb_doc_id_get), 0); rb_define_method(xb_cDoc, "to_s", RMF(xb_doc_content_get), 0); rb_define_method(xb_cDoc, "to_str", RMF(xb_doc_content_get), 0); rb_define_method(xb_cDoc, "uri", RMF(xb_doc_uri_get), 0); rb_define_method(xb_cDoc, "uri=", RMF(xb_doc_uri_set), 1); rb_define_method(xb_cDoc, "prefix", RMF(xb_doc_prefix_get), 0); rb_define_method(xb_cDoc, "prefix=", RMF(xb_doc_prefix_set), 1); rb_define_method(xb_cDoc, "query", RMF(xb_doc_query), -1); #if BDBXML_VERSION >= 10102 rb_define_method(xb_cDoc, "modify", RMF(xb_doc_modify), 1); #endif xb_cCxt = rb_define_class_under(xb_mXML, "Context", rb_cObject); rb_const_set(xb_mXML, rb_intern("QueryContext"), xb_cCxt); rb_define_const(xb_cCxt, "Documents", INT2FIX(XmlQueryContext::ResultDocuments)); rb_define_const(xb_cCxt, "Values", INT2FIX(XmlQueryContext::ResultValues)); rb_define_const(xb_cCxt, "Candidates", INT2FIX(XmlQueryContext::CandidateDocuments)); rb_define_const(xb_cCxt, "DocumentsAndValues", INT2FIX(XmlQueryContext::ResultDocumentsAndValues)); rb_define_const(xb_cCxt, "Eager", INT2FIX(XmlQueryContext::Eager)); rb_define_const(xb_cCxt, "Lazy", INT2FIX(XmlQueryContext::Lazy)); #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_define_alloc_func(xb_cCxt, RMFS(xb_cxt_s_alloc)); #else rb_define_singleton_method(xb_cCxt, "allocate", RMFS(xb_cxt_s_alloc), 0); #endif rb_define_singleton_method(xb_cCxt, "new", RMF(xb_s_new), -1); rb_define_private_method(xb_cCxt, "initialize", RMF(xb_cxt_init), -1); rb_define_method(xb_cCxt, "set_namespace", RMF(xb_cxt_name_set), 2); rb_define_method(xb_cCxt, "get_namespace", RMF(xb_cxt_name_get), 1); rb_define_method(xb_cCxt, "namespace", RMF(xb_cxt_name), 0); rb_define_method(xb_cCxt, "del_namespace", RMF(xb_cxt_name_del), 1); rb_define_method(xb_cCxt, "clear", RMF(xb_cxt_clear), 0); rb_define_method(xb_cCxt, "clear_namespaces", RMF(xb_cxt_clear), 0); rb_define_method(xb_cCxt, "[]", RMF(xb_cxt_get), 1); rb_define_method(xb_cCxt, "[]=", RMF(xb_cxt_set), 2); rb_define_method(xb_cCxt, "returntype", RMF(xb_cxt_return_get), 0); rb_define_method(xb_cCxt, "returntype=", RMF(xb_cxt_return_set), 1); rb_define_method(xb_cCxt, "evaltype", RMF(xb_cxt_eval_get), 0); rb_define_method(xb_cCxt, "evaltype=", RMF(xb_cxt_eval_set), 1); #if BDBXML_VERSION >= 10200 rb_define_method(xb_cCxt, "metadata", RMF(xb_cxt_meta_get), 0); rb_define_method(xb_cCxt, "metadata=", RMF(xb_cxt_meta_set), 1); rb_define_method(xb_cCxt, "with_metadata", RMF(xb_cxt_meta_get), 0); rb_define_method(xb_cCxt, "with_metadata=", RMF(xb_cxt_meta_set), 1); #endif xb_cPat = rb_define_class_under(xb_mXML, "XPath", rb_cObject); rb_undef_method(CLASS_OF(xb_cPat), "allocate"); rb_undef_method(CLASS_OF(xb_cPat), "new"); rb_define_method(xb_cPat, "to_s", RMF(xb_pat_to_str), 0); rb_define_method(xb_cPat, "to_str", RMF(xb_pat_to_str), 0); xb_cRes = rb_define_class_under(xb_mXML, "Results", rb_cObject); rb_include_module(xb_cRes, rb_mEnumerable); rb_undef_method(CLASS_OF(xb_cRes), "allocate"); rb_undef_method(CLASS_OF(xb_cRes), "new"); rb_define_method(xb_cRes, "each", RMF(xb_res_each), 0); rb_define_method(xb_cRes, "size", RMF(xb_res_size), 0); rb_define_method(xb_cRes, "to_a", RMF(xb_res_search), 0); #if defined(DBXML_DOM_XERCES2) xb_mDom = rb_define_class_under(xb_mDb, "DOM", rb_cObject); xb_cNod = rb_define_class_under(xb_mDom, "Node", rb_cObject); #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_undef_method(CLASS_OF(xb_cNod), "allocate"); #endif rb_undef_method(CLASS_OF(xb_cNod), "new"); rb_define_method(xb_cNod, "to_s", RMF(xb_nod_to_s), 0); rb_define_method(xb_cNod, "to_str", RMF(xb_nod_to_s), 0); rb_define_method(xb_cNod, "inspect", RMF(xb_nod_inspect), 0); #if BDBXML_VERSION < 10101 xb_cNol = rb_define_class_under(xb_mDom, "NodeList", rb_cObject); rb_const_set(xb_mDom, rb_intern("List"), xb_cNol); rb_include_module(xb_cNol, rb_mEnumerable); #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_undef_method(CLASS_OF(xb_cNol), "allocate"); #endif rb_undef_method(CLASS_OF(xb_cNol), "new"); rb_define_method(xb_cNol, "size", RMF(xb_nol_size), 0); rb_define_method(xb_cNol, "length", RMF(xb_nol_size), 0); rb_define_method(xb_cNol, "[]", RMF(xb_nol_get), 1); rb_define_method(xb_cNol, "each", RMF(xb_nol_each), 0); rb_define_method(xb_cNol, "to_s", RMF(xb_nol_to_str), 0); rb_define_method(xb_cNol, "to_str", RMF(xb_nol_to_str), 0); rb_define_method(xb_cNol, "inspect", RMF(xb_nol_inspect), 0); rb_define_method(xb_cNol, "to_a", RMF(xb_nol_to_ary), 0); rb_define_method(xb_cNol, "to_ary", RMF(xb_nol_to_ary), 0); #endif #endif #if BDBXML_VERSION >= 10102 xb_cMod = rb_define_class_under(xb_mXML, "Modify", rb_cObject); rb_define_const(xb_cMod, "InsertAfter", INT2NUM(XmlModify::InsertAfter)); rb_define_const(xb_cMod, "InsertBefore", INT2NUM(XmlModify::InsertBefore)); rb_define_const(xb_cMod, "Append", INT2NUM(XmlModify::Append)); rb_define_const(xb_cMod, "Update", INT2NUM(XmlModify::Update)); rb_define_const(xb_cMod, "Remove", INT2NUM(XmlModify::Remove)); rb_define_const(xb_cMod, "Rename", INT2NUM(XmlModify::Rename)); rb_define_const(xb_cMod, "Element", INT2NUM(XmlModify::Element)); rb_define_const(xb_cMod, "Attribute", INT2NUM(XmlModify::Attribute)); rb_define_const(xb_cMod, "Text", INT2NUM(XmlModify::Text)); rb_define_const(xb_cMod, "ProcessingInstruction", INT2NUM(XmlModify::ProcessingInstruction)); rb_define_const(xb_cMod, "PI", INT2NUM(XmlModify::ProcessingInstruction)); rb_define_const(xb_cMod, "Comment", INT2NUM(XmlModify::Comment)); rb_define_const(xb_cMod, "None", INT2NUM(XmlModify::None)); #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_define_alloc_func(xb_cMod, RMFS(xb_mod_s_alloc)); #else rb_define_singleton_method(xb_cMod, "allocate", RMFS(xb_mod_s_alloc), 0); #endif rb_define_singleton_method(xb_cMod, "new", RMF(xb_s_new), -1); rb_define_private_method(xb_cMod, "initialize", RMF(xb_mod_init), -1); rb_define_method(xb_cMod, "encoding=", RMF(xb_mod_encoding), 1); rb_define_method(xb_cMod, "count", RMF(xb_mod_count), 0); #endif } } ruby-bdb-0.6.6/bdbxml1/bdbxml.h000066400000000000000000000041231154714021300162010ustar00rootroot00000000000000#include "bdb.h" #include #include using namespace DbXml; #define RMF(func) RUBY_METHOD_FUNC(func) #define RDF RUBY_DATA_FUNC #if RUBY_VERSION_CODE >= 180 #define RMFS(func) ((VALUE (*)(VALUE))func) #define RMFF(func) ((void (*)(VALUE))func) #else #define RMFS(func) RMF(func) #define RMFF(func) ((void (*)())func) #endif #define BDBXML_VERSION (10000*DBXML_VERSION_MAJOR+100*DBXML_VERSION_MINOR+DBXML_VERSION_PATCH) #define PROTECT2(comm_, libr_) \ try { \ comm_; \ } \ catch (XmlException &e) { \ VALUE xb_err = Qnil; \ libr_; \ if ((xb_err = bdb_return_err()) != Qnil) { \ rb_raise(xb_eFatal, StringValuePtr(xb_err)); \ } \ rb_raise(xb_eFatal, e.what()); \ } \ catch (std::exception &e) { \ libr_; \ rb_raise(xb_eFatal, e.what()); \ } \ catch (...) { \ libr_; \ rb_raise(xb_eFatal, "Unknown error"); \ } #define PROTECT(comm_) PROTECT2(comm_,) #define GetConTxn(obj_, con_, txn_) \ { \ Data_Get_Struct(obj_, xcon, con_); \ if (con_->closed || !con_->con) { \ rb_raise(xb_eFatal, "closed container"); \ } \ txn_ = 0; \ if (con_->txn_val) { \ bdb_TXN *txnst; \ Data_Get_Struct(con_->txn_val, bdb_TXN, txnst); \ txn_ = (DbTxn *)txnst->txn_cxx; \ } \ } typedef struct { XmlContainer *con; VALUE env_val; VALUE txn_val; VALUE ori_val; VALUE name; int closed, flag; } xcon; typedef struct { XmlResults *res; VALUE txn_val; VALUE cxt_val; } xres; #if defined(DBXML_DOM_XERCES2) extern "C" void Init_bdbxml_dom(); typedef struct { #if BDBXML_VERSION < 10101 XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList *nol; #else XERCES_CPP_NAMESPACE_QUALIFIER DOMNode *nol; #endif VALUE cxt_val; } xnol; #endif typedef struct { XmlDocument *doc; VALUE uri, prefix; } xdoc; typedef struct { XmlQueryContext *cxt; } xcxt; typedef struct { VALUE con; XmlUpdateContext *upd; } xupd; ruby-bdb-0.6.6/bdbxml1/bdbxml.rd000066400000000000000000000055111154714021300163610ustar00rootroot00000000000000=begin = BDB::XML # module BDB #^ Berkeley DB XML is an embedded native XML datastore that provides for the efficient storage and retrieval of XML encoded information. Retrieval is supported by an XPath query engine that derives its efficiency from indices generated from the stored XML data. #^ # module XML # (()) #^ The container name provides the base for the filenames of the database files used to store the container content. The directory within which the files are opened is taken from the environment passed through the Container constructor. If no environment was provided, then the directory used will be the current working directory. #^ # class Container # end (()) #^ Define the indexing strategy for a Container Indexing is specified by providing the name of a node and a list of indexing strategies for that node. #^ # class Index # end (()) #^ A Document is the unit of storage within a Container. A Document contains a stream of bytes that may be of type XML. The Container only indexes the content of Documents that contain XML. Document supports annotation attributes. #^ # class Document # end (()) #^ The context within which a query is performed against a Container. The context within which a query is performed against a Container is complex enough to warrent an encapsulating class. This context includes a namespace mapping, variable bindings, and flags that determine how the query result set should be determined and returned to the caller. The XPath syntax permits expressions to refer to namespace prefixes, but not to define them. The Context class provides a number of namespace management methods so that the caller may manage the namespace prefix to URI mapping. The XPath syntax also permits expressions to refer to variables, but not to define them. The Context class provides a number of methods so that the caller may manage the variable to value bindings. #^ # class Context # end (()) #^ Modify encapsulates the context within which a set of documents specified by a query can be modified in place. The modification is performed using the methods ((|BDB::XML::Container#modify|)) and ((|BDB::XML::Document#modify|)) There are two parts to the object -- the query and the operation. The query identifies target nodes against which the operation is run. The operation specifies what modifications to perform. #^ # class Modify # end (()) #^ The results of a query are a collection of values. The values could be either String, Float, true, false, BDB::XML::Documents or BDB::XML::Nodes #^ Implement only the method ((|each|)) # # class Results # end # end # end =end ruby-bdb-0.6.6/bdbxml1/docs/000077500000000000000000000000001154714021300155105ustar00rootroot00000000000000ruby-bdb-0.6.6/bdbxml1/docs/bdbxml.rb000066400000000000000000000052651154714021300173150ustar00rootroot00000000000000# # Berkeley DB XML is an embedded native XML datastore that provides for # the efficient storage and retrieval of XML encoded information. # # Retrieval is supported by an XPath query engine that derives its efficiency # from indices generated from the stored XML data. # # The following classes are defined # # * BDB::XML::Container # # The container name provides the base for the filenames of the database # files used to store the container content. The directory within which # the files are opened is taken from the environment passed through the # Container constructor. If no environment was provided, then the # directory used will be the current working directory. # # * BDB::XML::Index # # Define the indexing strategy for a Container # # Indexing is specified by providing the name of a node and a list of # indexing strategies for that node. # # * BDB::XML::Document # # A Document is the unit of storage within a Container. # # A Document contains a stream of bytes that may be of type XML. # The Container only indexes the content of Documents # that contain XML. # # Document supports annotation attributes. # # # * BDB::XML::Context # # The context within which a query is performed against a Container. # # The context within which a query is performed against a Container # is complex enough to warrent an encapsulating class. This context # includes a namespace mapping, variable bindings, and flags that # determine how the query result set should be determined and returned # to the caller. # # The XPath syntax permits expressions to refer to namespace prefixes, but # not to define them. The Context class provides a number of namespace # management methods so that the caller may manage the namespace prefix # to URI mapping. # # The XPath syntax also permits expressions to refer to variables, but not # to define them. The Context class provides a number of methods so # that the caller may manage the variable to value bindings. # # * BDB::XML::Modify # # Modify encapsulates the context within which a set of documents specified by # a query can be modified in place. # # The modification is performed using the methods # BDB::XML::Container#modify and BDB::XML::Document#modify # # There are two parts to the object -- the query and the operation. # The query identifies target nodes against which the operation is run. # The operation specifies what modifications to perform. # # * BDB::XML::Results # # # The results of a query are a collection of values. The values could # be either String, Float, true, false, BDB::XML::Documents or BDB::XML::Nodes # # module BDB::XML end ruby-bdb-0.6.6/bdbxml1/docs/container.rb000066400000000000000000000150641154714021300200250ustar00rootroot00000000000000# The container name provides the base for the filenames of the database # files used to store the container content. The directory within which # the files are opened is taken from the environment passed through the # Container constructor. If no environment was provided, then the # directory used will be the current working directory. class BDB::XML::Container include Enumerable class << self # #create a new Container object # #* name # the name of the container # #* flags # The flags must be the string "r", "r+", "w", "w+", "a", "a+" or # and integer value. # #* mode # mode for creation (see chmod(2)) # #* options # Hash with the possible keys # # * env # the Berkeley DB environment within which all database # operations are to be performed. # # * txn # the transaction within which all database # operations are to be performed. # # * set_pagesize # Set the pagesize of the primary database (512 < size < 64K) # def new(name = nil, flags = 0, mode = 0, options = {}) end #Dump the container name into the specified file. # def dump(name, filename) end #Load data from the specified file into the container name # def load(name, filename) end #Remove the container name # def remove(name) end #Rename the container name # def rename(name, newname) end #Verify the container name, and save the content in #filename # #* flags # flags can has the value BDB::AGGRESSIVE # def salvage(name, filename, flags = 0) end #Set the name for the container name. The underlying files for the #container are not renamed - for that, see Container::rename # def set_name(name, str) end #Verify the container name # # def verify(name) end end #close an open container # #* flags # flags can has the value 0 or BDB::NOSYNC # def close(flags = 0) end #Remove the document from the container # #* document # document can be an ID or an BDB::XML::Document previously stored # #* flags # flags can has the value 0 or BDB::AUTO_COMMIT # def delete(document, flags = 0) end #return the current environment for the container, or nil # def environment end #same than environment def env end #return true if the container was opend in an environment # def environment? end #same than environment? def env? end #Iterate over all documents # def each yield doc end #Fetch the document from the container # #* id # the id assigned to the document when it was first added to a container # #* flags # flags can has the value 0 or BDB::DIRTY_READ, BDB::RMW # def self[id] end #same than self[id] def get(id, flags = 0) end #Replace the document (see also #update) # def self[id] = document end #set the indexing : index must be an BDB::XML::Index object # def index=(index) end #Retrieve the BDB::XML::Index # #Return nil if no indexing was specified # def index end #in-place modification of all documents according to the state of the #BDB::XML::Modify object, which contains an XPath expression to #target document nodes, as well as specification of the modifications #to perform # #context is an optional BDB::XML::Context used for the update #operations on the container. # #flags must be set to zero or BDB::RMW to acquire a write lock # def modify(mod, context = nil, flags = 0) end #return the name of the container # def name end #Set the name of the container. Can be called only on a closed container #See also Container::set_name # def name=(str) end #return true if the container is open # def open? end #Pre-parse an XPath query and return an BDB::XML::XPath object # #* query # the XPath query to execute against the container # #* context # the context within which the query will be executed # def parse(query, context = nil) end #Add a document to the container and return an ID # #* document # an object BDB::XML::Document or any object suitable for # BDB::XML::Document::new # #* flags # flags can be 0 or BDB::AUTO_COMMIT # def push(document, flags = 0) end #Add a document to the container and return self # def <<(document) end #Query the container with an XPath expression, which can be an object #BDB::XML::XPath or a String # #* flags # flags can have the value 0 or BDB::DIRTY_READ, BDB::RMW # #return a BDB::XML::Results object # def query(xpath, flags = 0) end #Iterate over the result of a query # #returntype can have the values BDB::XML::Context::Document #or BDB::XML::Context::Values # #the query is evaluated lazily # def search(xpath, returntype = BDB::XML::Context::Document) yield doc end #return the transaction associated with the container, or nil # def transaction end #return true if the container is associated with a transaction # def in_transaction? end #same than in_transaction? def transaction? end #Update a document within the container # def update(document) end #return an BDB::XML::UpdateContext which can be used to perform #[], []=, push, delete, update operation # #This can be used for a performance improvement # def update_context yield cxt end #same than update_context {|cxt| ... } def context yield cxt end end ruby-bdb-0.6.6/bdbxml1/docs/container.rd000066400000000000000000000127051154714021300200260ustar00rootroot00000000000000=begin == BDB::XML::Container The container name provides the base for the filenames of the database files used to store the container content. The directory within which the files are opened is taken from the environment passed through the Container constructor. If no environment was provided, then the directory used will be the current working directory. # module BDB # module XML # class Container # include Enumerable # class << self === Class Methods --- allocate(name = nil, options = {}) allocate a new Container object : ((|name|)) the name of the container : ((|options|)) Hash with the possible keys : ((|env|)) the Berkeley DB environment within which all database operations are to be performed. : ((|txn|)) the transaction within which all database operations are to be performed. : ((|set_pagesize|)) Set the pagesize of the primary database (512 < size < 64K) --- dump(name, filename) Dump the container ((|name|)) into the specified file. --- load(name, filename) Load data from the specified file into the container ((|name|)) --- remove(name) Remove the container ((|name|)) --- rename(name, newname) Rename the container ((|name|)) --- salvage(name, filename, flags = 0) Verify the container ((|name|)), and save the content in ((|filename|)) : ((|flags|)) flags can has the value ((|BDB::AGGRESSIVE|)) --- set_name(name, str) Set the name for the container ((|name|)). The underlying files for the container are not renamed - for that, see ((|Container::rename|)) --- verify(name) Verify the container ((|name|)) # end === Methods --- close(flags = 0) close an open container : ((|flags|)) flags can has the value 0 or ((|BDB::NOSYNC|)) --- delete(document, flags = 0) Remove the document from the container : ((|document|)) document can be an ID or an ((|BDB::XML::Document|)) previously stored : ((|flags|)) flags can has the value 0 or ((|BDB::AUTO_COMMIT|)) --- environment --- env return the current environment for the container, or ((|nil|)) --- environment? --- env? return ((|true|)) if the container was opend in an environment --- each {|doc| ... } Iterate over all documents --- self[id] --- get(id, flags = 0) Fetch the document from the container : ((|id|)) the id assigned to the document when it was first added to a container : ((|flags|)) flags can has the value 0 or ((|BDB::DIRTY_READ|)), ((|BDB::RMW|)) --- self[id] = document Replace the document (see also #update) --- index=(index) set the indexing : ((|index|)) must be an ((|BDB::XML::Index|)) object --- index Retrieve the ((|BDB::XML::Index|)) Return ((|nil|)) if no indexing was specified --- initialize(name, flags = 0, mode = 0) open the container : ((|name|)) see ((|allocate|)) : ((|flags|)) The flags must be the string "r", "r+", "w", "w+", "a", "a+" or and integer value. : ((|mode|)) mode for creation (see chmod(2)) --- modify(mod, context = nil, flags = 0) in-place modification of all documents according to the state of the ((|BDB::XML::Modify|)) object, which contains an XPath expression to target document nodes, as well as specification of the modifications to perform ((|context|)) is an optional ((|BDB::XML::Context|)) used for the update operations on the container. ((|flags|)) must be set to zero or ((|BDB::RMW|)) to acquire a write lock --- name return the name of the container --- name=(str) Set the name of the container. Can be called only on a closed container See also ((|Container::set_name|)) --- open? return ((|true|)) if the container is open --- parse(query, context = nil) Pre-parse an XPath query and return an ((|BDB::XML::XPath|)) object : ((|query|)) the XPath query to execute against the container : ((|context|)) the context within which the query will be executed --- push(document, flags = 0) Add a document to the container and return an ID : ((|document|)) an object ((|BDB::XML::Document|)) or any object suitable for ((|BDB::XML::Document::new|)) : ((|flags|)) flags can be 0 or ((|BDB::AUTO_COMMIT|)) --- <<(document) Add a document to the container and return ((|self|)) --- query(xpath, flags = 0) --- query(string, context, flags = 0) Query the container with an XPath expression, which can be an object ((|BDB::XML::XPath|)) or a ((|String|)) : ((|flags|)) flags can have the value 0 or ((|BDB::DIRTY_READ|)), ((|BDB::RMW|)) return a ((|BDB::XML::Results|)) object --- search(xpath, returntype = BDB::XML::Context::Document) {|doc| ... } Iterate over the result of a query ((|returntype|)) can have the values ((|BDB::XML::Context::Document|)) or ((|BDB::XML::Context::Values|)) the query is evaluated lazily --- transaction return the transaction associated with the container, or ((|nil|)) --- in_transaction? --- transaction? return ((|true|)) if the container is associated with a transaction --- update(document) Update a document within the container --- update_context {|cxt| ... } --- context {|cxt| ... } return an ((|BDB::XML::UpdateContext|)) which can be used to perform ((|[]|)), ((|[]=|)), ((|push|)), ((|delete|)), ((|update|)) operation This can be used for a performance improvement # end # end # end =endruby-bdb-0.6.6/bdbxml1/docs/context.rb000066400000000000000000000051261154714021300175250ustar00rootroot00000000000000# The context within which a query is performed against a Container. # # The context within which a query is performed against a Container # is complex enough to warrent an encapsulating class. This context # includes a namespace mapping, variable bindings, and flags that # determine how the query result set should be determined and returned # to the caller. # # The XPath syntax permits expressions to refer to namespace prefixes, but # not to define them. The Context class provides a number of namespace # management methods so that the caller may manage the namespace prefix # to URI mapping. # # The XPath syntax also permits expressions to refer to variables, but not # to define them. The Context class provides a number of methods so # that the caller may manage the variable to value bindings. class BDB::XML::Context #Get the value bound to a variable # def [](variable) end #Bind a value to a variable # def []=(variable, value) end #Delete all the namespace prefix mappings # def clear_namespaces end #same than clear_namespaces def clear end #Delete the namespace URI for a particular prefix # def del_namespace(name) end #Return the evaluation type # def evaltype end #Set the evaluation type # def evaltype=(type) end #Get the namespace URI that a namespace prefix maps onto # def get_namespace(name) end #same than get_namespace def namespace[name] end #Initialize the object with the optional evaluation type #BDB::XML::Context::Lazy or BDB::XML::Context::Eager #and return type BDB::XML::Context::Documents, #BDB::XML::Context::Values or #BDB::XML::Context::Candidates # def initialize(returntype = nil, evaluation = nil) end #return true if the metadata is added to the document # def metadata end #same than metadata def with_metadata end #The with parameter specifies whether or not to add the document #metadata prior to the query. # def metadata=(with) end #same than metadata= def with_metadata=(with) end #Return the return type # def returntype end #Set the return type # def returntype=(type) end #Define a namespace prefix, providing the URI that it maps onto # #If uri is nil delete the namespace def namespace[name]=(uri) end #same than namespace[name]= def set_namespace(name, uri) end end ruby-bdb-0.6.6/bdbxml1/docs/context.rd000066400000000000000000000043401154714021300175240ustar00rootroot00000000000000=begin == BDB::XML::Context The context within which a query is performed against a Container. The context within which a query is performed against a Container is complex enough to warrent an encapsulating class. This context includes a namespace mapping, variable bindings, and flags that determine how the query result set should be determined and returned to the caller. The XPath syntax permits expressions to refer to namespace prefixes, but not to define them. The Context class provides a number of namespace management methods so that the caller may manage the namespace prefix to URI mapping. The XPath syntax also permits expressions to refer to variables, but not to define them. The Context class provides a number of methods so that the caller may manage the variable to value bindings. # module BDB # module XML # class Context # class << self === Class Methods --- allocate Allocate a new Context object # end === Methods --- self[variable] Get the value bound to a variable --- self[variable] = value Bind a value to a variable --- clear_namespaces --- clear Delete all the namespace prefix mappings --- del_namespace(name) Delete the namespace URI for a particular prefix --- evaltype Return the evaluation type --- evaltype=(type) Set the evaluation type --- get_namespace(name) --- namespace[name] Get the namespace URI that a namespace prefix maps onto --- initialize(returntype = nil, evaluation = nil) Initialize the object with the optional evaluation type ((|BDB::XML::Context::Lazy|)) or ((|BDB::XML::Context::Eager|)) and return type ((|BDB::XML::Context::Documents|)), ((|BDB::XML::Context::Values|)) or ((|BDB::XML::Context::Candidates|)) --- metadata --- with_metadata return ((|true|)) if the metadata is added to the document --- metadata=(with) --- with_metadata=(with) The ((|with|)) parameter specifies whether or not to add the document metadata prior to the query. --- returntype Return the return type --- returntype=(type) Set the return type --- namespace[name]=(uri) --- set_namespace(name, uri) Define a namespace prefix, providing the URI that it maps onto If ((|uri|)) is ((|nil|)) delete the namespace # end # end # end =end ruby-bdb-0.6.6/bdbxml1/docs/document.rb000066400000000000000000000037421154714021300176610ustar00rootroot00000000000000# A Document is the unit of storage within a Container. # # A Document contains a stream of bytes that may be of type XML. # The Container only indexes the content of Documents # that contain XML. # # Document supports annotation attributes. # class BDB::XML::Document #Return the value of an attribute # def [](attr) end #Set the value of an attribute # def []=(attr, val) end #Return the content of the document # def content end #Set the content of the document # def content=(val) end #Return the value of an attribute. uri specify the namespace #where reside the attribute. # #the optional class argument give the type (String, Numeric, ...) # def get(uri = "", attr [, class]) end #Return the ID # def id end #Initialize the document with the content specified # def initialize(content = "") end #Modifies the document contents based on the information contained in the #BDB::XML::Modify object # def modify(mod) end #Return the name of the document # def name end #Set the name of the document # def name=(val) end #Return the default prefix for the namespace # def prefix end #Set the default prefix used by set # def prefix=(val) end #Execute the XPath expression xpath against the document #Return an BDB::XML::Results # def query(xpath, context = nil) end #Set an attribute in the namespace uri. prefix is the prefix #for the namespace # def set(uri = "", prefix = "", attr, value) end #Return the document as a String object # def to_s end #same than to_s def to_str end #Return the default namespace # def uri end #Set the default namespace used by set and get # def uri=(val) end end ruby-bdb-0.6.6/bdbxml1/docs/document.rd000066400000000000000000000032201154714021300176520ustar00rootroot00000000000000=begin == BDB::XML::Document A Document is the unit of storage within a Container. A Document contains a stream of bytes. Document supports annotation attributes. # module BDB # module XML # class Document # class << self === Class Methods --- allocate Allocate a new object # end === Methods --- self[attr] Return the value of an attribute --- self[attr] = val Set the value of an attribute --- content Return the content of the document --- content=(val) Set the content of the document --- get(uri = "", attr [, class]) Return the value of an attribute. ((|uri|)) specify the namespace where reside the attribute. the optional ((|class|)) argument give the type (String, Numeric, ...) --- id Return the ID --- initialize(content = "") Initialize the document with the content specified --- modify(mod) Modifies the document contents based on the information contained in the ((|BDB::XML::Modify|)) object --- name Return the name of the document --- name=(val) Set the name of the document --- prefix Return the default prefix for the namespace --- prefix=(val) Set the default prefix used by ((|set|)) --- query(xpath, context = nil) Execute the XPath expression ((|xpath|)) against the document Return an ((|BDB::XML::Results|)) --- set(uri = "", prefix = "", attr, value) Set an attribute in the namespace ((|uri|)). ((|prefix|)) is the prefix for the namespace --- to_s --- to_str Return the document as a String object --- uri Return the default namespace --- uri=(val) Set the default namespace used by ((|set|)) and ((|get|)) # end # end # end =end ruby-bdb-0.6.6/bdbxml1/docs/index.rb000066400000000000000000000035151154714021300171500ustar00rootroot00000000000000# Define the indexing strategy for a Container # # Indexing is specified by providing the name of a node and a list of indexing # strategies for that node. class BDB::XML::Index # #add a new index # #* uri # The namespace for the element (optional) # #* name # The name parameter provides the fully qualified element type # to be indexed. # #* index # The index string is a comma separated list of the following indexing # strategy names # # * none-none-none-none # * node-element-presence # * node-attribute-presence # * node-element-equality-string # * node-element-equality-number # * node-element-substring-string # * node-attribute-equality-string # * node-attribute-equality-number # * node-attribute-substring-string # * edge-element-presence # * edge-attribute-presence # * edge-element-equality-string # * edge-element-equality-number # * edge-element-substring-string # * edge-attribute-equality-string # * edge-attribute-equality-number # * edge-attribute-substring-string # def add(uri = "", name, index) end #Delete the specified index # def delete(uri = "", name, index) end #Iterate over all indexes # def each yield uri, name, index end #Initialize the index with the optional values [uri, name, value] # def initialize([[uri0, name0, index0] [, [uri1, name1, index1], ... ]]) end #Find the indexing startegy associated with uri, and name # #Return nil is no indexing strategy was defined # def find(uri = "", name) end #Replace the specified index # def replace(uri = "", name, index) end #Return an Array of all indexes # def to_a end end ruby-bdb-0.6.6/bdbxml1/docs/index.rd000066400000000000000000000033621154714021300171520ustar00rootroot00000000000000=begin == BDB::XML::Index The index specification # module BDB # module XML # class Index # class << self === Class Methods --- allocate Allocate a new Index object # end === Methods --- add(uri = "", name, index) add a new index : ((|uri|)) The namespace for the element (optional) : ((|name|)) The name parameter provides the fully qualified element type to be indexed. : ((|index|)) The index string is a comma separated list of the following indexing strategy names : none-none-none-none : node-element-presence : node-attribute-presence : node-element-equality-string : node-element-equality-number : node-element-substring-string : node-attribute-equality-string : node-attribute-equality-number : node-attribute-substring-string : edge-element-presence : edge-attribute-presence : edge-element-equality-string : edge-element-equality-number : edge-element-substring-string : edge-attribute-equality-string : edge-attribute-equality-number : edge-attribute-substring-string --- delete(uri = "", name, index) Delete the specified index --- each {|uri, name, index| ... } Iterate over all indexes --- initialize([[uri0, name0, index0] [, [uri1, name1, index1], ... ]]) Initialize the index with the optional values [uri, name, value] --- find(uri = "", name) Find the indexing startegy associated with ((|uri|)), and ((|name|)) Return ((|nil|)) is no indexing strategy was defined --- replace(uri = "", name, index) Replace the specified index --- to_a Return an Array of all indexes # end # end # end =end ruby-bdb-0.6.6/bdbxml1/docs/modify.rb000066400000000000000000000036301154714021300173260ustar00rootroot00000000000000# Modify encapsulates the context within which a set of documents specified by # a query can be modified in place. # # The modification is performed using the methods # BDB::XML::Container#modify and BDB::XML::Document#modify # # There are two parts to the object -- the query and the operation. # The query identifies target nodes against which the operation is run. # The operation specifies what modifications to perform. class BDB::XML::Modify #return the number of node hits in the specified query. # def count end # #xpath is a String, or an BDB::XML::Context object # #operation can have the value BDB::XML::Modify::InsertAfter, #BDB::XML::Modify::InsertBefore, BDB::XML::Modify::Append, #BDB::XML::Modify::Update, BDB::XML::Modify::Remove or #BDB::XML::Modify::Rename. # #type can have the value BDB::XML::Modify::Element, #BDB::XML::Modify::Attribute, BDB::XML::Modify::Text, #BDB::XML::Modify::ProcessingInstruction, BDB::XML::Modify::Comment or #BDB::XML::Modify::None. # #name is the name for the new content. # #content the content for operations that require content. # #location indicate where a new child node will be placed for the #append operation # #context is valid only when a String is given as the first argument. #This must be a BDB::XML::Context which contains the variable #bindings, the namespace prefix to URI mapping, and the query processing #flags. # def initialize(xpath, operation, type = BDB::XML::Modify::None, name = "", content = "", location = -1, context = nil) end #Specify a new character encoding for the modified documents. # def encoding=(string) end end ruby-bdb-0.6.6/bdbxml1/docs/modify.rd000066400000000000000000000036211154714021300173300ustar00rootroot00000000000000=begin == BDB::XML::Modify Modify encapsulates the context within which a set of documents specified by a query can be modified in place. The modification is performed using the methods ((|BDB::XML::Container#modify|)) and ((|BDB::XML::Document#modify|)) There are two parts to the object -- the query and the operation. The query identifies target nodes against which the operation is run. The operation specifies what modifications to perform. # module BDB # module XML # class Modify # class << self === Class Methods --- allocate Allocate a new object # end === Methods --- count return the number of node hits in the specified query. --- initialize(xpath, operation, type = BDB::XML::Modify::None, name = "", content = "", location = -1, context = nil) ((|xpath|)) is a ((|String|)), or an ((|BDB::XML::Context|)) object ((|operation|)) can have the value ((|BDB::XML::Modify::InsertAfter|)), ((|BDB::XML::Modify::InsertBefore|)), ((|BDB::XML::Modify::Append|)), ((|BDB::XML::Modify::Update|)), ((|BDB::XML::Modify::Remove|)) or ((|BDB::XML::Modify::Rename|)). ((|type|)) can have the value ((|BDB::XML::Modify::Element|)), ((|BDB::XML::Modify::Attribute|)), ((|BDB::XML::Modify::Text|)), ((|BDB::XML::Modify::ProcessingInstruction|)), ((|BDB::XML::Modify::Comment|)) or ((|BDB::XML::Modify::None|)). ((|name|)) is the name for the new content. ((|content|)) the content for operations that require content. ((|location|)) indicate where a new child node will be placed for the append operation ((|context|)) is valid only when a String is given as the first argument. This must be a ((|BDB::XML::Context|)) which contains the variable bindings, the namespace prefix to URI mapping, and the query processing flags. --- encoding=(string) Specify a new character encoding for the modified documents. # end # end # end =end ruby-bdb-0.6.6/bdbxml1/docs/results.rb000066400000000000000000000004261154714021300175400ustar00rootroot00000000000000# # The results of a query are a collection of values. The values could # be either String, Float, true, false, BDB::XML::Documents or BDB::XML::Nodes # class BDB::XML::Results include Enumerable #Iterate on each values # def each yield val end end ruby-bdb-0.6.6/bdbxml1/docs/results.rd000066400000000000000000000005041154714021300175370ustar00rootroot00000000000000=begin == BDB::XML::Results The results of a query are a collection of values. The values could be either String, Float, true, false, BDB::XML::Documents or BDB::XML::Nodes # module BDB # module XML # class Results # include Enumerable === Methods --- each {|val| ... } Iterate on each values # end # end # end =end ruby-bdb-0.6.6/bdbxml1/examples/000077500000000000000000000000001154714021300163765ustar00rootroot00000000000000ruby-bdb-0.6.6/bdbxml1/examples/dbxml/000077500000000000000000000000001154714021300175045ustar00rootroot00000000000000ruby-bdb-0.6.6/bdbxml1/examples/dbxml/README000066400000000000000000000050721154714021300203700ustar00rootroot00000000000000 This directory contains example "DBXML Getting Started Examples" translated in ruby You must first load the database, to do this 1) change the variable data in load.rb data = "/home/ts/db/dbxml-1.1.0/examples/xmlData" to specify where are located the 2 directories simpleData and nsData 2) execute load.rb You can then use the examples. * query.rb Executes several XPath queries and prints query results to the console. * context.rb Identical to query.rb, except that contexts are used to define namespaces and variables. * document.rb Identical to context.rb, except that specific document data is retrieved from each document found in the query's result set. * names.rb Identical to context.rb, except that the query is performed using the document name that was set when load.rb placed the document into the container. * metadata.rb Identical to context.rb, except that the timestamp that was stored as metadata is retrieved and displayed. This timestamp was set on the document when load.rb placed the document into the container. * update.rb Identical to context.rb, except that the document retrieved as the result of the query is updated in a trivial way and then stored back into the container. * delete.rb Identical to context.rb, except that every document retrieved as the result of the query is deleted from the container. * add_index.rb Adds indexes to a specific document node. * replace_index.rb Replaces the indexes on a specific document node with new indexes. Iterates through the indexes maintained for the container and shows what is being used. For best results, run add_index.rb before running this example. * delete_index.rb Deletes indexes from a specific document. Iterates through the indexes maintained for the container and shows what is being used. For best results, run add_index.rb before running this example. * build_db.rb Illustrates how a DBXML container can be used with a Berkeley DB database. A Berkeley DB database is created in the same environment as the container and data corresponding to documents in the container is loaded into the database. The DBXML query and database put are all wrapped in a common transaction. * retrieve_db.rb Illustrates how a DBXML container can be used with a Berkeley DB database. Documents are retrieved from the container and then data corresponding to each document is retrieved from the Berkeley DB database. Again, all queries are wrapped in a common transaction. For best results, run build_db.rb before running this example. ruby-bdb-0.6.6/bdbxml1/examples/dbxml/a.sh000066400000000000000000000015601154714021300202620ustar00rootroot00000000000000#!/bin/sh echo "=================================== query.rb" ruby query.rb echo "=================================== context.rb" ruby context.rb echo "=================================== document.rb" ruby document.rb echo "=================================== names.rb" ruby names.rb echo "=================================== metadata.rb" ruby metadata.rb echo "=================================== update.rb" ruby update.rb echo "=================================== delete.rb" ruby delete.rb echo "=================================== add_index.rb" ruby add_index.rb echo "=================================== replace_index.rb" ruby replace_index.rb echo "=================================== delete_index.rb" ruby delete_index.rb echo "=================================== build_db.rb " ruby build_db.rb echo "=================================== retrieve_db.rb" ruby retrieve_db.rb ruby-bdb-0.6.6/bdbxml1/examples/dbxml/add_index.rb000077500000000000000000000016241154714021300217560ustar00rootroot00000000000000#!/usr/bin/ruby -I../.. -I../../../src require 'bdbxml' def add(container, uri, name, itype) puts "Adding index type : #{itype} to #{name}" index = container.index puts "Before index add" count = 0 index.each do |u, n, i| puts "\tFor node #{n}, found index #{i}." count += 1 end puts "#{count} indexes found" index.add(uri, name, itype) container.index = index puts "After index add" count = 0 index.each do |u, n, i| puts "\tFor node #{n}, found index #{i}." count += 1 end puts "#{count} indexes found" rescue puts "Add index failed #{$!}" end options = {'home' => 'env', 'container' => 'name.xml'} BDB::Env.new(options['home'], BDB::INIT_TRANSACTION).begin do |txn| con = txn.open_xml(options['container']) add(con, "", "product", "node-element-equality-string") add(con, "", "product", "edge-element-presence") txn.commit end ruby-bdb-0.6.6/bdbxml1/examples/dbxml/build_db.rb000077500000000000000000000013441154714021300216020ustar00rootroot00000000000000#!/usr/bin/ruby -I../.. -I../../../src require 'bdbxml' def value(document, xpath, context) result = document.query(xpath, context).to_a if result.size != 1 raise "Expected 1 got #{result.size}" end result[0].to_s end options = {'home' => 'env', 'container' => 'name.xml'} env = BDB::Env.new(options['home'], BDB::INIT_TRANSACTION) context = BDB::XML::Context.new context.returntype = BDB::XML::Context::Values env.begin do |txn| con = txn.open_xml(options['container']) bdb = txn.open_db(BDB::Btree, 'bdb', nil, 'a') con.search("/vendor") do |doc| res = value(doc, "/vendor/salesrep/name/text()", context) bdb[res] = "This is the data stored in the database for #{res}" end txn.commit end ruby-bdb-0.6.6/bdbxml1/examples/dbxml/context.rb000077500000000000000000000026031154714021300215210ustar00rootroot00000000000000#!/usr/bin/ruby -I../.. -I../../../src require 'bdbxml' def value(document, xpath, context) context.returntype = BDB::XML::Context::Values result = document.query(xpath, context).to_a if result.size != 1 raise "Expected 1 got #{result.size}" end result[0] ensure context.returntype = BDB::XML::Context::Documents end def query_context(container, xpath, context) puts "Exercising query '#{xpath}'" print "Return to continue : " STDIN.gets results = container.query(xpath, context) results.each {|r| puts r} puts "#{results.size} objects returned for expression '#{xpath}'" puts rescue puts "Query #{xpath} failed : #{$!}" end options = {'home' => 'env', 'container' => 'name.xml'} con = BDB::Env.new(options['home'], BDB::INIT_LOMP). open_xml(options['container']) context = BDB::XML::Context.new context.set_namespace("fruits", "http://groceryItem.dbxml/fruits") context.set_namespace("vegetables", "http://groceryItem.dbxml/vegetables") context.set_namespace("desserts", "http://groceryItem.dbxml/desserts"); context["aDessert"] = "Blueberry Boy Bait" query_context(con, "/vendor", context) query_context(con, "/item/product[text()='Lemon Grass']", context) query_context(con, "/fruits:item/product[text()='Lemon Grass']", context) query_context(con, "/vegetables:item", context) query_context(con, "/desserts:item/product[text()=$aDessert]", context) ruby-bdb-0.6.6/bdbxml1/examples/dbxml/delete.rb000077500000000000000000000032511154714021300212770ustar00rootroot00000000000000#!/usr/bin/ruby -I../.. -I../../../src require 'bdbxml' def value(document, xpath, context) context.returntype = BDB::XML::Context::Values result = document.query(xpath, context).to_a if result.size != 1 raise "Expected 1 got #{result.size}" end result[0] ensure context.returntype = BDB::XML::Context::Documents end def delete(container, xpath, context) puts "Deleting document for '#{xpath}'" print "Return to continue : " STDIN.gets results = container.query(xpath, context) puts "\nFound #{results.size} documents matching the expression '#{xpath}'" results.each do |r| puts "Deleting document #{value(r, '/*/product/text()', context)}" container.delete(r) puts "Deleted document #{value(r, '/*/product/text()', context)}" end puts rescue puts "Query #{xpath} failed : #{$!}" end def confirm(container, xpath, context) puts "Conforming the delete document" puts "The query : '#{xpath}' should get result set size 0" if container.query(xpath, context).size == 0 puts "Deletion confirmed." else puts "Document deletion failed." end end options = {'home' => 'env', 'container' => 'name.xml'} BDB::Env.new(options['home'], BDB::INIT_TRANSACTION).begin do |txn| con = txn.open_xml(options['container']) context = BDB::XML::Context.new context.set_namespace("fruits", "http://groceryItem.dbxml/fruits") context.set_namespace("vegetables", "http://groceryItem.dbxml/vegetables") context.set_namespace("desserts", "http://groceryItem.dbxml/desserts"); delete(con, "/fruits:item[product = 'Mabolo']", context) confirm(con, "/fruits:item[product = 'Mabolo']", context) txn.commit end ruby-bdb-0.6.6/bdbxml1/examples/dbxml/delete_index.rb000077500000000000000000000016601154714021300224700ustar00rootroot00000000000000#!/usr/bin/ruby -I../.. -I../../../src require 'bdbxml' def delete(container, uri, name, itype) puts "Deleting index type : #{itype} to #{name}" index = container.index puts "Before index delete" count = 0 index.each do |u, n, i| puts "\tFor node #{n}, found index #{i}." count += 1 end puts "#{count} indexes found" index.delete(uri, name, itype) container.index = index puts "After index delete" count = 0 index.each do |u, n, i| puts "\tFor node #{n}, found index #{i}." count += 1 end puts "#{count} indexes found" rescue puts "delete index failed #{$!}" end options = {'home' => 'env', 'container' => 'name.xml'} BDB::Env.new(options['home'], BDB::INIT_TRANSACTION).begin do |txn| con = txn.open_xml(options['container']) delete(con, "", "product", "node-element-equality-string") delete(con, "", "product", "edge-element-presence-none") txn.commit end ruby-bdb-0.6.6/bdbxml1/examples/dbxml/document.rb000077500000000000000000000026071154714021300216570ustar00rootroot00000000000000#!/usr/bin/ruby -I../.. -I../../../src require 'bdbxml' def value(document, xpath, context) context.returntype = BDB::XML::Context::Values result = document.query(xpath, context).to_a if result.size != 1 raise "Expected 1 got #{result.size}" end result[0] ensure context.returntype = BDB::XML::Context::Documents end def details(container, xpath, context) puts "Exercising query '#{xpath}'" print "Return to continue : " STDIN.gets results = container.query(xpath, context) puts "\n\tProduct : Price : Inventory Level" results.each do |r| item = value(r, "/*/product/text()", context) price = value(r, "/*/inventory/price/text()", context) inventory = value(r, "/*/inventory/inventory/text()", context) puts "\t#{item} : #{price} : #{inventory}" end puts rescue puts "Query #{xpath} failed : #{$!}" end options = {'home' => 'env', 'container' => 'name.xml'} con = BDB::Env.new(options['home'], BDB::INIT_LOMP). open_xml(options['container']) context = BDB::XML::Context.new context.set_namespace("fruits", "http://groceryItem.dbxml/fruits") context.set_namespace("vegetables", "http://groceryItem.dbxml/vegetables") context.set_namespace("desserts", "http://groceryItem.dbxml/desserts"); details(con, "/fruits:item/product[text() = 'Zulu Nut']", context) details(con, "/vegetables:item/product[starts-with(text(),'A')]", context) ruby-bdb-0.6.6/bdbxml1/examples/dbxml/load.rb000077500000000000000000000006541154714021300207600ustar00rootroot00000000000000#!/usr/bin/ruby data = "/home/ts/db/dbxml-1.1.0/examples/xmlData" unless FileTest.directory?(data) && FileTest.directory?(data + "/simpleData") puts "Error can't find DbXml examples" puts "path : #{data}" exit end puts "Loading from #{data}" [["simpleData", "simple"], ["nsData", "name"]].each do |dir, name| xml = Dir[data + "/#{dir}/*.xml"] system("ruby ./loadex.rb -h env -c #{name}.xml #{xml.join(' ')}") end ruby-bdb-0.6.6/bdbxml1/examples/dbxml/loadex.rb000077500000000000000000000027141154714021300213140ustar00rootroot00000000000000#!/usr/bin/ruby -I../.. -I../../../src require 'bdbxml' require 'getoptlong' opt = GetoptLong.new( ['--container', '-c', GetoptLong::REQUIRED_ARGUMENT], ['--path', '-p', GetoptLong::REQUIRED_ARGUMENT], ['--files', '-f', GetoptLong::REQUIRED_ARGUMENT], ['--home', '-h', GetoptLong::REQUIRED_ARGUMENT] ) options = {'path' => ''} opt.each {|name, value| options[name.sub(/^--/, '')] = value} $files = ARGV.dup options['path'] << '/' if options['path'].size > 0 if options['files'] IO.foreach(options['files']) {|line| $files << options['path'] + line.chomp} end if !$files || !options['container'] || !options['home'] puts <<-EOT This program loads XML data into an identified container and environment. Provide the directory where you want to place your database environment, the name of the container to use, and the xml files you want inserted into the container. -h -c -f -p file1.xml ... EOT exit(-1) end BDB::Env.new(options['home'],BDB::CREATE|BDB::INIT_TRANSACTION). begin do |txn| con = txn.open_xml(options['container'], 'a') $files.each do |f| doc = BDB::XML::Document.new(IO.readlines(f, nil)[0]) /[^\/]*$/ =~ f doc.name = $& doc.set("http://dbxmlExamples/timestamp", "time", "timeStamp", Time.now.to_s) con << doc puts "added #{f} to container #{options['container']}" end txn.commit end ruby-bdb-0.6.6/bdbxml1/examples/dbxml/metadata.rb000077500000000000000000000024011154714021300216110ustar00rootroot00000000000000#!/usr/bin/ruby -I../.. -I../../../src require 'bdbxml' def value(document, xpath, context) context.returntype = BDB::XML::Context::Values result = document.query(xpath, context).to_a if result.size != 1 raise "Expected 1 got #{result.size}" end result[0] ensure context.returntype = BDB::XML::Context::Documents end def timestamp(container, xpath, context) puts "Exercising query '#{xpath}'" print "Return to continue : " STDIN.gets results = container.query(xpath, context) puts "\n\tProduct : Price : Inventory Level" results.each do |r| meta = r.get("http://dbxmlExamples/timestamp", "timeStamp", String) puts "Document #{r.name} stored on #{meta}" end puts "#{results.size} objects returned for expression '#{xpath}'" puts rescue puts "Query #{xpath} failed : #{$!}" end options = {'home' => 'env', 'container' => 'name.xml'} con = BDB::Env.new(options['home'], BDB::INIT_LOMP). open_xml(options['container']) context = BDB::XML::Context.new context.set_namespace("fruits", "http://groceryItem.dbxml/fruits") context.set_namespace("vegetables", "http://groceryItem.dbxml/vegetables") context.set_namespace("desserts", "http://groceryItem.dbxml/desserts"); timestamp(con, "/vegetables:item", context) ruby-bdb-0.6.6/bdbxml1/examples/dbxml/names.rb000077500000000000000000000017531154714021300211450ustar00rootroot00000000000000#!/usr/bin/ruby -I../.. -I../../../src require 'bdbxml' def names(container, xpath, context) puts "Exercising query '#{xpath}'" print "Return to continue : " STDIN.gets results = container.query(xpath, context) results.each do |r| puts "Document name : #{r.name}" puts r end puts "#{results.size} objects returned for expression '#{xpath}'" puts rescue puts "Query #{xpath} failed : #{$!}" end options = {'home' => 'env', 'container' => 'name.xml'} con = BDB::Env.new(options['home'], BDB::INIT_LOMP). open_xml(options['container']) context = BDB::XML::Context.new context.set_namespace("fruits", "http://groceryItem.dbxml/fruits") context.set_namespace("vegetables", "http://groceryItem.dbxml/vegetables") context.set_namespace("desserts", "http://groceryItem.dbxml/desserts"); names(con, "//*[@dbxml:name='ZuluNut.xml']", context) names(con, "//*[@dbxml:name='TrifleOrange.xml']", context) names(con, "//*[@dbxml:name='TriCountyProduce.xml']", context) ruby-bdb-0.6.6/bdbxml1/examples/dbxml/query.rb000077500000000000000000000012631154714021300212030ustar00rootroot00000000000000#!/usr/bin/ruby -I../.. -I../../../src require 'bdbxml' query = [ '/vendor', '/vendor[@type="wholesale"]', '/product/item[text()="Lemon Grass"]', '/product/inventory[number(price)<=0.11]', '/product[number(inventory/price)<=0.11 and category/text()="vegetables"]', ] options = {'home' => 'env', 'container' => 'simple.xml'} env = BDB::Env.new(options['home'], BDB::INIT_LOMP) con = env.open_xml(options['container']) query.each do |q| puts "Exercising query '#{q}'" print "Return to continue : " STDIN.gets results = con.query(q) results.each {|r| puts r} puts "#{results.size} objects returned for expression '#{q}'" puts end ruby-bdb-0.6.6/bdbxml1/examples/dbxml/replace_index.rb000077500000000000000000000016371154714021300226450ustar00rootroot00000000000000#!/usr/bin/ruby -I../.. -I../../../src require 'bdbxml' def replace(container, uri, name, itype) puts "Replacing index type : #{itype} to #{name}" index = container.index puts "Before index delete" count = 0 index.each do |u, n, i| puts "\tFor node #{n}, found index #{i}." count += 1 end puts "#{count} indexes found" index.replace(uri, name, itype) container.index = index puts "After index replace" count = 0 index.each do |u, n, i| puts "\tFor node #{n}, found index #{i}." count += 1 end puts "#{count} indexes found" rescue puts "Replace index failed #{$!}" end options = {'home' => 'env', 'container' => 'name.xml'} BDB::Env.new(options['home'], BDB::INIT_TRANSACTION).begin do |txn| con = txn.open_xml(options['container']) replace(con, "", "product", "node-attribute-substring-string node-element-equality-string") txn.commit end ruby-bdb-0.6.6/bdbxml1/examples/dbxml/retrieve_db.rb000077500000000000000000000013461154714021300223320ustar00rootroot00000000000000#!/usr/bin/ruby -I../.. -I../../../src require 'bdbxml' def value(document, xpath, context) result = document.query(xpath, context).to_a if result.size != 1 raise "Expected 1 got #{result.size}" end result[0].to_s end options = {'home' => 'env', 'container' => 'name.xml'} env = BDB::Env.new(options['home'], BDB::INIT_TRANSACTION) context = BDB::XML::Context.new context.returntype = BDB::XML::Context::Values env.begin do |txn| con = txn.open_xml(options['container']) bdb = txn.open_db(BDB::Btree, 'bdb', nil, 'a') con.search("/vendor") do |doc| res = value(doc, "/vendor/salesrep/name/text()", context) puts "For key '#{res}', retrieved : " puts "\t #{bdb[res]}" end txn.commit end ruby-bdb-0.6.6/bdbxml1/examples/dbxml/update.rb000077500000000000000000000040071154714021300213170ustar00rootroot00000000000000#!/usr/bin/ruby -I../.. -I../../../src require 'bdbxml' def value(document, xpath, context) context.returntype = BDB::XML::Context::Values result = document.query(xpath, context).to_a if result.size != 1 raise "Expected 1 got #{result.size}" end result[0] ensure context.returntype = BDB::XML::Context::Documents end def new_document(document, context) res = value(document,"/*/inventory/inventory/text()", context).to_s document.to_s.sub(/#{res}/, "#{res}A") end def update(container, xpath, context) puts "Updating document for '#{xpath}'" print "Return to continue : " STDIN.gets results = container.query(xpath, context) puts "\nFound #{results.size} documents matching the expression '#{xpath}'" results.each do |r| puts "Updating document #{r.name}" puts r print "Return to continue : " STDIN.gets r.content = new_document(r, context) container.update(r) end puts rescue puts "Query #{xpath} failed : #{$!}" end def retrieve(container, xpath, context) puts "Retrieving document for '#{xpath}'" print "Return to continue : " STDIN.gets results = container.query(xpath, context) puts "\nFound #{results.size} documents matching the expression '#{xpath}'" results.each do |r| puts "Document #{r.name}" puts r print "Return to continue : " STDIN.gets end puts rescue puts "Query #{xpath} failed : #{$!}" end options = {'home' => 'env', 'container' => 'name.xml'} BDB::Env.new(options['home'], BDB::INIT_TRANSACTION).begin do |txn| con = txn.open_xml(options['container']) context = BDB::XML::Context.new context.set_namespace("fruits", "http://groceryItem.dbxml/fruits") context.set_namespace("vegetables", "http://groceryItem.dbxml/vegetables") context.set_namespace("desserts", "http://groceryItem.dbxml/desserts"); update(con, "/fruits:item/product[text() = 'Zapote Blanco']", context) retrieve(con, "/fruits:item/product[text() = 'Zapote Blanco']", context) txn.commit end ruby-bdb-0.6.6/bdbxml1/examples/index.rb000066400000000000000000000020061154714021300200300ustar00rootroot00000000000000#!/usr/bin/ruby -I../../src -I.. require 'bdbxml' index = BDB::XML::Index.new index.add(BDB::XML::Namespace["uri"], BDB::XML::Name["default"], "node-attribute-substring-string") index.add("http://moulon/", "ref2", "node-attribute-equality-string") index.add("http://moulon/", "ref0", "node-attribute-equality-string") index.add("http://moulon/", "ref1", "node-element-presence-none") index.each do |url, name, val| puts "#{url}, #{name}, #{val}" end p index.find("http://moulon/", "ref2") p index.find("", "ref2") index.add("http://moulon/", "ref0", "node-element-presence-none") index.add("http://moulon/", "ref0", "edge-attribute-equality-string") p index.find("http://moulon/", "ref0") index.delete("http://moulon/", "ref0", "node-attribute-equality-string") p index.find("http://moulon/", "ref0") index.replace("http://moulon/", "ref0", "edge-element-presence-none") p index.find("http://moulon/", "ref0") index.replace("http://moulon/", "ref0", "none-none-none-none") p index.find("http://moulon/", "ref0") ruby-bdb-0.6.6/bdbxml1/examples/transaction.rb000077500000000000000000000015471154714021300212620ustar00rootroot00000000000000#!/usr/bin/ruby -I../../src -I.. $LOAD_PATH.unshift "../../src", ".." require 'bdbxml' require 'find' Find::find('tmp') do |f| File::unlink(f) if FileTest::file? f end env = BDB::Env.new("tmp", BDB::CREATE | BDB::INIT_TRANSACTION) doc = env.open_xml("toto", "a") bdb = env.open_db(BDB::Btree, "tutu", nil, "a") 2.times do |i| doc.push("title nb #{i}") bdb[i] = "bdb#{i}" end env.begin(doc, bdb) do |txn, doc1, bdb1| 2.times do |i| bdb1[i+2] = "bdb#{i+2}" doc1.push("title nb #{i+2}") end puts "=========================================" doc1.search("//ttl[@id < 12]", BDB::XML::Context::Values) {|x| p x} bdb1.each {|k,v| p "#{k} -- #{v}" } end puts "=========================================" doc.search("//ttl[@id < 12]") {|x| p x } bdb.each {|k,v| p "#{k} -- #{v}" } ruby-bdb-0.6.6/bdbxml1/extconf.rb000066400000000000000000000044011154714021300165520ustar00rootroot00000000000000# VERIFY 'myconfig' then comment this line require 'mkmf' load './myconfig' $DLDFLAGS ||= "" $LDFLAGS ||= "" def addld(key, path, lib) libs = if lib.kind_of?(Array) "-l" + lib.join(" -l") else "-l#{lib}" end if path case Config::CONFIG["arch"] when /solaris2/ libs = " -L#{path} -R#{path} #{libs}" when /linux/ libs = " -Wl,-rpath,#{path} -L#{path} #{libs}" else libs = " -L#{path} #{libs}" end end $stderr.puts "\t#{key}\tusing ... #{libs}" $DLDFLAGS += " #{libs}" $LDFLAGS += " #{libs}" end $CFLAGS += " -I. -I../src" $stderr.puts "INCLUDE" $order.each do |key| val = $include[key] unless val.nil? res = if val.kind_of?(Array) " -I" + val.join(" -I") else " -I#{val}" end $stderr.puts "\t#{key}\tusing ... #{res}" $CFLAGS += res end end $CFLAGS += " -DBDB_NO_THREAD" if enable_config("thread") == false $stderr.puts "\nLIBRARY" $order.each do |key| val = $library[key] if val.kind_of?(Array) && val.size == 2 addld(key, *val) end end if CONFIG["LDSHARED"] == "gcc -shared" CONFIG["LDSHARED"] = "g++ -shared" end if with_config("bdb-objs") bdb_obj = Dir["../src/*.#{$OBJEXT}"] if bdb_obj.size == 0 puts <<-EOT **************************************************** Build bdb first, if you want to link bdbxml with bdb **************************************************** EOT exit end $objs = ["bdbxml.o"] + bdb_obj $CFLAGS += " -DBDB_LINK_OBJ" end create_makefile('bdbxml') begin make = open("Makefile", "a") make.print <<-EOF %.html: %.rd \trd2 $< > ${<:%.rd=%.html} EOF make.print "HTML = bdbxml.html" docs = Dir['docs/*.rd'] docs.each {|x| make.print " \\\n\t#{x.sub(/\.rd$/, '.html')}" } make.print "\n\nRDOC = bdbxml.rd" docs.each {|x| make.print " \\\n\t#{x}" } make.puts make.print <<-EOF rdoc: docs/doc/index.html docs/doc/index.html: $(RDOC) \t@-(cd docs; rdoc .) ri: \t@-(rdoc -r docs/*rb) ri-site: \t@-(rdoc -R docs/*rb) rd2: html html: $(HTML) test: $(DLLIB) EOF Dir.glob('tests/*.rb') do |x| next if /(_\.rb|~)$/ =~ x next if FileTest.directory?(x) make.print "\t#{CONFIG['RUBY_INSTALL_NAME']} #{x}\n" end ensure make.close end ruby-bdb-0.6.6/bdbxml1/glossary/000077500000000000000000000000001154714021300164235ustar00rootroot00000000000000ruby-bdb-0.6.6/bdbxml1/glossary/README000066400000000000000000000004121154714021300173000ustar00rootroot00000000000000=begin = (()) Glossary # Original: by matz@zetabits.com (Yukihiro Matsumoto, aka matz) # English Translation: by matz himself and web-i31s@clio.ne.jp (SugHimsi) et alii. # First Release: 2000-12-25 # Last Retrieval: 2000-12-29 (Fixed some misspelling.) =end ruby-bdb-0.6.6/bdbxml1/glossary/abstract_data_type000066400000000000000000000007771154714021300222160ustar00rootroot00000000000000 Abstract Data Type encapsulation data A bunch of data structure and operation to the ((data|Data)) is called an abstract data type. The abstract data should not be operated unless passing this operation. As a result, it is not referred directly from the outside, and the change in an internal structure does not color the outside. This is called ((encapsulation|Encapsulation)). ruby-bdb-0.6.6/bdbxml1/glossary/associative_array000066400000000000000000000012251154714021300220560ustar00rootroot00000000000000 Associative Array hash Alias of ((hash|Hash)) It seems "Associative" is because the hash can take out the value of an arbitrary key, and "Array" is because you can assume it to be an array which the subscript is not number. Once upon a time, the associative array (called associative memory then) was thought to be realized with hardware, but improvement of hardware's calculation speed and discovery of an appropriate algorithm (it is called "((Hash)) table", derivation of the hash) brought us achievement only with software. ruby-bdb-0.6.6/bdbxml1/glossary/awk000066400000000000000000000003551154714021300171330ustar00rootroot00000000000000 AWK scripting language A small ((scripting language|Scripting Language)) by Alfred ((*A*))ho, Peter ((*W*))einberger, and Brian ((*K*))ernighan. ruby-bdb-0.6.6/bdbxml1/glossary/big_endian000066400000000000000000000012301154714021300204210ustar00rootroot00000000000000 Big Endian byte order data little endian The American Continent original inhabitants... are Indians. Here: ((*endian*)). The etymology is the people who eat the egg from a round edge, after Swift's "Gulliver's Travels." Naturally, the people who eat from a pointed edge are the (('Little' endian|Little Endian)). In the computer industry, it is one of the forms when CPU etc. arrange ((data|Data)). The networkers are said that they will like Big endian. See also "((byte order|Byte Order))." ruby-bdb-0.6.6/bdbxml1/glossary/block000066400000000000000000000002361154714021300174410ustar00rootroot00000000000000 Block The one to compose loop with, to build house and wall with, or to hit person with. ruby-bdb-0.6.6/bdbxml1/glossary/bug000066400000000000000000000001001154714021300171120ustar00rootroot00000000000000 Bug ruby-bdb-0.6.6/bdbxml1/glossary/built-in_class000066400000000000000000000014251154714021300212600ustar00rootroot00000000000000 Built-In Class object instance ruby data hash thread ((Ruby)) interpreter built-in class which the structure of ((instance|Instance)) is different from usual ((object|Object)). To define the class which inherits these classes is not recommended. A built-in class of ((Ruby)) is as follows: * Array * Bignum * Class * ((Data)) * FalseClass * File * Fixnum * Float * ((Hash)) * IO * ((MatchingData)) * Module * NilClass * Proc * Regexp * String * Struct * ((Thread)) * TrueClass ruby-bdb-0.6.6/bdbxml1/glossary/byte_order000066400000000000000000000007351154714021300205110ustar00rootroot00000000000000 Byte Order data big endian little endian Do you arrange four byte ((data|Data)) 0x1234 with 1, 2, 3, 4? or 4, 3, 2, 1? The former way is called ((Big Endian)), and the latter is called ((Little Endian)). The controversy which is good continues from the preliterate era and till now the conclusion has not been reached yet. ruby-bdb-0.6.6/bdbxml1/glossary/class000066400000000000000000000001021154714021300174440ustar00rootroot00000000000000 Class ruby-bdb-0.6.6/bdbxml1/glossary/class_method000066400000000000000000000007221154714021300210140ustar00rootroot00000000000000 Class Method self method ((Method)) of class. It is defined in class Class of all classes. Though there is a method which is common in all classes and a ((singleton method|Singleton Method)) which is proper to each class. that's not much of a problem. Do not misunderstand than '((|((self))|))' in the class method is a class. ruby-bdb-0.6.6/bdbxml1/glossary/coerce000066400000000000000000000012521154714021300176060ustar00rootroot00000000000000 Coerce instance method ruby ((Method)) of converting type of numerical value. The numeric calculation method is set on, when the ((instance|Instance)) which it doesn't know is passed as an argument, which the coerce method is used to convert it. The coerce method returns a pair of given (, and converted) value and itself (a converted value, if necessary), as its arguments. The converting order of numerical types of the library of ((Ruby)) is as follows: Fixnum -> Bignum -> Rational -> Float -> Complex ruby-bdb-0.6.6/bdbxml1/glossary/constant000066400000000000000000000003041154714021300201740ustar00rootroot00000000000000 Constant variable ((Variable)) which cannot change value once it is defined. ...Contradiction in terms? ruby-bdb-0.6.6/bdbxml1/glossary/data000066400000000000000000000010411154714021300172530ustar00rootroot00000000000000 Data function object ruby Wrapper to show pointer at C level as ((Ruby)) ((object|Object)). It is made of C pointer, the mark function, and the free function. The person who tries to add the ((function|Function)) to ((Ruby)) by C should master the usage of this class, by all means. Contrary to that, it is a class that have no business with a person whose schedule has no chance to try it. ruby-bdb-0.6.6/bdbxml1/glossary/defined?000066400000000000000000000010161154714021300200410ustar00rootroot00000000000000 defined? method ruby Operator to examine whether the various expression is actually defined. It returns the string to show the type of the expression if defined, and returns nil if not defined. While defined? looks like the ((method|Method)), it is the built-in operator of ((Ruby)), and it doesn't evaluate arguments. Therefore, there'll be no output with: defined? print("abc\n") ruby-bdb-0.6.6/bdbxml1/glossary/destructive000066400000000000000000000005261154714021300207120ustar00rootroot00000000000000 Destructive receiver method ((Method)) such as String#chop and Array#concat is said "It has destructive action", since they change the state of the ((receiver|Receiver)), though the hardware is seldom put out of order. ruby-bdb-0.6.6/bdbxml1/glossary/dictionary000066400000000000000000000011411154714021300205100ustar00rootroot00000000000000 Dictionary data paradigm object-oriented hash ruby The one that can take the definition out of the item. Changed to the alias of "((hash|Hash))." In ((Smalltalk)) (which can be called the origin of ((object-oriented|Object-Oriented)) ((paradigm|Paradigm)) the ((data|Data)) structure which corresponds to the hash was called "Dictionary." So there are specks of the crowd who are familiar with that term. ruby-bdb-0.6.6/bdbxml1/glossary/document000066400000000000000000000005431154714021300201660ustar00rootroot00000000000000 document bugs matz The one that ((matz)) is really bad at. He always says "the source itself should be the document. It even describes ((bugs|Bug)) perfectly." But no one agrees. This is the programmers' use and wont. Sigh. ruby-bdb-0.6.6/bdbxml1/glossary/dynamic_binding000066400000000000000000000012751154714021300214710ustar00rootroot00000000000000 Dynamic Binding variable paradigm object-oriented object data method ruby To select an appropriate procedure (((method|Method))) on the operation according to the ((data|Data)) type of its ((object|Object)). The flexibility of the program is effected to be improved. One of the requirements for ((object-oriented|Object-Oriented)) ((paradigm|Paradigm)). Dynamic binding is inevitable in ((Ruby)) because there is no type in the ((variable|Variable)). ruby-bdb-0.6.6/bdbxml1/glossary/eiffel000066400000000000000000000011131154714021300175740ustar00rootroot00000000000000 Eiffel block object-oriented programming ruby matz An ((object-oriented programming|Object-Oriented Programming)) language. Young ((matz)) has said to drop scales off his eyes by the book "Object-oriented Software Construction," written by the author of this language. Even so, ((Ruby)) doesn't look like Eiffel at all, except the ((block|Block)) end (with '((|((end))|))') and a reserved word '((|rescue|)).' ruby-bdb-0.6.6/bdbxml1/glossary/encapsulation000066400000000000000000000012001154714021300212040ustar00rootroot00000000000000 Encapsulation instance variable method data ruby To hide the algorithm of an internal structure and processing from outside, by the immediate operation to ((data|Data)) only from a specific procedure (called the ((method|Method))) which accompanies the type of data. See also "((Abstract Data Type))." In ((Ruby)) it can be said that encapsulation will be compelled since it is impossible to refer to the ((instance variable|Instance Variable)) from non-method. ruby-bdb-0.6.6/bdbxml1/glossary/end000066400000000000000000000040271154714021300171170ustar00rootroot00000000000000 end block bug ruby eiffel perl matz Reserved word to which ((block|Block)) structure is finished. According to a certain statistics, 33% of the person, who saw ((Ruby)) first sees this, associates Pascal. (...trust it?) However, this form which does not pair with '((|begin|))' is actually the neighbor of Ada or ((Eiffel)) rather than Pascal. ((Ruby)) do not to have offered to {} which had been accustomed and familiar with C and ((Perl)). It is from the following reasons: * Evasion of ambiguous simple / complex sentence problem For instance, in C, when you try to add a sentence on if (a==b) c(); and do as follows if (a==b) c(); d(); leads a confusing ((bug|Bug)). This problem exists also in Pascal. * Evasion of dangling 'else' problem It is similar to the situation above-mentioned. If you write if (a==b) if (c==d) foo(); else bar(); it becomes annoying. To tell the truth, what you really meant is: if (a==b) { if (c==d) foo(); else bar(); } * Improvement of readability There is a person who thinks that closing the ((block|Block)) in the word named 'end' is legible to program, though it is a debatable opinion. * Problems in sentence structure of '((|begin|))' and '((|case|))' Frankly speaking, ((matz)) have tried to use the ((variable|Variable)) 'end' several time only to have had a terrible time. Then, he examined to change to the grammar with {} for a time, but every time he abandoned it for the part of grammar of '((|begin|))' and '((|case|))' with no beauty. To tell the truth, this might be the first reason. ruby-bdb-0.6.6/bdbxml1/glossary/env000066400000000000000000000012051154714021300171340ustar00rootroot00000000000000 ENV environment variable singleton method instance ruby object hash ((Object)) which operates same as ((Hash)) to access ((environment variable|Environment Variable)). Actually it is an ((instance|Instance)) of the Object class which adds a ((singleton method|Singleton Method)). When the ((environment variable|Environment Variable)) is changed with this object, it is succeeded to the offspring process of ((Ruby)). ruby-bdb-0.6.6/bdbxml1/glossary/environment_variable000066400000000000000000000007271154714021300225650ustar00rootroot00000000000000 Environment Variable Value which is delivered from parent process to offspring process. It is accessed with ((|((ENV))|)). What is delivered to the offspring process is a copy of the environment ((variable|Variable)), so it is not possible to pass informations from the offspring process to the parent by using the environment variable. The parent will not listen to the child. ruby-bdb-0.6.6/bdbxml1/glossary/exception000066400000000000000000000013031154714021300203410ustar00rootroot00000000000000 Exception thread ruby The one occurs in exceptional situation. when it occurs, unless it is caught explicitly by '((|rescue|))' paragraph of '((|begin|))', the call hierarchy is traced back and the execution of program (((Thread))) is interrupted. The ((Ruby)) program should thank exception, because it is able to ((end)) without checking an exceptional situation one by one, in almost all of the case. The information on the place where the exception is generated is stored in ((|$@|)), and the information on the exception itself is stored in ((|$!|)). ruby-bdb-0.6.6/bdbxml1/glossary/faq000066400000000000000000000003361154714021300171170ustar00rootroot00000000000000 FAQ ruby ...And the compiled answers of them. ((Ruby)) FAQ is still developing now. Questions and answers are always welcome. ruby-bdb-0.6.6/bdbxml1/glossary/function000066400000000000000000000016771154714021300202060ustar00rootroot00000000000000 Function self module function receiver instance variable method ruby Strictly speaking, ((Ruby)) has no functions. But the appearance of a method call with ((receiver|Receiver)) left out is like a function, and furthermore, there is a ((method|Method)) which we can describe it as a virtual function, ((|((self))|)), ((instance variable|Instance Variable)), where no ((receiver|Receiver)) informations are referred. Such methods are sometimes, in a torelant situation, called functions. Mostly such function(al method)s' visibility is set to private, so that they could not be called in the form which ((receiver|Receiver)) is not omitted. The representative of that methods is ((module function|Module Function)). ruby-bdb-0.6.6/bdbxml1/glossary/global_variable000066400000000000000000000003241154714021300214520ustar00rootroot00000000000000 Global Variable variable ((Variable)) which can be referred to anywhere in the program. ((*Danger!*)) Overuse deadlock. ruby-bdb-0.6.6/bdbxml1/glossary/goto000066400000000000000000000007511154714021300173210ustar00rootroot00000000000000 goto exception ruby non-local exit One of which ((Ruby)) doesn't have. Why ((|goto|))'s absent is not for the policy "it should not be anywhere," but for the fact "it's troublesome in implementation." In place of ((|goto|)), ((|catch|))/((|throw|)) or the ((exception|Exception)) is used\ in ((Ruby)). See also "((Non-Local Exit))." ruby-bdb-0.6.6/bdbxml1/glossary/hash000066400000000000000000000007511154714021300172740ustar00rootroot00000000000000 Hash associative array dictionary ruby Data structure in ((Ruby)) which expresses the mapping from key to value. It is also called "((Associative Array))" or "((Dictionary))." The derivation of hash is the algorithm which is called "Hash table" in the achievement of the structure. The word 'hash' means "cut in pieces", of "hashed beef." ruby-bdb-0.6.6/bdbxml1/glossary/immediate_value000066400000000000000000000011601154714021300214760ustar00rootroot00000000000000 Immediate Value object reference variable ruby The one in ((variable|Variable)) that not ((reference|Reference)) but actual value is stored. Only '((|Fixnum|))' and ((|nil|))/((|true|))/((|false|)) are immediate values in present ((Ruby)). However, there's no law against another ((Ruby)) which ((|Fixnum|)) is not immediate value, and also you can regard the all values on the model as a ((reference|Reference)) to the ((object|Object)). ruby-bdb-0.6.6/bdbxml1/glossary/inheritance000066400000000000000000000014711154714021300206420ustar00rootroot00000000000000 Inheritance function mix-in Do minimum in itself, and fully rely on what succeeded from the ancestor or the relative to deal the rest matter. In the real world, It should be an unpleasant fellow. Turned to establish a new class which adds the ((function|Function)) to a certain class. Inheritance is effective to express the relation of is-a. For instance, "Student" class which describes the character of the general student can be succeeded to "Department of Engineering student (who is afflicted with the experiment)" class. When there is no is-a relation and the situation only shares the character and the function, it is assumed preferable to use ((Mix-in)). ruby-bdb-0.6.6/bdbxml1/glossary/initialize000066400000000000000000000013211154714021300205040ustar00rootroot00000000000000 Initialize block method object Put the ((object|Object)) (or "something") into "ready-to-use-it" state. The '((|initialize|))' ((method|Method)) should be redefined to initialize the ((instance|Instance)). The default definition of the method '((|new|))' of the class is to execute Initialize to the newly generated instance. The argument to ((|new|)) is tossed to initialize as it is. Moreover, when ((|new|)) is called with the ((block|Block)), the block is given to initialize as it is. This surely means Class#new is not to have to be redefined. ruby-bdb-0.6.6/bdbxml1/glossary/instance000066400000000000000000000007541154714021300201600ustar00rootroot00000000000000 Instance paradigm object-oriented object ((Object)) There seems to be a meaning to emphasize belonging to the class where the object exists. It is heard that there are a lot of people who have failed in ((object-oriented|Object-Oriented)) ((paradigm|Paradigm)) by confusing whether the one s/he touches is an object or an instance. ruby-bdb-0.6.6/bdbxml1/glossary/instance_variable000066400000000000000000000007201154714021300220160ustar00rootroot00000000000000 Instance Variable method instance object variable ruby Intrinsic ((variable|Variable)) to ((object|Object)). The ((instance|Instance)) variable of ((Ruby)) is the one that applies @ just before the identifier. It can be referred only from inside of the ((method|Method)). ruby-bdb-0.6.6/bdbxml1/glossary/iterator000066400000000000000000000017451154714021300202060ustar00rootroot00000000000000 Iterator block method Rehearser The group of a certain code which can be passed to the ((method|Method)) is called '((block|Block)).' Iterator is the method which the given block...this is surely the case. In general, the block is executed more than one time, so the method is called 'iterator' ("iterate" = repeat it); but there is a custom to call the case executing only once or not repeating, also iterator, insofar as the block is given to the method. Keep in mind, just the method have the 'repetition' as many as 0 or 1 time, do not call it liar, because it must be the 'repetition.' In the iterator, you can execute the block by '((|yield|)).' Ah, of course Nothing happens to the metho when the block is given of not evaluating the block internally. I wish you not to disappoint though the error does not occur either. ruby-bdb-0.6.6/bdbxml1/glossary/japanese_(language)000066400000000000000000000005101154714021300221140ustar00rootroot00000000000000 Japanese (language) documentation matz ruby Native language of ((matz)), the author of ((Ruby)). The cause of the poor ((documentation|document)) of ((Ruby)) (according to his excuse). ruby-bdb-0.6.6/bdbxml1/glossary/little_endian000066400000000000000000000006451154714021300211660ustar00rootroot00000000000000 Little Endian byte order data At first there're ten children and decreases one by one. In the computer industry, it is one of the forms when CPU etc. arrange ((data|Data)). A certain CPU maker with very big share is said that they will like Little endian. See also "((byte order|Byte Order))." ruby-bdb-0.6.6/bdbxml1/glossary/local_variable000066400000000000000000000013651154714021300213120ustar00rootroot00000000000000 Local Variable block ruby variable method ((Variable)) which can be referred only within a certain range. The range is called 'Scope'. The scope of ((Ruby)) is among: * The entire program * Class and module definition * ((Method)) definition * ((Block)) and only ((block|Block)) can access the local variable in the outside scope. An effective range of the local variable is from the place where the first substitution in scope appeared to an end of the scope. The effective range is fixed statically, and is unrelated whether actually executed. ruby-bdb-0.6.6/bdbxml1/glossary/main000066400000000000000000000010431154714021300172700ustar00rootroot00000000000000 main self singleton method instance object '((|((self))|))' at top level. Since it can't be without self, it is a mere ((instance|Instance)) of an ((Object)) class, only for being there. Some ((singleton methods|Singleton Method)) are defined to operate the Object class. Defined ((singleton method|Singleton Method)): * private * public * include ruby-bdb-0.6.6/bdbxml1/glossary/matchingdata000066400000000000000000000006351154714021300207760ustar00rootroot00000000000000 MatchingData object variable ((Object)) which shows state concerning match of regular expression. Value of ((variable|Variable)) ((|$~|)). When the value of this variable is changed, the value of variable group (((|$1|)),((|$2|))...,etc) concerning the regular expression changes, too. ruby-bdb-0.6.6/bdbxml1/glossary/matz000066400000000000000000000004211154714021300173160ustar00rootroot00000000000000 matz ruby ((Ruby))'s author His real name is 'Yukihiro Matsumoto.' If you say '((*You-Key-Hero Matz-motor*))' real quick, it sounds like his name. ('tz' as in 'waltz') ruby-bdb-0.6.6/bdbxml1/glossary/method000066400000000000000000000011211154714021300176210ustar00rootroot00000000000000 Method self built-in class receiver object ruby Operation to ((object|Object)). You can refer to the object ((receiver|Receiver)) to be operated with ((self)). In ((Ruby)), if you exclude the object of a ((built-in class|Built-In Class)), since the structure of the object is dynamically determined, the character of a certain object is determined by the method defined in the object. ruby-bdb-0.6.6/bdbxml1/glossary/mix-in000066400000000000000000000012621154714021300175500ustar00rootroot00000000000000 Mix-in function inheritance ruby matz To make a new taste mixing various one with the ice cream. Changed into mix the module with the class, and add the ((function|Function)). See also "((Inheritance))." Multiple ((inheritance|Inheritance)) is not adopted in ((Ruby)). Instead, the inheritance for the is-a relation, and Mix-in for sharing the ((function|Function)) is prepared. The purpose of this is the belief of ((matz)) that the relations should be in chaos when multiple inheritance is abused. ruby-bdb-0.6.6/bdbxml1/glossary/module_function000066400000000000000000000011531154714021300215400ustar00rootroot00000000000000 Module Function singleton method function method In the ((methods|Method)) which is used like ((function|Function)). the one defined both as a method of the module and a ((singleton method|Singleton Method)) is called module function. For instance, most methods of the ((|Math|)) module are the module functions. These methods is convenient because it can be used both in the form(for example):: Math.sqrt(2) and include Math sqrt(2) ruby-bdb-0.6.6/bdbxml1/glossary/non-local_exit000066400000000000000000000020171154714021300212610ustar00rootroot00000000000000 Non-Local Exit object bug exception method ruby Non-local exit (or global exit) is not an escape within the ranges of the ((methods|Method)) such as ((|break|)), ((|next|)), ((|redo|)), ((|retry|)), and ((|return|)), but the type which interrupts going back the hierarchy of the method call as long as it's not caught. In ((Ruby)) there are two way: by ((exception|Exception)), or ((|catch|))/((|throw|)). Almost all exceptions can be caught with '((|rescue|))' (including ((|SystemExit|)) generated by exit), but the exception not significant to catching (example: Fail in memory allocation/interpreter's ((bug|Bug)) does not become the ((object|Object)) to catch. ((|catch|))/((|throw|)) is the one which, when '((|throw|))' is done, jumps at a dash to catch with the same tag as the tag specified. ruby-bdb-0.6.6/bdbxml1/glossary/object000066400000000000000000000012771154714021300176230ustar00rootroot00000000000000 Object awk paradigm object-oriented encapsulation abstract data type A thing. The matter. Love, perhaps, is not an object, but love letter is an object. Whether something is an object or not strongly depends on YOUR philosophy. Might the cause that ((object-oriented|Object-Oriented)) ((paradigm|Paradigm)) is difficult. Someone in the computer industry calls a specific space in computer memory as 'object.' ((Awk|AWK))ward guys... See also "((Encapsulation))," and "((Abstract Data Type))." ruby-bdb-0.6.6/bdbxml1/glossary/object-oriented000066400000000000000000000017321154714021300214260ustar00rootroot00000000000000 Object-Oriented paradigm object japanese inheritance encapsulation polymorphism dynamic binding ((In Japanese|Japanese (language))), an adjective "Object-Oriented" has transcolored to an abstract noun, which means "the ((object|Object))-based ((paradigm|Paradigm))." Any kind of view looks OK at first as long as the object is the central concept, but in general, it seems that the ((paradigm|Paradigm)) needs * ((Inheritance)), * ((Encapsulation)), * and ((Polymorphism)) (or ((Dynamic Binding))). Someone deals it as a wild card or a kind of magic, but our life has a lot more. Twenty-odd years since the dawn, through all our fortunes, there comes to be a first stage of pragmatic use...perhaps...agreed? ruby-bdb-0.6.6/bdbxml1/glossary/object-oriented_analysis000066400000000000000000000002571154714021300233320ustar00rootroot00000000000000 Object-Oriented Analysis object System analysis based on ((object|Object)). ((*OOA*)). ruby-bdb-0.6.6/bdbxml1/glossary/object-oriented_design000066400000000000000000000002531154714021300227540ustar00rootroot00000000000000 Object-Oriented Design object System design based on ((object|Object)). ((*OOD*)). ruby-bdb-0.6.6/bdbxml1/glossary/object-oriented_programming000066400000000000000000000002561154714021300240300ustar00rootroot00000000000000 Object-Oriented Programming object Programming based on ((object|Object)). ((*OOP*)). ruby-bdb-0.6.6/bdbxml1/glossary/override000066400000000000000000000006031154714021300201640ustar00rootroot00000000000000 Override method super redefinition ((Redefinition)). Define a ((method|Method)) same name as the one defined on the super class or included method. In overridden method, '((|((super))|))' can invoke the superior method with same name. ruby-bdb-0.6.6/bdbxml1/glossary/paradigm000066400000000000000000000002351154714021300201320ustar00rootroot00000000000000 Paradigm An affected expression of a 'view.' You tame could use the plain word instead. ruby-bdb-0.6.6/bdbxml1/glossary/perl000066400000000000000000000001551154714021300173110ustar00rootroot00000000000000 Perl Hmm.. Sounds familiar. What was that? ruby-bdb-0.6.6/bdbxml1/glossary/polymorphism000066400000000000000000000010471154714021300211120ustar00rootroot00000000000000 Polymorphism receiver method object ruby To define actual operation as to an ((object|Object)). ((Ruby)) carries it out to choose the ((method|Method) according to the object of the ((receiver|Receiver)). : Example: obj = "abc" print obj.length, "\n" # => 3 obj = [1,2,3,4] print obj.length, "\n" # => 4 ruby-bdb-0.6.6/bdbxml1/glossary/python000066400000000000000000000006631154714021300176740ustar00rootroot00000000000000 Python object-oriented programming ruby matz An ((object-oriented programming|Object-Oriented Programming)) language. ((Ruby))'s rival. "An elapsed serpent." If ((matz)) was content with Python, ((Ruby)) wouldn't be born now. Anxious most is length of the name. (Up to 6 characters!) ruby-bdb-0.6.6/bdbxml1/glossary/receiver000066400000000000000000000010041154714021300201450ustar00rootroot00000000000000 Receiver self variable instance variable method Operational subject of the ((method|Method)). It is on the left of '((|.|))' or '((|::|))' of method call expression. In a method, it can be referred as '((|((self))|)).' The ((instance variable|Instance Variable)) of the receiver is accessible in the form '((|@|))((variable|Variable))_name.' ruby-bdb-0.6.6/bdbxml1/glossary/redefinition000066400000000000000000000002051154714021300210220ustar00rootroot00000000000000 Redefinition override ((Override)). Rewrite. ruby-bdb-0.6.6/bdbxml1/glossary/reference000066400000000000000000000001341154714021300203020ustar00rootroot00000000000000 Reference See also foobar. ruby-bdb-0.6.6/bdbxml1/glossary/ruby000066400000000000000000000007351154714021300173340ustar00rootroot00000000000000 Ruby scripting language object-oriented perl The name of the ((object-oriented|Object-Oriented)) ((scripting language|Scripting Language)) and its interpreter. The name 'ruby' is not an acronym. It's named after the red precious stone, which is the birthsone of July. Notice pearl(((Perl))) is the birthstone of June. ruby-bdb-0.6.6/bdbxml1/glossary/sather000066400000000000000000000006141154714021300176350ustar00rootroot00000000000000 Sather matz object-oriented programming eiffel ruby An ((object-oriented programming|Object-Oriented Programming)) language. ((Matz|matz)) likes Sather rather than ((Eiffel)). But Sather doesn't look like ((Ruby)) at all, either. ruby-bdb-0.6.6/bdbxml1/glossary/script000066400000000000000000000003101154714021300176440ustar00rootroot00000000000000 Script Scenario Turned into a relatively short program where the interpreter works on. Of course there's a super-masterpiece. ruby-bdb-0.6.6/bdbxml1/glossary/scripting_language000066400000000000000000000004011154714021300222060ustar00rootroot00000000000000 Scripting Language script Interpreter which handles batch operations after the ((script|Script)). Man is also a scripting language on the point which reads script. ruby-bdb-0.6.6/bdbxml1/glossary/self000066400000000000000000000010001154714021300172660ustar00rootroot00000000000000 self method receiver smalltalk Expression which refers to ((receiver|Receiver)). Why it's called '((|self|))'? By one account, the ((receiver|Receiver)) is the subject of the sentence where ((method|Method)) is the verb, so from the method's standpoint it's itself, though it is strongly suspected that it's the mimic of ((Smalltalk)) without deep account. ruby-bdb-0.6.6/bdbxml1/glossary/singleton_class000066400000000000000000000002501154714021300215320ustar00rootroot00000000000000 Singleton Class object Virtual class only for the particular ((object|Object)). ruby-bdb-0.6.6/bdbxml1/glossary/singleton_method000066400000000000000000000010001154714021300216770ustar00rootroot00000000000000 Singleton Method override object method ((Method)) which is defined only for the particular ((object|Object)). Singleton method can be succeeded to other method(s) in the following case: * Cloned. * Made subclass(es). When the singleton method ((overrides|Override)) the original method, the original method can be invoked to appear by '((|((super))|))'. ruby-bdb-0.6.6/bdbxml1/glossary/smalltalk000066400000000000000000000006071154714021300203350ustar00rootroot00000000000000 Smalltalk object-oriented paradigm object-oriented programming An ((object-oriented programming|Object-Oriented Programming)) language, which laid the groundwork of the ((paradigm|Paradigm)) to this day, '((object-oriented|Object-Oriented))' style. ruby-bdb-0.6.6/bdbxml1/glossary/sort000066400000000000000000000005001154714021300173300ustar00rootroot00000000000000 Sort ruby To arrange in order ((Ruby)) can sort anything, not only array, however complex, if only * they're countable (((|Enumerable|)) is included), * and the order is (i.e. ((|<=>|)) is) defined in each element. ruby-bdb-0.6.6/bdbxml1/glossary/super000066400000000000000000000013271154714021300175070ustar00rootroot00000000000000 super variable overridde method Technique to call upper level ((method|Method)) from ((overridden|Override)) method. When argument is omitted, super'ed slave can be called by the same argument as that of the master's method. : Question: If you change the value of ((variable|Variable)) given as an argument, which 'super' gets, the original value, or the changed? def foo(a) print a end def self.foo(a) a=25 super end foo(5) # 5 or 25? : Answer the original one(((%5%))) ruby-bdb-0.6.6/bdbxml1/glossary/thread000066400000000000000000000003471154714021300176210ustar00rootroot00000000000000 Thread ruby ((*Thread of control*)), in original; a chain of control processes. In ((Ruby)), more than one thread can exist in a program. ruby-bdb-0.6.6/bdbxml1/glossary/undef000066400000000000000000000010451154714021300174470ustar00rootroot00000000000000 undef inheritance method mix-in To set the ((method|Method)) undefined. '((|undef|))' means that the particular method can be obviated, while ((inheritance|Inheritance)) or ((Mix-in)) just adds class on the method. However, you'll pay for the lack of prudence when you '((|undef|))' the method which is called from inside of the method, which is crucial to the implementation of the class. ruby-bdb-0.6.6/bdbxml1/glossary/variable000066400000000000000000000010321154714021300201270ustar00rootroot00000000000000 Variable local variable global variable instance variable object constant A tag attached to an ((object|Object)). ((Ruby)) has ((global|Global Variable)), ((local|Local Variable)), class, and ((instance|Instance Variable)) variables. ((Constant)) has the same implication of tag, though it's not variable, since its value cannot be changed. ruby-bdb-0.6.6/bdbxml1/myconfig000066400000000000000000000011561154714021300163210ustar00rootroot00000000000000# directories for cpp $base = "/home/ts/local" $include = { 'db' => "#{$base}/db4.2.52/include", 'dbxml' => "#{$base}/dbxml1.2/include", 'xercesc' => "#{$base}/xercesc/include" } # [directory, library] for ld # it's important to have xercesc compiled with -rnone # (i.e. *without* threads) $library = { 'db' => ["#{$base}/db4.2.52/lib", ["db-4.2", "db_cxx-4.2"]], 'dbxml' => ["#{$base}/dbxml1.2/lib", "dbxml-1.2"], 'pathan' => ["#{$base}/pathan/lib", "pathan"], 'xercesc' => ["#{$base}/xercesc/lib", "xerces-c"] } # order for ld (don't change it) $order = ['dbxml', 'db', 'pathan', 'xercesc'] ruby-bdb-0.6.6/bdbxml1/tests/000077500000000000000000000000001154714021300157225ustar00rootroot00000000000000ruby-bdb-0.6.6/bdbxml1/tests/data.e000066400000000000000000000023421154714021300170020ustar00rootroot00000000000000# Content # BDB::XML::Modify.new("/root",BDB::XML::Modify::InsertBefore,BDB::XML::Modify::Element,"new","") BDB::XML::Modify.new("/root",BDB::XML::Modify::InsertAfter,BDB::XML::Modify::Element,"new","") BDB::XML::Modify.new("/root",BDB::XML::Modify::Remove,BDB::XML::Modify::None,"","") BDB::XML::Modify.new("/root",BDB::XML::Modify::Append,BDB::XML::Modify::Attribute,"","val") BDB::XML::Modify.new("/root",BDB::XML::Modify::Append,BDB::XML::Modify::Attribute,"name","") BDB::XML::Modify.new("/root",BDB::XML::Modify::Append,BDB::XML::Modify::Element,"","val") # Content a contentb content 1 b content 2 # BDB::XML::Modify.new("/root/a/@att1",BDB::XML::Modify::Append,BDB::XML::Modify::Attribute,"name","val") BDB::XML::Modify.new("/root/comment()",BDB::XML::Modify::Append,BDB::XML::Modify::Attribute,"name","val") BDB::XML::Modify.new("/root/a/@att1",BDB::XML::Modify::Append,BDB::XML::Modify::Element,"name","val") BDB::XML::Modify.new("/root/comment()",BDB::XML::Modify::Append,BDB::XML::Modify::Element,"name","val") ruby-bdb-0.6.6/bdbxml1/tests/data.t000066400000000000000000000132671154714021300170310ustar00rootroot00000000000000# Content : an empty root element # # # BDB::XML::Modify.new("/root",BDB::XML::Modify::Append,BDB::XML::Modify::Element,"new","new content") # new content # # BDB::XML::Modify.new("/root",BDB::XML::Modify::Append,BDB::XML::Modify::Attribute,"new","foo") # # # BDB::XML::Modify.new("/root",BDB::XML::Modify::Append,BDB::XML::Modify::PI,"newPI","PIcontent") # # # BDB::XML::Modify.new("/root",BDB::XML::Modify::Append,BDB::XML::Modify::Comment,"","comment content") # # # BDB::XML::Modify.new("/root",BDB::XML::Modify::Append,BDB::XML::Modify::Text,"","text content") # text content # # Content : a little structure. # a content b content 1 b content 2 # # BDB::XML::Modify.new("/root/b/@att1",BDB::XML::Modify::Remove,BDB::XML::Modify::None) # a content b content 1b content 2 # # BDB::XML::Modify.new("/root/b[text()='b content 2']",BDB::XML::Modify::Remove,BDB::XML::Modify::None) # a content b content 1 # # BDB::XML::Modify.new("/root/comment()",BDB::XML::Modify::Remove,BDB::XML::Modify::None) # a content b content 1 b content 2 # # BDB::XML::Modify.new("/root/a/text()",BDB::XML::Modify::Remove,BDB::XML::Modify::None) # b content 1 b content 2 # # BDB::XML::Modify.new("/root",BDB::XML::Modify::Append,BDB::XML::Modify::Element,"new") # a content b content 1 b content 2 # # BDB::XML::Modify.new("/root",BDB::XML::Modify::Append,BDB::XML::Modify::Element,"new","",0) # a content b content 1 b content 2 # # BDB::XML::Modify.new("/root",BDB::XML::Modify::Append,BDB::XML::Modify::Element,"new","",2) # a content b content 1 b content 2 # # BDB::XML::Modify.new("/root/a",BDB::XML::Modify::InsertBefore,BDB::XML::Modify::Element,"new") # a content b content 1 b content 2 # # BDB::XML::Modify.new("/root/a",BDB::XML::Modify::InsertAfter,BDB::XML::Modify::Element,"new") # a content b content 1 b content 2 # # BDB::XML::Modify.new("/root/a",BDB::XML::Modify::Rename,BDB::XML::Modify::None,"x") # a content b content 1 b content 2 # # BDB::XML::Modify.new("/root/a/@att1",BDB::XML::Modify::Rename,BDB::XML::Modify::None,"att2") # a content b content 1 b content 2 # # Content test update # a content 1a content 2 b content 1 # # BDB::XML::Modify.new("/root/comment()",BDB::XML::Modify::Update,BDB::XML::Modify::None,"","new comment") # a content 1a content 2 b content 1 # # BDB::XML::Modify.new("/root/a",BDB::XML::Modify::Update,BDB::XML::Modify::None,"","new a text") # new a text b content 1 # # BDB::XML::Modify.new("/root/a",BDB::XML::Modify::Update,BDB::XML::Modify::None) # b content 1 # # BDB::XML::Modify.new("/root",BDB::XML::Modify::Update,BDB::XML::Modify::None,"","new root text") a content 1a content 2 b content 1 new root text # # BDB::XML::Modify.new("/root/b",BDB::XML::Modify::Update,BDB::XML::Modify::None,"","new b text") # a content 1a content 2 new b text # ruby-bdb-0.6.6/bdbxml1/tests/runit_.rb000066400000000000000000000012441154714021300175500ustar00rootroot00000000000000begin require 'test/unit' rescue LoadError require 'runit/testcase' require 'runit/cui/testrunner' module RUNIT module Assert def assert_raises(error, message = nil) begin yield rescue error assert(true, message) rescue assert_fail("must fail with #{error} : #{string}") else assert_fail("*must* fail : #{string}") end end end end end if RUBY_VERSION > "1.7" class Array alias indices select end class Hash alias indexes select end module BDB class Common alias indexes select end class Recnum alias indices select end end end ruby-bdb-0.6.6/bdbxml1/tests/xml.rb000077500000000000000000000146221154714021300170570ustar00rootroot00000000000000#!/usr/bin/ruby $LOAD_PATH.unshift *%w{../src . tests} $dir = Dir.pwd def clean Dir.foreach('tmp') do |x| if FileTest.file?("tmp/#{x}") File.unlink("tmp/#{x}") end end end at_exit do Dir.chdir($dir) clean() end require 'bdbxml' require 'runit_' $glo, $bdb, $env = nil, nil, nil $time = Time.now.to_s $reference = {"matz" => [], "object" => [], "ruby" => []} clean puts "\nVERSION of BDB is #{BDB::VERSION}\n" puts "\nVERSION of BDB::XML is #{BDB::XML::VERSION}\n" Inh = defined?(RUNIT) ? RUNIT : Test::Unit class TestXML < Inh::TestCase def test_00_env @flag ||= BDB::INIT_LOMP assert_kind_of(BDB::Env, $env = BDB::Env.new("tmp", BDB::CREATE | @flag)) assert_kind_of(BDB::XML::Container, $glo = $env.open_xml("glossary", "a")) assert_kind_of(BDB::XML::Index, index = $glo.index) $glo.index = [["http://moulon.inra.fr/", "reference", "node-attribute-equality-string"]] assert_equal("glossary", $glo.name) $base = "." end def test_01_doc $id, $names = [], [] @mask ||= "[a-z]" Dir["#{$base}/glossary/#{@mask}*"].each do |file| assert_kind_of(BDB::XML::Document, a = BDB::XML::Document.new) content = IO.readlines(file, nil)[0] $reference.each do |k, v| if content.index("reference>#{k}") v << file end end assert_equal(content, a.content = content) assert_equal(file, a.name = file) assert_equal($time, a['time'] = $time) $id << [file, $glo.push(a)] $names << file end end def test_02_each $id.each do |file, ind| assert_kind_of(BDB::XML::Document, doc = $glo[ind]) assert_equal(file, doc.name) content = IO.readlines(doc.name, nil)[0] assert_equal(content, doc.content) assert_equal(content, doc.to_s) assert_equal($time, doc['time']) assert_equal($time, doc.get(nil, 'time', String)) end end def test_03_search names = [] $glo.search("//*") {|doc| names << [doc.name, doc.id] } assert_equal($id.sort, names.sort) names = $glo.collect {|doc| [doc.name, doc.id] } assert_equal($id.sort, names.sort) names = $glo.query("//*").collect {|doc| [doc.name, doc.id] } assert_equal($id.sort, names.sort) names = $glo.query($glo.parse("//*")).collect {|doc| [doc.name, doc.id] } assert_equal($id.sort, names.sort) end def test_04_query $reference.each do |k, v| query = $glo.query("/entry[reference[contains(text(), '#{k}')]]") file = query.collect {|doc| doc.name} assert_equal(v.sort, file.sort) end end def test_05_names assert_kind_of(BDB::XML::Results, query = $glo.query("//*")) file = query.collect{|name| name.name} names = $id.collect{|id| id[0]} assert_equal(names.sort, file.sort) ids = [] $glo.search("//*") {|i| ids << i.id} id = $id.collect{|id| id[1]} assert_equal(ids.sort, id.sort) end def test_06_dump assert_equal(nil, $glo.close) assert_equal(nil, $env.close) assert_equal(nil, BDB::XML::Container.dump("tmp/glossary", "tmp/dumpee")) assert_equal(nil, BDB::XML::Container.load("tmp/glossary", "tmp/dumpee")) assert_equal(nil, BDB::XML::Container.remove("tmp/glossary")) end def test_07_reinit @flag = BDB::INIT_TRANSACTION @mask = "[a-m]" $reference = {"matz" => [], "object" => [], "ruby" => []} clean test_00_env test_01_doc test_04_query end def test_08_transaction old_ref = {} $reference.each{|k,v| old_ref[k] = v.dup} old_glo = $glo $env.begin($glo) do |txn, $glo| @mask = "[n-z]" test_01_doc test_04_query end $glo, $reference = old_glo, old_ref test_04_query $env.begin($glo) do |txn, $glo| @mask = "[n-z]" test_01_doc test_04_query txn.commit end $glo = old_glo test_04_query end def test_09_single $glo.close $env.close clean begin Dir.chdir('tmp') $base = ".." $reference.each {|k,v| v.clear} assert_kind_of(BDB::XML::Container, $glo = BDB::XML::Container.new("glossary", "a")) test_01_doc test_02_each test_03_search test_04_query ensure Dir.chdir("..") end end def expr_modify(content, expression, result) assert_kind_of(BDB::XML::Document, xml = BDB::XML::Document.new(content)) assert_kind_of(BDB::XML::Modify, modify = eval(expression)) assert_equal(xml, xml.modify(modify)) assert_equal(result, xml.to_s, "") end def test_10_modify return if !defined?(BDB::XML::Modify) $glo.close clean data = File.new('tests/data.t') begin expression, content, result = nil, nil, nil while line = data.gets next if /\A#\s*\z/ =~ line || /\A\s*\z/ =~ line if /\A#\s*Content/i =~ line while line = data.gets next if /\A#\s*\z/ =~ line break end content = line while line = data.gets break if /\A#\s*\z/ =~ line content << line end content.gsub!(/\n/, '') end if /\A#\s*BDB::XML::Modify/ =~ line expression = line.gsub(/\A#\s*/, '') while line = data.gets next if /\A#\s*\z/ =~ line break end result = line while line = data.gets break if /\A#\s*\z/ =~ line result << line end result.gsub!(/\n/, '') end if result expr_modify(content, expression, result) result = nil end end ensure data.close end end def expr_modify_error(content, expression) assert_kind_of(BDB::XML::Document, xml = BDB::XML::Document.new(content)) assert_kind_of(BDB::XML::Modify, modify = eval(expression)) assert_raises(BDB::Fatal) { xml.modify(modify) } end def test_11_modify_error return if !defined?(BDB::XML::Modify) data = File.new('tests/data.e') begin content = nil while line = data.gets next if /\A#\s*\z/ =~ line || /\A\s*\z/ =~ line if /\A#\s*Content/i =~ line while line = data.gets next if /\A#\s*\z/ =~ line break end content = line while line = data.gets break if /\A#\s*\z/ =~ line content << line end content.gsub!(/\n/, '') end next if /\A#/ =~ line || /\A\s*\z/ =~ line expr_modify_error(content, line.chomp) end ensure data.close end end end if defined?(RUNIT) RUNIT::CUI::TestRunner.run(TestXML.suite) end ruby-bdb-0.6.6/bdbxml2/000077500000000000000000000000001154714021300145615ustar00rootroot00000000000000ruby-bdb-0.6.6/bdbxml2/Changes000066400000000000000000000002231154714021300160510ustar00rootroot00000000000000 * bdb must now be compiled with --enable-db-xml * Fix a memory leak for transaction (thanks Alfons Hoogervorst ) ruby-bdb-0.6.6/bdbxml2/README.en000066400000000000000000000022511154714021300160420ustar00rootroot00000000000000 This is an interface to Berkeley DB XML, distributed by Sleepycat (http://www.sleepycat.com/products/xml.shtml) * Installation .... first build bdb which is in '../src', and use this version of bdb for use with bdbxml IMPORTANT : use --enable-db-xml ruby extconf.rb --enable-db-xml ... .... choose one of myconfig-2.2, myconfig-2.3 and copy it in myconfig modify './myconfig' to adapt it to your configuration IMPORTANT FOR dbxml 2.2 : you must use a version of xercesc compiled *without* threads .... Comment in extconf.rb the line VERIFY 'myconfig' then comment this line .... This version must be used with [ >= db-4.3.*, DbXml 2.*] .... ruby extconf.rb make make install .... if you want to make a shared version which use the object files from ../src, specify the flag --with-bdb-objs when you run extconf.rb ruby extconf.rb --with-bdb-objs make make install * Documentation : make rd2 make rdoc * Copying This extension module is copyrighted free software by Guy Decoux You can redistribute it and/or modify it under the same term as Ruby. Guy Decoux ruby-bdb-0.6.6/bdbxml2/bdbxml.cc000066400000000000000000005144521154714021300163530ustar00rootroot00000000000000#include "bdbxml.h" static VALUE xb_cEnv, xb_cRes, xb_cQue, xb_cMan; static VALUE xb_cInd, xb_cUpd, xb_cMod, xb_cVal; static VALUE xb_cCon, xb_cDoc, xb_cCxt, xb_mObs; #if HAVE_DBXML_XML_INDEX_LOOKUP static VALUE xb_cLook; #endif #if HAVE_DBXML_XML_EVENT_WRITER static VALUE xb_cEwr; #endif #if HAVE_DBXML_XML_EVENT_READER static VALUE xb_cErd; #endif static VALUE xb_io; static ID id_current_env, id_close, id_read, id_write, id_pos; #if 0 #define FREE_DEBUG(a, ...) fprintf(stderr, a, ##__VA_ARGS__) #else #define FREE_DEBUG(a, ...) #endif static void xb_val_mark(xval *val); static void xb_val_free(xval *val); static XmlValue xb_val_xml(VALUE); static void xb_io_push(VALUE obj) { if (TYPE(xb_io) == T_ARRAY) { rb_ary_push(xb_io, obj); } } static void xb_io_delete(VALUE obj, bool to_close) { if (TYPE(xb_io) == T_ARRAY) { for (int i = 0; i < RARRAY_LEN(xb_io); i++) { if (RARRAY_PTR(xb_io)[i] == obj) { rb_ary_delete_at(xb_io, i); break; } } } if (to_close) { rb_funcall2(obj, id_close, 0, 0); } } namespace std { class xbWrite : public streambuf { public: xbWrite(VALUE obj, bool to_close):obj_(obj),close_(to_close) { xb_io_push(obj); } ~xbWrite() { sync(); xb_io_delete(obj_, close_); } protected: int_type overflow(int c) { if (c != traits_type::eof()) { buf_ += c; if (c == '\n') { flush_line(); } } return c; } int sync() { if (!buf_.empty()) { flush_line(); } return 0; } private: VALUE obj_; string buf_; bool close_; void flush_line() { VALUE str = rb_str_new2(buf_.c_str()); buf_.clear(); rb_funcall(obj_, id_write, 1, str); } }; class xbRead : public streambuf { public: xbRead(VALUE obj, bool to_close):obj_(obj),close_(to_close), eof_(false) { xb_io_push(obj); } ~xbRead() { xb_io_delete(obj_, close_); } protected: int_type underflow() { if (gptr() < egptr()) return(traits_type::to_int_type(*gptr())); if (eof_) return traits_type::eof(); VALUE str = rb_funcall(obj_, id_read, 1, INT2NUM(1024)); if (NIL_P(str)) { eof_ = true; return traits_type::eof(); } char *ptr = StringValuePtr(str); MEMCPY(buff_, ptr, char, RSTRING(str)->len); setg(buff_, buff_, buff_ + RSTRING(str)->len); return(traits_type::to_int_type(*gptr())); } private: VALUE obj_; bool close_, eof_; char buff_[1024]; }; } #include "dbxml/XmlInputStream.hpp" class xbInput : public XmlInputStream { public: xbInput(const VALUE obj):pos_(false),obj_(obj) { if (rb_respond_to(obj, id_pos)) { pos_ = true; } xb_io_push(obj); } ~xbInput() { xb_io_delete(obj_, false); } xbInput(const xbInput &); unsigned int curPos() const { if (pos_) { VALUE count = rb_funcall(obj_, id_pos, 0, 0); return NUM2ULONG(count); } return 0; } unsigned int readBytes(char* const fill, const unsigned int maxr) { VALUE line = rb_funcall(obj_, id_read, 1, INT2NUM(maxr)); if (NIL_P(line)) return 0; char *str = StringValuePtr(line); MEMCPY(fill, str, char, RSTRING(line)->len); return RSTRING(line)->len; } private: bool pos_; VALUE obj_; }; class XbResolve : public XmlResolver { public: XbResolve(VALUE man, VALUE obj):man_(man),obj_(obj) {} ~XbResolve() {} virtual bool resolveCollection(XmlTransaction *xmltxn, XmlManager &xmlman, const std::string &xmluri, XmlResults &xmlresult) const { if (!rb_respond_to(obj_, rb_intern("resolve_collection"))) { return false; } VALUE uri = rb_tainted_str_new2(xmluri.c_str()); VALUE obj = retrieve_txn(xmltxn); VALUE rep = rb_funcall(obj_, rb_intern("resolve_collection"), 2, obj, uri); if (NIL_P(rep)) { return false; } if (TYPE(rep) == T_DATA && RDATA(rep)->dfree == (RDF)xb_res_free) { xres *res = get_res(rep); xmlresult = XmlResults(*res->res); return true; } else { rb_raise(rb_eArgError, "object must an XML::Results"); } return false; } virtual bool resolveDocument(XmlTransaction *xmltxn, XmlManager &xmlman, const std::string &xmluri, XmlValue &xmlval) const { if (!rb_respond_to(obj_, rb_intern("resolve_document"))) { return false; } VALUE uri = rb_tainted_str_new2(xmluri.c_str()); VALUE obj = retrieve_txn(xmltxn); VALUE rep = rb_funcall(obj_, rb_intern("resolve_document"), 2, obj, uri); if (NIL_P(rep)) { return false; } xmlval = xb_val_xml(rep); return true; } virtual XmlInputStream * resolveEntity(XmlTransaction *xmltxn, XmlManager &xmlman, const std::string &xmlsys, const std::string &xmlpub) const { if (!rb_respond_to(obj_, rb_intern("resolve_entity"))) { return NULL; } VALUE sys = rb_tainted_str_new2(xmlsys.c_str()); VALUE pub = rb_tainted_str_new2(xmlpub.c_str()); VALUE obj = retrieve_txn(xmltxn); VALUE res = rb_funcall(obj_, rb_intern("resolve_entity"), 3, obj, sys, pub); if (NIL_P(res)) { return NULL; } if (!rb_respond_to(res, id_read)) { rb_raise(rb_eArgError, "object must respond to #read"); } return new xbInput(res); } virtual XmlInputStream * resolveSchema(XmlTransaction *xmltxn, XmlManager &xmlman, const std::string &xmlschema, const std::string &xmlname) const { if (!rb_respond_to(obj_, rb_intern("resolve_schema"))) { return NULL; } VALUE schema = rb_tainted_str_new2(xmlschema.c_str()); VALUE name = rb_tainted_str_new2(xmlname.c_str()); VALUE obj = retrieve_txn(xmltxn); VALUE res = rb_funcall(obj_, rb_intern("resolve_schema"), 3, obj, schema, name); if (NIL_P(res)) { return NULL; } if (!rb_respond_to(res, id_read)) { rb_raise(rb_eArgError, "object must respond to #read"); } return new xbInput(res); } virtual XmlInputStream * resolveModule(XmlTransaction *xmltxn, XmlManager &xmlman, const std::string &xmlmodule, const std::string &xmlname) const { if (!rb_respond_to(obj_, rb_intern("resolve_module"))) { return NULL; } VALUE module = rb_tainted_str_new2(xmlmodule.c_str()); VALUE name = rb_tainted_str_new2(xmlname.c_str()); VALUE obj = retrieve_txn(xmltxn); VALUE res = rb_funcall(obj_, rb_intern("resolve_module"), 3, obj, module, name); if (NIL_P(res)) { return NULL; } if (!rb_respond_to(res, id_read)) { rb_raise(rb_eArgError, "object must respond to #read"); } return new xbInput(res); } virtual bool resolveModuleLocation(XmlTransaction *xmltxn, XmlManager &xmlman, const std::string &xmlname, XmlResults &xmlresult) const { if (!rb_respond_to(obj_, rb_intern("resolve_module_location"))) { return false; } VALUE name = rb_tainted_str_new2(xmlname.c_str()); VALUE obj = retrieve_txn(xmltxn); VALUE rep = rb_funcall(obj_, rb_intern("resolve_collection"), 2, obj, name); if (NIL_P(rep)) { return false; } if (TYPE(rep) == T_DATA && RDATA(rep)->dfree == (RDF)xb_res_free) { xres *res = get_res(rep); xmlresult = XmlResults(*res->res); return true; } else { rb_raise(rb_eArgError, "object must an XML::Results"); } return false; } private: VALUE man_; VALUE obj_; VALUE retrieve_txn(XmlTransaction *xmltxn) const { if (xmltxn == 0) return man_; xman *man = get_man(man_); bdb_ENV *envst; GetEnvDBErr(man->env, envst, id_current_env, xb_eFatal); if (!envst->db_ary.ptr) return man_; VALUE obj; for (int i = 0; i < envst->db_ary.len; i++) { obj = envst->db_ary.ptr[i]; if (rb_obj_is_kind_of(obj, xb_cTxn)) { bdb_TXN *txnst; GetTxnDBErr(obj, txnst, xb_eFatal); if (xmltxn == (XmlTransaction *)txnst->txn_cxx) { return obj; } } } return man_; } }; static VALUE xb_s_new(int argc, VALUE *argv, VALUE obj) { VALUE res = rb_funcall2(obj, rb_intern("allocate"), 0, 0); rb_obj_call_init(res, argc, argv); return res; } static VALUE xb_i_txn(VALUE obj, int *flags) { VALUE key, value; char *options; key = rb_ary_entry(obj, 0); value = rb_ary_entry(obj, 1); key = rb_obj_as_string(key); options = StringValuePtr(key); if (strcmp(options, "flags") == 0) { *flags = NUM2INT(value); } return Qnil; } static VALUE xb_protect_close(VALUE obj) { return rb_funcall2(obj, id_close, 0, 0); } static void xb_final(bdb_ENV *envst) { VALUE *ary; int i; ary = envst->db_ary.ptr; if (ary) { envst->db_ary.mark = Qtrue; for (i = 0; i < envst->db_ary.len; i++) { if (rb_respond_to(ary[i], rb_intern("close"))) { xb_protect_close(ary[i]); } } envst->db_ary.mark = Qfalse; envst->db_ary.total = envst->db_ary.len = 0; envst->db_ary.ptr = 0; ::free(ary); } if (envst->envp) { if (!(envst->options & BDB_ENV_NOT_OPEN)) { DbEnv *env_cxx = static_cast(envst->envp->app_private); delete env_cxx; } envst->envp = NULL; } } static void xb_env_free(bdb_ENV *envst) { xb_final(envst); ::free(envst); } static VALUE xb_env_close(VALUE obj) { if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4) { rb_raise(rb_eSecurityError, "Insecure: can't close the environnement"); } bdb_ENV *envst; GetEnvDBErr(obj, envst, id_current_env, xb_eFatal); xb_final(envst); rset_obj(obj); return Qnil; } static VALUE xb_env_s_alloc(VALUE obj) { bdb_ENV *envst; return Data_Make_Struct(obj, bdb_ENV, 0, free, envst); } static VALUE xb_env_s_i_options(VALUE obj, int *flags) { VALUE key = rb_ary_entry(obj, 0); VALUE value = rb_ary_entry(obj, 1); key = rb_obj_as_string(key); char *options = StringValuePtr(key); if (strcmp(options, "env_flags") == 0) { *flags = NUM2INT(value); } #if HAVE_DBXML_CONST_DB_CLIENT else if (strcmp(options, "set_rpc_server") == 0 || strcmp(options, "set_server") == 0) { *flags |= DB_CLIENT; } #endif return Qnil; } static VALUE xb_env_s_new(int argc, VALUE *argv, VALUE obj) { VALUE res; bdb_ENV *envst; int flags = 0; #ifdef HAVE_RB_DEFINE_ALLOC_FUNC res = rb_obj_alloc(obj); #else res = rb_funcall2(obj, rb_intern("allocate"), 0, 0); #endif Data_Get_Struct(res, bdb_ENV, envst); if (argc && TYPE(argv[argc - 1]) == T_HASH) { rb_iterate(rb_each, argv[argc - 1], (VALUE(*)(ANYARGS))xb_env_s_i_options, (VALUE)&flags); } DbEnv *env = new DbEnv(flags); envst->envp = env->get_DB_ENV(); envst->envp->app_private = static_cast(env); envst->envp->set_errpfx(envst->envp, "BDB::"); bdb_test_error(envst->envp->set_alloc(envst->envp, malloc, realloc, free)); RDATA(res)->dfree = (RDF)xb_env_free; rb_obj_call_init(res, argc, argv); return res; } static VALUE xb_env_init(int argc, VALUE *argv, VALUE obj) { bdb_env_init(argc, argv, obj); return obj; } static VALUE xb_env_begin(int argc, VALUE *argv, VALUE obj) { rb_raise(rb_eNoMethodError, "use a Manager to open a transaction"); } static void xb_man_mark(xman *man) { rb_gc_mark(man->env); rb_gc_mark(man->rsv); } static VALUE ent_each(VALUE klass) { return rb_funcall(xb_mObs, rb_intern("each_object"), 1, klass); } static VALUE xb_res_close(VALUE obj); static VALUE xb_val_close(VALUE obj); static VALUE xb_doc_close(VALUE obj); static VALUE xb_con_close(VALUE obj); static VALUE ent_release(VALUE obj, VALUE man) { VALUE klass = CLASS_OF(obj); if (klass == xb_cRes) { xres *res; Data_Get_Struct(obj, xres, res); if (res->man == man) { FREE_DEBUG("res_release %x\n", obj); xb_res_close(obj); } return Qnil; } if (klass == xb_cVal) { xval *val; Data_Get_Struct(obj, xval, val); if (val->man == man) { FREE_DEBUG("val_release %x\n", obj); xb_val_close(obj); } return Qnil; } if (klass == xb_cDoc) { xdoc *doc; Data_Get_Struct(obj, xdoc, doc); if (doc->man == man) { FREE_DEBUG("doc_release %x\n", obj); xb_doc_close(obj); } return Qnil; } if (klass == xb_cCon) { xcon *con; Data_Get_Struct(obj, xcon, con); if (con->man == man) { FREE_DEBUG("con_release %x\n", obj); xb_con_close(obj); } return Qnil; } if (klass == xb_cQue) { xque *que; Data_Get_Struct(obj, xque, que); if (que->man == man) { FREE_DEBUG("que_release %x\n", obj); delete que->que; que->que = 0; rset_obj(obj); } return Qnil; } return Qnil; } static VALUE clean_ent(VALUE ary) { return rb_iterate(ent_each, RARRAY_PTR(ary)[1], (VALUE (*)(...))ent_release, RARRAY_PTR(ary)[0]); } static VALUE xb_man_close(VALUE obj) { xman *man = (xman *)DATA_PTR(obj); FREE_DEBUG("xb_man_close %x\n", man); if (man->env) { bdb_ENV *envst = (bdb_ENV *)DATA_PTR(man->env); bdb_ary_delete(&envst->db_ary, obj); man->env = 0; } VALUE ary = rb_ary_new2(2); rb_ary_push(ary, obj); rb_ary_push(ary, xb_cRes); rb_protect(clean_ent, ary, 0); rb_ary_store(ary, 1, xb_cVal); rb_protect(clean_ent, ary, 0); rb_ary_store(ary, 1, xb_cDoc); rb_protect(clean_ent, ary, 0); rb_ary_store(ary, 1, xb_cQue); rb_protect(clean_ent, ary, 0); rb_ary_store(ary, 1, xb_cCon); rb_protect(clean_ent, ary, 0); if (man->man) { delete man->man; man->man = 0; } return Qnil; } static void xb_man_free(xman *man) { FREE_DEBUG("xb_man_free %x\n", man); if (man->man) { xb_man_close(man->ori); } ::free(man); } static VALUE xb_env_manager(int argc, VALUE *argv, VALUE obj) { VALUE res, a; bdb_ENV *envst; DbEnv *env_cxx; xman *man; XmlManager *xmlman; int flags = 0; if (rb_scan_args(argc, argv, "01", &a)) { flags = NUM2INT(a) & ~DBXML_ADOPT_DBENV; } GetEnvDBErr(obj, envst, id_current_env, xb_eFatal); if (!(envst->options & BDB_ENV_NOT_OPEN)) { envst->options |= BDB_ENV_NOT_OPEN; flags |= DBXML_ADOPT_DBENV; } env_cxx = static_cast(envst->envp->app_private); PROTECT(xmlman = new XmlManager(env_cxx, flags)); res = Data_Make_Struct(xb_cMan, xman, (RDF)xb_man_mark, (RDF)xb_man_free, man); man->man = xmlman; man->env = obj; man->ori = res; return res; } static VALUE xb_man_s_alloc(VALUE obj) { xman *man; return Data_Make_Struct(obj, xman, 0, (RDF)free, man); } static VALUE xb_man_init(int argc, VALUE *argv, VALUE obj) { VALUE a = Qnil, b; xman *man; int flags = 0; switch (argc) { case 0: break; case 1: if (FIXNUM_P(a)) { flags = NUM2INT(a); a = Qnil; } else { a = argv[0]; } break; default: if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { flags = NUM2INT(b); } } if (NIL_P(a)) { Data_Get_Struct(obj, xman, man); PROTECT(man->man = new XmlManager(flags)); } else { bdb_ENV *envst; DbEnv *env_cxx; GetEnvDBErr(a, envst, id_current_env, xb_eFatal); env_cxx = static_cast(envst->envp->app_private); Data_Get_Struct(obj, xman, man); PROTECT(man->man = new XmlManager(env_cxx, flags)); man->env = a; bdb_ary_push(&envst->db_ary, obj); } RDATA(obj)->dfree = (RDF)xb_man_free; man->ori = obj; return obj; } static VALUE xb_man_env(VALUE obj) { xman *man = get_man(obj); if (RTEST(man->env)) { return man->env; } return Qnil; } static VALUE xb_man_env_p(VALUE obj) { xman *man = get_man(obj); if (RTEST(man->env)) { return Qtrue; } return Qfalse; } static VALUE xb_man_home(VALUE obj) { xman *man = get_man(obj); return rb_tainted_str_new2(man->man->getHome().c_str()); } static VALUE xb_man_page_get(VALUE obj) { xman *man = get_man(obj); return INT2NUM(man->man->getDefaultPageSize()); } static VALUE xb_man_page_set(VALUE obj, VALUE a) { xman *man = get_man(obj); u_int32_t page = NUM2INT(a); PROTECT(man->man->setDefaultPageSize(page)); return a; } static VALUE xb_man_flags_get(VALUE obj) { xman *man = get_man(obj); return INT2NUM(man->man->getDefaultContainerFlags()); } static VALUE xb_man_flags_set(VALUE obj, VALUE a) { xman *man = get_man(obj); u_int32_t flags = NUM2INT(a); PROTECT(man->man->setDefaultContainerFlags(flags)); return a; } static VALUE xb_man_type_get(VALUE obj) { xman *man = get_man(obj); return INT2NUM(man->man->getDefaultContainerType()); } static VALUE xb_man_type_set(VALUE obj, VALUE a) { xman *man = get_man(obj); XmlContainer::ContainerType type = XmlContainer::ContainerType(NUM2INT(a)); PROTECT(man->man->setDefaultContainerType(type)); return a; } static VALUE xb_man_rename(VALUE obj, VALUE a, VALUE b) { rb_secure(2); XmlTransaction *xmltxn = get_txn(obj); xman *man = get_man_txn(obj); char *oldname = StringValuePtr(a); char *newname = StringValuePtr(b); if (xmltxn) { PROTECT(man->man->renameContainer(*xmltxn, oldname, newname)); } else { PROTECT(man->man->renameContainer(oldname, newname)); } return obj; } static VALUE xb_man_remove(VALUE obj, VALUE a) { rb_secure(2); XmlTransaction *xmltxn = get_txn(obj); xman *man = get_man_txn(obj); char *name = StringValuePtr(a); if (xmltxn) { PROTECT(man->man->removeContainer(*xmltxn, name)); } else { PROTECT(man->man->removeContainer(name)); } return obj; } #if ! HAVE_RB_BLOCK_CALL static VALUE xb_each(VALUE *tmp) { return rb_funcall2(tmp[0], (ID)tmp[1], (int)tmp[2], (VALUE *)tmp[3]); } #endif static VALUE xb_txn_missing(int argc, VALUE *argv, VALUE obj) { bdb_TXN *txnst; GetTxnDBErr(obj, txnst, xb_eFatal); get_man(txnst->man); if (argc <= 0) { rb_raise(rb_eArgError, "no id given"); } ID id = SYM2ID(argv[0]); argc--; argv++; if (rb_block_given_p()) { #if HAVE_RB_BLOCK_CALL return rb_block_call(txnst->man, id, argc, argv, (VALUE(*)(ANYARGS))rb_yield, 0); #else VALUE tmp[4]; tmp[0] = txnst->man; tmp[1] = (VALUE)id; tmp[2] = (VALUE)argc; tmp[3] = (VALUE)argv; return rb_iterate((VALUE(*)(VALUE))xb_each, (VALUE)tmp, (VALUE(*)(ANYARGS))rb_yield, 0); #endif } return rb_funcall2(txnst->man, id, argc, argv); } static VALUE xb_man_dump_con(int argc, VALUE *argv, VALUE obj) { VALUE a, b, c; bool to_close = false; xman *man = get_man(obj); if (rb_scan_args(argc, argv, "21", &a, &b, &c) == 3) { to_close = RTEST(c); } char *name = StringValuePtr(a); if (rb_respond_to(b, id_write)) { std::xbWrite rbw(b, to_close); std::ostream out(&rbw); PROTECT(man->man->dumpContainer(name, &out)); } else { char *file = StringValuePtr(b); std::ofstream out(file); PROTECT2(man->man->dumpContainer(name, &out), out.close()); } return obj; } static VALUE xb_man_verify(int argc, VALUE *argv, VALUE obj) { VALUE a, b, c, d; int flags = 0; rb_secure(4); switch (rb_scan_args(argc, argv, "12", &a, &b, &c, &d)) { case 4: flags = NUM2INT(d); /* ... */ case 3: if (!rb_respond_to(b, id_write)) { flags = NUM2INT(c); } } xman *man = get_man(obj); char *name = StringValuePtr(a); if (flags & DB_SALVAGE) { if (rb_respond_to(b, id_write)) { std::xbWrite rbw(b, RTEST(c)); std::ostream out(&rbw); PROTECT(man->man->verifyContainer(name, &out, flags)); } else { char *file = StringValuePtr(b); std::ofstream out; out.open(file); PROTECT2(man->man->verifyContainer(name, &out, flags), out.close()); } } else { std::ofstream out; PROTECT(man->man->verifyContainer(name, &out, flags)); } return Qnil; } static VALUE xb_man_load_con(int argc, VALUE *argv, VALUE obj) { VALUE a, b, c = Qnil, d = Qnil; xupd *upd; XmlUpdateContext *xmlupd = 0; unsigned long lineno = 0; bool freeupd = true; rb_secure(2); xman *man = get_man(obj); switch (rb_scan_args(argc, argv, "22", &a, &b, &c, &d)) { case 4: upd = get_upd(d); xmlupd = upd->upd; freeupd = false; /* ... */ case 3: if (!rb_respond_to(b, id_read)) { upd = get_upd(c); xmlupd = upd->upd; freeupd = false; } } char *name = StringValuePtr(a); if (rb_respond_to(b, id_read)) { std::xbRead rbs(b, RTEST(c)); std::istream in(&rbs); if (freeupd) { xmlupd = new XmlUpdateContext(man->man->createUpdateContext()); } PROTECT2(man->man->loadContainer(name, &in, &lineno, *xmlupd), if (freeupd) delete xmlupd); } else { char *file = StringValuePtr(b); std::ifstream in(file); if (freeupd) { xmlupd = new XmlUpdateContext(man->man->createUpdateContext()); } PROTECT2(man->man->loadContainer(name, &in, &lineno, *xmlupd), in.close(); if (freeupd) delete xmlupd); } return obj; } static void xmltxn_free(void **xmltxn) { if (!xmltxn) return; if (!*xmltxn) return; XmlTransaction *cxxtxn = reinterpret_cast(*xmltxn); delete cxxtxn; // tell the c layer we deallocated it *xmltxn = NULL; } static int xmltxn_abort( void * xmltxn ) { return reinterpret_cast(xmltxn)->getDbTxn()->abort(); } static int xmltxn_commit( void * xmltxn, u_int32_t flags ) { return reinterpret_cast(xmltxn)->getDbTxn()->commit(flags); } static int xmltxn_discard( void * xmltxn, u_int32_t flags ) { return reinterpret_cast(xmltxn)->getDbTxn()->discard(flags); } static VALUE xb_man_begin(int argc, VALUE *argv, VALUE obj) { struct txn_rslbl txnr; xman *man; VALUE rman; XmlTransaction *xmltxn, *xmlold = 0; int flags = 0; if (argc) { if (TYPE(argv[argc - 1]) == T_HASH) { rb_iterate(RMFS(rb_each), argv[argc - 1], RMF(xb_i_txn), (VALUE)&flags); } if (FIXNUM_P(argv[0])) { flags = NUM2INT(argv[0]); } flags &= ~BDB_TXN_COMMIT; } if (rb_obj_is_kind_of(obj, xb_cTxn)) { bdb_TXN *txnst; GetTxnDBErr(obj, txnst, xb_eFatal); rman = txnst->man; xmlold = (XmlTransaction *)txnst->txn_cxx; man = get_man(txnst->man); } else { rman = obj; man = get_man(obj); if (!RTEST(man->env)) { rb_raise(rb_eArgError, "no environnement"); } obj = man->env; } if (xmlold) { PROTECT(xmltxn = new XmlTransaction(xmlold->createChild(flags))); } else { PROTECT(xmltxn = new XmlTransaction(man->man->createTransaction(flags))); } txnr.txn_cxx = xmltxn; txnr.txn_cxx_free = xmltxn_free; txnr.txn_cxx_abort = xmltxn_abort; txnr.txn_cxx_commit = xmltxn_commit; txnr.txn_cxx_discard = xmltxn_discard; txnr.txn = xmltxn->getDbTxn()->get_DB_TXN(); // XXX txnr.man = rman; return bdb_env_rslbl_begin((VALUE)&txnr, argc, argv, obj); } #if HAVE_DBXML_MAN_EXISTS_CONTAINER static VALUE xb_man_con_version(VALUE obj, VALUE a) { xman *man = get_man(obj); char *uri = StringValuePtr(a); return INT2NUM(man->man->existsContainer(uri)); } #endif #if HAVE_DBXML_MAN_REINDEX_CONTAINER static VALUE xb_man_reindex(int argc, VALUE *argv, VALUE obj) { XmlUpdateContext *xmlupd = 0; xupd *upd; VALUE a, b, c; std::string name; bool freeupd = true; int flags = 0; rb_secure(2); XmlTransaction *xmltxn = get_txn(obj); xman *man = get_man_txn(obj); switch (rb_scan_args(argc, argv, "12", &a, &b, &c)) { case 3: flags = NUM2INT(c); /* ... */ case 2: if (!NIL_P(b)) { upd = get_upd(b); xmlupd = upd->upd; freeupd = false; } /* ... */ case 1: name = StringValuePtr(a); break; } if (freeupd) { xmlupd = new XmlUpdateContext(man->man->createUpdateContext()); } if (!xmltxn) { PROTECT2(man->man->reindexContainer(name, *xmlupd, flags), if (freeupd) delete xmlupd); } else { PROTECT2(man->man->reindexContainer(*xmltxn, name, *xmlupd, flags), if (freeupd) delete xmlupd); } return obj; } #endif #if HAVE_DBXML_MAN_DEFAULT_SEQUENCE_INCREMENT static VALUE xb_man_increment_get(VALUE obj) { xman *man = get_man(obj); return INT2NUM(man->man->getDefaultSequenceIncrement()); } static VALUE xb_man_increment_set(VALUE obj, VALUE a) { xman *man = get_man(obj); int incr = NUM2INT(a); PROTECT(man->man->setDefaultSequenceIncrement(incr)); return a; } #endif #if HAVE_DBXML_MAN_GET_FLAGS static VALUE xb_man_get_flags(VALUE obj) { xman *man = get_man(obj); return INT2NUM(man->man->getFlags()); } #endif #if HAVE_DBXML_MAN_GET_IMPLICIT_TIMEZONE static VALUE xb_man_get_itz(VALUE obj) { xman *man = get_man(obj); return INT2NUM(man->man->getImplicitTimezone()); } static VALUE xb_man_set_itz(VALUE obj, VALUE a) { xman *man = get_man(obj); int tz = NUM2INT(a); PROTECT(man->man->setImplicitTimezone(tz)); return a; } #endif #if HAVE_DBXML_MAN_COMPACT_CONTAINER static VALUE xb_man_compact_con(int argc, VALUE *argv, VALUE obj) { XmlUpdateContext *xmlupd = 0; xupd *upd; VALUE a, b; std::string name; bool freeupd = true; int flags = 0; rb_secure(2); XmlTransaction *xmltxn = get_txn(obj); xman *man = get_man_txn(obj); switch (rb_scan_args(argc, argv, "11", &a, &b)) { case 2: if (!NIL_P(b)) { upd = get_upd(b); xmlupd = upd->upd; freeupd = false; } /* ... */ case 1: name = StringValuePtr(a); break; } if (freeupd) { xmlupd = new XmlUpdateContext(man->man->createUpdateContext()); } if (!xmltxn) { PROTECT2(man->man->compactContainer(name, *xmlupd, flags), if (freeupd) delete xmlupd); } else { PROTECT2(man->man->compactContainer(*xmltxn, name, *xmlupd, flags), if (freeupd) delete xmlupd); } return obj; } #endif #if HAVE_DBXML_MAN_TRUNCATE_CONTAINER static VALUE xb_man_truncate_con(int argc, VALUE *argv, VALUE obj) { XmlUpdateContext *xmlupd = 0; xupd *upd; VALUE a, b; std::string name; bool freeupd = true; int flags = 0; rb_secure(2); XmlTransaction *xmltxn = get_txn(obj); xman *man = get_man_txn(obj); switch (rb_scan_args(argc, argv, "11", &a, &b)) { case 2: if (!NIL_P(b)) { upd = get_upd(b); xmlupd = upd->upd; freeupd = false; } /* ... */ case 1: name = StringValuePtr(a); break; } if (freeupd) { xmlupd = new XmlUpdateContext(man->man->createUpdateContext()); } if (!xmltxn) { PROTECT2(man->man->truncateContainer(name, *xmlupd, flags), if (freeupd) delete xmlupd); } else { PROTECT2(man->man->truncateContainer(*xmltxn, name, *xmlupd, flags), if (freeupd) delete xmlupd); } return obj; } #endif static void xb_con_mark(xcon *con) { rb_gc_mark(con->man); rb_gc_mark(con->ind); rb_gc_mark(con->txn); #if HAVE_DBXML_XML_INDEX_LOOKUP rb_gc_mark(con->look); #endif } static VALUE close_txn(VALUE txn) { bdb_TXN *txnst; Data_Get_Struct(txn, bdb_TXN, txnst); if (txnst->txnid) { rb_funcall2(txn, rb_intern("abort"), 0, 0); } return Qnil; } static void delete_ind(VALUE obj) { if (!RTEST(obj)) return; xind *ind = get_ind(obj); delete ind->ind; ind->ind = 0; RDATA(obj)->dfree = free; RDATA(obj)->dmark = 0; } static void delete_look(VALUE obj) { if (!RTEST(obj)) return; xlook *look = get_look(obj); delete look->look; look->look = 0; RDATA(obj)->dfree = free; RDATA(obj)->dmark = 0; } static void xb_con_free(xcon *con) { FREE_DEBUG("xb_con_free %x\n", con); if (con->con) { if (con->man) { delete_ind(con->ind); #if HAVE_DBXML_XML_INDEX_LOOKUP delete_look(con->look); #endif if (con->txn) { close_txn(con->txn); } } delete con->con; } ::free(con); } static VALUE xb_int_open_con(int argc, VALUE *argv, VALUE obj, VALUE orig) { VALUE res, a, b; XmlContainer *xmlcon; xcon *con; int flags = 0; if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { flags = NUM2INT(b); } if (flags && DB_CREATE) { rb_secure(4); } char *name = StringValuePtr(a); xman *man = get_man_txn(obj); XmlTransaction *xmltxn = get_txn(obj); if (xmltxn) { PROTECT(xmlcon = new XmlContainer(man->man->openContainer(*xmltxn, name, flags))); } else { PROTECT(xmlcon = new XmlContainer(man->man->openContainer(name, flags))); } if (!orig) { res = Data_Make_Struct(xb_cCon, xcon, (RDF)xb_con_mark, (RDF)xb_con_free, con); } else { res = orig; Data_Get_Struct(res, xcon, con); RDATA(res)->dfree = (RDF)xb_con_free; } FREE_DEBUG("open_con %x man %x\n", con, man); con->con = xmlcon; if (rb_obj_is_kind_of(obj, xb_cTxn)) { con->txn = obj; con->man = get_txn_man(obj); } else { con->man = obj; } con->opened = 1; return res; } static VALUE xb_int_create_con(int argc, VALUE *argv, VALUE obj, VALUE orig) { VALUE res, a, b, c, d; XmlContainer *xmlcon; xcon *con; rb_secure(4); xman *man = get_man_txn(obj); XmlTransaction *xmltxn = get_txn(obj); if (argc == 1) { char *name = StringValuePtr(argv[0]); if (xmltxn) { PROTECT(xmlcon = new XmlContainer(man->man->createContainer(*xmltxn, name))); } else { PROTECT(xmlcon = new XmlContainer(man->man->createContainer(name))); } } else { int flags = 0, mode = 0; XmlContainer::ContainerType type = XmlContainer::NodeContainer; switch (rb_scan_args(argc, argv, "13", &a, &b, &c, &d)) { case 4: mode = NUM2INT(d); /* ... */ case 3: if (!NIL_P(c)) { type = XmlContainer::ContainerType(NUM2INT(c)); } /* ... */ case 2: if (!NIL_P(b)) { flags = NUM2INT(b); } } char *name = StringValuePtr(a); if (xmltxn) { PROTECT(xmlcon = new XmlContainer(man->man->createContainer(*xmltxn, name, flags, type, mode))); } else { PROTECT(xmlcon = new XmlContainer(man->man->createContainer(name, flags, type, mode))); } } if (!orig) { res = Data_Make_Struct(xb_cCon, xcon, (RDF)xb_con_mark, (RDF)xb_con_free, con); } else { res = orig; Data_Get_Struct(res, xcon, con); RDATA(res)->dfree = (RDF)xb_con_free; } FREE_DEBUG("open_con %x man %x\n", con, man); con->con = xmlcon; if (rb_obj_is_kind_of(obj, xb_cTxn)) { con->txn = obj; con->man = get_txn_man(obj); } else { con->man = obj; } con->opened = 1; return res; } static VALUE xb_man_create_con(int argc, VALUE *argv, VALUE obj) { return xb_int_create_con(argc, argv, obj, 0); } static VALUE xb_man_open_con(int argc, VALUE *argv, VALUE obj) { return xb_int_open_con(argc, argv, obj, 0); } static VALUE xb_con_s_alloc(VALUE obj) { xcon *con; return Data_Make_Struct(obj, xcon, (RDF)xb_con_mark, (RDF)free, con); } static VALUE xb_con_s_open(int argc, VALUE *argv, VALUE obj) { if (argc <= 0) { rb_raise(rb_eArgError, "invalid number of arguments (%d)", argc); } VALUE tmp = argv[0]; argc--; argv++; get_man(tmp); VALUE res = xb_con_s_alloc(obj); return xb_int_open_con(argc, argv, tmp, res); } static VALUE xb_con_init(int argc, VALUE *argv, VALUE obj) { if (argc <= 0) { rb_raise(rb_eArgError, "invalid number of arguments (%d)", argc); } VALUE tmp = argv[0]; argc--; argv++; return xb_int_open_con(argc, argv, tmp, obj); } static void xb_upd_mark(xupd *upd) { rb_gc_mark(upd->man); } static void xb_upd_free(xupd *upd) { FREE_DEBUG("xb_upd_free %x\n", upd); if (upd->upd) { delete upd->upd; } ::free(upd); } static VALUE xb_int_create_upd(VALUE obj, VALUE orig) { VALUE res; XmlUpdateContext *xmlupd; xupd *upd; xman *man = get_man(obj); PROTECT(xmlupd = new XmlUpdateContext(man->man->createUpdateContext())); if (!orig) { res = Data_Make_Struct(xb_cUpd, xupd, (RDF)xb_upd_mark, (RDF)xb_upd_free, upd); } else { res = orig; Data_Get_Struct(res, xupd, upd); RDATA(res)->dfree = (RDF)xb_upd_free; } upd->man = obj; upd->upd = xmlupd; return res; } static VALUE xb_man_create_upd(VALUE obj) { return xb_int_create_upd(obj, 0); } static VALUE xb_upd_s_alloc(VALUE obj) { xupd *upd; return Data_Make_Struct(obj, xupd, (RDF)xb_upd_mark, (RDF)free, upd); } static VALUE xb_upd_init(VALUE obj, VALUE a) { return xb_int_create_upd(a, obj); } static VALUE xb_upd_manager(VALUE obj) { xupd *upd = get_upd(obj); return upd->man; } #if HAVE_DBXML_UPDATE_APPLY_CHANGES static VALUE xb_upd_changes_get(VALUE obj) { xupd *upd = get_upd(obj); if (RTEST(upd->upd->getApplyChangesToContainers())) { return Qtrue; } return Qfalse; } static VALUE xb_upd_changes_set(VALUE obj, VALUE a) { xupd *upd = get_upd(obj); upd->upd->setApplyChangesToContainers(RTEST(a)); return obj; } #endif static void xb_doc_mark(xdoc *doc) { rb_gc_mark(doc->man); } static void doc_free(xdoc *doc) { if (doc->doc) { delete doc->doc; doc->doc = 0; } } static void xb_doc_free(xdoc *doc) { FREE_DEBUG("xb_doc_free %x\n", doc); doc_free(doc); ::free(doc); } static VALUE xb_int_create_doc(VALUE obj, VALUE orig) { XmlDocument *xmldoc; xdoc *doc; xman *man = get_man(obj); PROTECT(xmldoc = new XmlDocument(man->man->createDocument())); VALUE res; if (!orig) { res = Data_Make_Struct(xb_cDoc, xdoc, (RDF)xb_doc_mark, (RDF)xb_doc_free, doc); } else { res = orig; Data_Get_Struct(res, xdoc, doc); RDATA(res)->dfree = (RDF)xb_doc_free; } doc->man = obj; doc->doc = xmldoc; return res; } static VALUE xb_man_create_doc(VALUE obj) { return xb_int_create_doc(obj, 0); } static VALUE xb_doc_s_alloc(VALUE obj) { xdoc *doc; return Data_Make_Struct(obj, xdoc, (RDF)xb_doc_mark, (RDF)free, doc); } static VALUE xb_doc_init(VALUE obj, VALUE a) { return xb_int_create_doc(a, obj); } static VALUE xb_doc_close(VALUE obj) { xdoc *doc = get_doc(obj); FREE_DEBUG("xb_doc_close %x\n", doc); doc_free(doc); rset_obj(obj); return Qnil; } static void xb_cxt_mark(xcxt *cxt) { rb_gc_mark(cxt->man); } static void xb_cxt_free(xcxt *cxt) { FREE_DEBUG("xb_cxt_free %x\n", cxt); if (cxt->cxt) { delete cxt->cxt; } ::free(cxt); } static VALUE xb_int_create_cxt(int argc, VALUE *argv, VALUE obj, VALUE orig) { XmlQueryContext::ReturnType rt = XmlQueryContext::LiveValues; XmlQueryContext::EvaluationType et = XmlQueryContext::Eager; VALUE a, b; xcxt *cxt; XmlQueryContext *xmlcxt; switch (rb_scan_args(argc, argv, "02", &a, &b)) { case 2: et = XmlQueryContext::EvaluationType(NUM2INT(b)); /* ... */ case 1: rt = XmlQueryContext::ReturnType(NUM2INT(a)); } xman *man = get_man(obj); PROTECT(xmlcxt = new XmlQueryContext(man->man->createQueryContext(rt, et))); VALUE res; if (!orig) { res = Data_Make_Struct(xb_cCxt, xcxt, (RDF)xb_cxt_mark, (RDF)xb_cxt_free, cxt); } else { res = orig; Data_Get_Struct(res, xcxt, cxt); RDATA(res)->dfree = (RDF)xb_cxt_free; } cxt->cxt = xmlcxt; cxt->man = obj; return res; } static VALUE xb_man_create_cxt(int argc, VALUE *argv, VALUE obj) { return xb_int_create_cxt(argc, argv, obj, 0); } static VALUE xb_cxt_s_alloc(VALUE obj) { xcxt *cxt; return Data_Make_Struct(obj, xcxt, (RDF)xb_cxt_mark, (RDF)free, cxt); } static VALUE xb_cxt_init(int argc, VALUE *argv, VALUE obj) { if (argc <= 0) { rb_raise(rb_eArgError, "invalid number of arguments (%d)", argc); } VALUE tmp = argv[0]; argc--; argv++; return xb_int_create_cxt(argc, argv, tmp, obj); } static void xb_que_mark(xque *que) { rb_gc_mark(que->man); rb_gc_mark(que->txn); } static void xb_que_free(xque *que) { FREE_DEBUG("xb_que_free %x\n", que); if (que->que) { delete que->que; } ::free(que); } static VALUE xb_man_prepare(int argc, VALUE *argv, VALUE obj) { VALUE res, a, b; XmlQueryExpression *xmlqe; XmlQueryContext *xmlcxt; bool freecxt = false; xman *man = get_man_txn(obj); XmlTransaction *xmltxn = get_txn(obj); if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { xcxt *cxt = get_cxt(b); xmlcxt = cxt->cxt; } else { xmlcxt = new XmlQueryContext(man->man->createQueryContext()); freecxt = true; } char *str = StringValuePtr(a); if (xmltxn) { PROTECT2(xmlqe = new XmlQueryExpression(man->man->prepare(*xmltxn, str, *xmlcxt)), if (freecxt) delete xmlcxt); } else { PROTECT2(xmlqe = new XmlQueryExpression(man->man->prepare(str, *xmlcxt)), if (freecxt) delete xmlcxt); } xque *que; res = Data_Make_Struct(xb_cQue, xque, (RDF)xb_que_mark, (RDF)xb_que_free, que); que->que = xmlqe; if (rb_obj_is_kind_of(obj, xb_cTxn)) { que->txn = obj; que->man = get_txn_man(obj); } else { que->man = obj; } return res; } static void xb_res_mark(xres *res) { rb_gc_mark(res->man); } static void res_free(xres *res) { if (res->res) { delete res->res; res->res = 0; } } static void xb_res_free(xres *res) { FREE_DEBUG("xb_res_free %x\n", res); res_free(res); ::free(res); } static VALUE xb_res_close(VALUE obj) { xres *res = get_res(obj); res_free(res); rset_obj(obj); return Qnil; } static VALUE xb_int_create_res(VALUE obj, VALUE orig) { xres *res; XmlResults *xmlres; xman *man = get_man(obj); PROTECT(xmlres = new XmlResults(man->man->createResults())); VALUE result; if (!orig) { result = Data_Make_Struct(xb_cRes, xres, (RDF)xb_res_mark, (RDF)xb_res_free, res); } else { result = orig; Data_Get_Struct(result, xres, res); RDATA(result)->dfree = (RDF)xb_res_free; } res->res = xmlres; res->man = obj; return result; } static VALUE xb_man_create_res(VALUE obj) { return xb_int_create_res(obj, 0); } static VALUE xb_res_s_alloc(VALUE obj) { xres *res; return Data_Make_Struct(obj, xres, (RDF)xb_res_mark, (RDF)free, res); } static VALUE xb_res_init(VALUE obj, VALUE a) { return xb_int_create_res(a, obj); } static VALUE xb_man_query(int argc, VALUE *argv, VALUE obj) { VALUE a, b, c; XmlResults *xmlres; XmlQueryContext *xmlcxt; bool freecxt = false; xcxt *cxt; int flags = 0; xman *man = get_man_txn(obj); XmlTransaction *xmltxn = get_txn(obj); switch(rb_scan_args(argc, argv, "12", &a, &b, &c)) { case 3: flags = NUM2INT(c); case 2: cxt = get_cxt(b); xmlcxt = cxt->cxt; break; default: xmlcxt = new XmlQueryContext(man->man->createQueryContext()); freecxt = true; } char *str = StringValuePtr(a); if (xmltxn) { PROTECT2(xmlres = new XmlResults(man->man->query(*xmltxn, str, *xmlcxt, flags)), if (freecxt) delete xmlcxt); } else { PROTECT2(xmlres = new XmlResults(man->man->query(str, *xmlcxt, flags)), if (freecxt) delete xmlcxt); } xres *res; VALUE result = Data_Make_Struct(xb_cRes, xres, (RDF)xb_res_mark, (RDF)xb_res_free, res); res->res = xmlres; if (rb_obj_is_kind_of(obj, xb_cTxn)) { res->man = get_txn_man(obj); } else { res->man = obj; } if (rb_block_given_p()) { #if HAVE_RB_BLOCK_CALL return rb_block_call(result, rb_intern("each"), 0, 0, (VALUE(*)(ANYARGS))rb_yield, Qnil); #else return rb_iterate(rb_each, result, (VALUE(*)(ANYARGS))rb_yield, Qnil); #endif } return result; } static VALUE xb_man_upgrade(int argc, VALUE *argv, VALUE obj) { VALUE a, b; xupd *upd; XmlUpdateContext *xmlupd; bool freeupd = false; xman *man = get_man(obj); char *name = StringValuePtr(a); if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { upd = get_upd(b); xmlupd = upd->upd; } else { xmlupd = new XmlUpdateContext(man->man->createUpdateContext()); freeupd = true; } PROTECT2(man->man->upgradeContainer(name, *xmlupd), if (freeupd) delete xmlupd); return obj; } static VALUE xb_con_manager(VALUE obj) { xcon *con = get_con(obj); return con->man; } static VALUE xb_con_alias_set(VALUE obj, VALUE a) { xcon *con = get_con(obj); char *alias = StringValuePtr(a); if (con->con->addAlias(alias)) { return a; } return Qnil; } static VALUE xb_con_alias_del(VALUE obj, VALUE a) { xcon *con = get_con(obj); char *alias = StringValuePtr(a); if (con->con->removeAlias(alias)) { return a; } return Qfalse; } static VALUE xb_con_all(int argc, VALUE *argv, VALUE obj) { xres *res; XmlResults *xmlres; VALUE a; int flags = 0; if (rb_scan_args(argc, argv, "01", &a)) { flags = NUM2INT(a); } xcon *con = get_con(obj); XmlTransaction *xmltxn = get_con_txn(con); if (xmltxn) { PROTECT(xmlres = new XmlResults(con->con->getAllDocuments(*xmltxn, flags))); } else { PROTECT(xmlres = new XmlResults(con->con->getAllDocuments(flags))); } VALUE result = Data_Make_Struct(xb_cRes, xres, (RDF)xb_res_mark, (RDF)xb_res_free, res); res->res = xmlres; res->man = con->man; return result; } static VALUE xb_con_type(VALUE obj) { xcon *con = get_con(obj); return INT2NUM(con->con->getContainerType()); } static VALUE xb_con_sync(VALUE obj) { xcon *con = get_con(obj); PROTECT(con->con->sync()); return obj; } static VALUE xb_con_close(VALUE obj) { xcon *con = get_con(obj); FREE_DEBUG("xb_con_close %x\n", con); rset_obj(obj); delete_ind(con->ind); #if HAVE_DBXML_XML_INDEX_LOOKUP delete_look(con->look); #endif delete con->con; return Qnil; } static void delete_doc(VALUE obj, xdoc *doc) { if (TYPE(obj) != T_DATA || RDATA(obj)->dfree != (RDF)xb_doc_free) { rb_raise(rb_eArgError, "expected a Document object"); } delete doc->doc; rset_obj(obj); } static VALUE xb_con_add(int argc, VALUE *argv, VALUE obj) { VALUE a, c, d; volatile VALUE b; xupd *upd; XmlUpdateContext *xmlupd = 0; bool freeupd = true; int flags = 0; rb_secure(4); xcon *con = get_con(obj); XmlTransaction *xmltxn = get_con_txn(con); rb_scan_args(argc, argv, "13", &a, &b, &c, &d); if (TYPE(a) == T_DATA && RDATA(a)->dmark == (RDF)xb_doc_mark) { if (argc == 4) { rb_raise(rb_eArgError, "invalid number of argument (4 for 3)"); } if (argc >= 2 && !NIL_P(b)) { upd = get_upd(b); xmlupd = upd->upd; freeupd = false; } if (argc == 3) { flags = NUM2INT(c); } xdoc *doc = get_doc(a); if (freeupd) { xman *man = get_man(con->man); xmlupd = new XmlUpdateContext(man->man->createUpdateContext()); } if (xmltxn) { PROTECT2(con->con->putDocument(*xmltxn, *doc->doc, *xmlupd, flags), if (freeupd) delete xmlupd); } else { PROTECT2(con->con->putDocument(*doc->doc, *xmlupd, flags), if (freeupd) delete xmlupd); } delete_doc(a, doc); } else { std::string new_id; if (argc == 1) { rb_raise(rb_eArgError, "invalid number of argument (1 for 2)"); } char *name = StringValuePtr(a); if (argc >= 3 && !NIL_P(c)) { upd = get_upd(c); xmlupd = upd->upd; freeupd = false; } if (argc == 4) { flags = NUM2INT(d); } if (rb_respond_to(b, id_read)) { xbInput rbs(b); if (freeupd) { xman *man = get_man(con->man); xmlupd = new XmlUpdateContext(man->man->createUpdateContext()); } if (xmltxn) { PROTECT2(new_id = con->con->putDocument(*xmltxn, name, &rbs, *xmlupd, flags), if (freeupd) delete xmlupd); } else { PROTECT2(new_id = con->con->putDocument(name, &rbs, *xmlupd, flags), if (freeupd) delete xmlupd); } } else { char *content = StringValuePtr(b); if (freeupd) { xman *man = get_man(con->man); xmlupd = new XmlUpdateContext(man->man->createUpdateContext()); } if (xmltxn) { PROTECT2(new_id = con->con->putDocument(*xmltxn, name, content, *xmlupd, flags), if (freeupd) delete xmlupd); } else { PROTECT2(new_id = con->con->putDocument(name, content, *xmlupd, flags), if (freeupd) delete xmlupd); } } return rb_tainted_str_new2(new_id.c_str()); } return obj; } static VALUE xb_con_set(VALUE obj, VALUE a, VALUE b) { VALUE tmp[2]; tmp[0] = a; tmp[1] = b; return xb_con_add(2, tmp, obj); } static VALUE xb_con_update(int argc, VALUE *argv, VALUE obj) { VALUE a, b; XmlUpdateContext *xmlupd = 0; bool freeupd = true; rb_secure(4); xcon *con = get_con(obj); XmlTransaction *xmltxn = get_con_txn(con); if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { xupd *upd = get_upd(b); xmlupd = upd->upd; freeupd = false; } if (TYPE(a) != T_DATA || RDATA(a)->dmark != (RDF)xb_doc_mark) { rb_raise(rb_eArgError, "expected an Document object"); } xdoc *doc = get_doc(a); if (freeupd) { xman *man = get_man(con->man); xmlupd = new XmlUpdateContext(man->man->createUpdateContext()); } if (xmltxn) { PROTECT2(con->con->updateDocument(*xmltxn, *doc->doc, *xmlupd), if (freeupd) delete xmlupd); } else { PROTECT2(con->con->updateDocument(*doc->doc, *xmlupd), if (freeupd) delete xmlupd); } delete_doc(a, doc); return obj; } static VALUE xb_con_delete(int argc, VALUE *argv, VALUE obj) { VALUE a, b; xupd *upd; XmlUpdateContext *xmlupd = 0; bool freeupd = true; rb_secure(4); xcon *con = get_con(obj); XmlTransaction *xmltxn = get_con_txn(con); if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { upd = get_upd(b); xmlupd = upd->upd; freeupd = false; } if (TYPE(a) == T_DATA && RDATA(a)->dmark == (RDF)xb_doc_mark) { xdoc *doc = get_doc(a); if (freeupd) { xman *man = get_man(con->man); xmlupd = new XmlUpdateContext(man->man->createUpdateContext()); } if (xmltxn) { PROTECT2(con->con->deleteDocument(*xmltxn, *doc->doc, *xmlupd), if (freeupd) delete xmlupd); } else { PROTECT2(con->con->deleteDocument(*doc->doc, *xmlupd), if (freeupd) delete xmlupd); } } else { char *name = StringValuePtr(a); if (freeupd) { xman *man = get_man(con->man); xmlupd = new XmlUpdateContext(man->man->createUpdateContext()); } if (xmltxn) { PROTECT2(con->con->deleteDocument(*xmltxn, name, *xmlupd), if (freeupd) delete xmlupd); } else { PROTECT2(con->con->deleteDocument(name, *xmlupd), if (freeupd) delete xmlupd); } } return obj; } static VALUE xb_con_txn_p(VALUE obj) { xcon *con = get_con(obj); if (RTEST(con->txn)) { return Qtrue; } return Qfalse; } static VALUE xb_con_txn(VALUE obj) { xcon *con = get_con(obj); if (RTEST(con->txn)) { return con->txn; } return Qnil; } static VALUE xb_con_name(VALUE obj) { std::string name; xcon *con = get_con(obj); PROTECT(name = con->con->getName()); return rb_tainted_str_new2(name.c_str()); } static VALUE xb_con_add_index(int argc, VALUE *argv, VALUE obj) { xupd *upd; VALUE a, b, c, d, e; char *uri = 0, *name = 0, *index = 0; XmlUpdateContext *xmlupd = 0; xcon *con = get_con(obj); XmlTransaction *xmltxn = get_con_txn(con); switch(rb_scan_args(argc, argv, "32", &a, &b, &c, &d, &e)) { case 5: { uri = StringValuePtr(a); name = StringValuePtr(b); XmlIndexSpecification::Type type = XmlIndexSpecification::Type(NUM2INT(c)); XmlValue::Type syntax = XmlValue::Type(NUM2INT(d)); upd = get_upd(e); xmlupd = upd->upd; if (xmltxn) { PROTECT(con->con->addIndex(*xmltxn, uri, name, type, syntax, *xmlupd)); } else { PROTECT(con->con->addIndex(uri, name, type, syntax, *xmlupd)); } break; } case 4: { uri = StringValuePtr(a); name = StringValuePtr(b); if (TYPE(d) == T_DATA && RDATA(d)->dfree == (RDF)xb_upd_free) { upd = get_upd(d); xmlupd = upd->upd; index = StringValuePtr(c); if (xmltxn) { PROTECT(con->con->addIndex(*xmltxn, uri, name, index, *xmlupd)); } else { PROTECT(con->con->addIndex(uri, name, index, *xmlupd)); } } else { XmlValue::Type syntax = XmlValue::Type(NUM2INT(d)); XmlIndexSpecification::Type type = XmlIndexSpecification::Type(NUM2INT(c)); xman *man = get_man(con->man); xmlupd = new XmlUpdateContext(man->man->createUpdateContext()); if (xmltxn) { PROTECT2(con->con->addIndex(*xmltxn, uri, name, type, syntax, *xmlupd), delete xmlupd); } else { PROTECT2(con->con->addIndex(uri, name, type, syntax, *xmlupd), delete xmlupd); } } break; } case 3: { uri = StringValuePtr(a); name = StringValuePtr(b); index = StringValuePtr(c); xman *man = get_man(con->man); xmlupd = new XmlUpdateContext(man->man->createUpdateContext()); if (xmltxn) { PROTECT2(con->con->addIndex(*xmltxn, uri, name, index, *xmlupd), delete xmlupd); } else { PROTECT2(con->con->addIndex(uri, name, index, *xmlupd), delete xmlupd); } break; } } return obj; } static VALUE xb_con_add_def_index(int argc, VALUE *argv, VALUE obj) { xupd *upd; VALUE a, b; char *index = 0; XmlUpdateContext *xmlupd = 0; xcon *con = get_con(obj); XmlTransaction *xmltxn = get_con_txn(con); switch(rb_scan_args(argc, argv, "11", &a, &b)) { case 2: { index = StringValuePtr(a); upd = get_upd(b); xmlupd = upd->upd; if (xmltxn) { PROTECT(con->con->addDefaultIndex(*xmltxn, index, *xmlupd)); } else { PROTECT(con->con->addDefaultIndex(index, *xmlupd)); } break; } case 1: { index = StringValuePtr(a); xman *man = get_man(con->man); xmlupd = new XmlUpdateContext(man->man->createUpdateContext()); if (xmltxn) { PROTECT2(con->con->addDefaultIndex(*xmltxn, index, *xmlupd), delete xmlupd); } else { PROTECT2(con->con->addDefaultIndex(index, *xmlupd), delete xmlupd); } break; } } return obj; } static VALUE xb_con_delete_index(int argc, VALUE *argv, VALUE obj) { xupd *upd; VALUE a, b, c, d; char *uri = 0, *name = 0, *index = 0; XmlUpdateContext *xmlupd = 0; xcon *con = get_con(obj); XmlTransaction *xmltxn = get_con_txn(con); switch(rb_scan_args(argc, argv, "31", &a, &b, &c, &d)) { case 4: { uri = StringValuePtr(a); name = StringValuePtr(b); index = StringValuePtr(c); upd = get_upd(d); xmlupd = upd->upd; if (xmltxn) { PROTECT(con->con->deleteIndex(*xmltxn, uri, name, index, *xmlupd)); } else { PROTECT(con->con->deleteIndex(uri, name, index, *xmlupd)); } break; } case 3: { uri = StringValuePtr(a); name = StringValuePtr(b); index = StringValuePtr(c); xman *man = get_man(con->man); xmlupd = new XmlUpdateContext(man->man->createUpdateContext()); if (xmltxn) { PROTECT2(con->con->deleteIndex(*xmltxn, uri, name, index, *xmlupd), delete xmlupd); } else { PROTECT2(con->con->deleteIndex(uri, name, index, *xmlupd), delete xmlupd); } break; } } return obj; } static VALUE xb_con_delete_def_index(int argc, VALUE *argv, VALUE obj) { xupd *upd; VALUE a, b; char *index = 0; XmlUpdateContext *xmlupd = 0; xcon *con = get_con(obj); XmlTransaction *xmltxn = get_con_txn(con); switch(rb_scan_args(argc, argv, "11", &a, &b)) { case 2: { index = StringValuePtr(a); upd = get_upd(b); xmlupd = upd->upd; if (xmltxn) { PROTECT(con->con->deleteDefaultIndex(*xmltxn, index, *xmlupd)); } else { PROTECT(con->con->deleteDefaultIndex(index, *xmlupd)); } break; } case 1: { index = StringValuePtr(a); xman *man = get_man(con->man); xmlupd = new XmlUpdateContext(man->man->createUpdateContext()); if (xmltxn) { PROTECT2(con->con->deleteDefaultIndex(*xmltxn, index, *xmlupd), delete xmlupd); } else { PROTECT2(con->con->deleteDefaultIndex(index, *xmlupd), delete xmlupd); } break; } } return obj; } static VALUE xb_con_replace_index(int argc, VALUE *argv, VALUE obj) { xupd *upd; VALUE a, b, c, d; char *uri = 0, *name = 0, *index = 0; XmlUpdateContext *xmlupd = 0; xcon *con = get_con(obj); XmlTransaction *xmltxn = get_con_txn(con); switch(rb_scan_args(argc, argv, "31", &a, &b, &c, &d)) { case 4: { uri = StringValuePtr(a); name = StringValuePtr(b); index = StringValuePtr(c); upd = get_upd(d); xmlupd = upd->upd; if (xmltxn) { PROTECT(con->con->replaceIndex(*xmltxn, uri, name, index, *xmlupd)); } else { PROTECT(con->con->replaceIndex(uri, name, index, *xmlupd)); } break; } case 3: { uri = StringValuePtr(a); name = StringValuePtr(b); index = StringValuePtr(c); xman *man = get_man(con->man); xmlupd = new XmlUpdateContext(man->man->createUpdateContext()); if (xmltxn) { PROTECT2(con->con->replaceIndex(*xmltxn, uri, name, index, *xmlupd), delete xmlupd); } else { PROTECT2(con->con->replaceIndex(uri, name, index, *xmlupd), delete xmlupd); } break; } } return obj; } static VALUE xb_con_replace_def_index(int argc, VALUE *argv, VALUE obj) { xupd *upd; VALUE a, b; char *index = 0; XmlUpdateContext *xmlupd = 0; xcon *con = get_con(obj); XmlTransaction *xmltxn = get_con_txn(con); switch(rb_scan_args(argc, argv, "11", &a, &b)) { case 2: { index = StringValuePtr(a); upd = get_upd(b); xmlupd = upd->upd; if (xmltxn) { PROTECT(con->con->replaceDefaultIndex(*xmltxn, index, *xmlupd)); } else { PROTECT(con->con->replaceDefaultIndex(index, *xmlupd)); } break; } case 1: { index = StringValuePtr(a); xman *man = get_man(con->man); xmlupd = new XmlUpdateContext(man->man->createUpdateContext()); if (xmltxn) { PROTECT2(con->con->replaceDefaultIndex(*xmltxn, index, *xmlupd), delete xmlupd); } else { PROTECT2(con->con->replaceDefaultIndex(index, *xmlupd), delete xmlupd); } break; } } return obj; } static void xb_ind_mark(xind *ind) { rb_gc_mark(ind->con); } static void xb_ind_free(xind *ind) { FREE_DEBUG("xb_ind_free %x\n", ind); if (ind->ind) { delete ind->ind; if (RTEST(ind->con)) { xcon *con = get_con(ind->con); con->ind = 0; } } ::free(ind); } static VALUE xb_con_index(int argc, VALUE *argv, VALUE obj) { XmlIndexSpecification *xmlind; VALUE a; xcon *con = get_con(obj); XmlTransaction *xmltxn = get_con_txn(con); if (RTEST(con->ind)) return con->ind; if (xmltxn) { int flags = 0; if (rb_scan_args(argc, argv, "01", &a) == 1) { flags = NUM2INT(a); } PROTECT(xmlind = new XmlIndexSpecification(con->con->getIndexSpecification(*xmltxn, flags))); } else { if (argc) { rb_raise(xb_eFatal, "invalid number of arguments (%d for 0)", argc); } PROTECT(xmlind = new XmlIndexSpecification(con->con->getIndexSpecification())); } xind *ind; VALUE res = Data_Make_Struct(xb_cInd, xind, (RDF)xb_ind_mark, (RDF)xb_ind_free, ind); ind->ind = xmlind; ind->con = obj; con->ind = res; return res; } static void add_ind(VALUE obj, VALUE a) { xcon *con = get_con(obj); if (con->ind == a) return; if (RTEST(con->ind)) { xind *ind = get_ind(con->ind); delete ind->ind; rset_obj(con->ind); } xind *ind = get_ind(a); if (ind->con != obj) { xcon *tmp = get_con(ind->con); tmp->ind = 0; } con->ind = a; } static VALUE xb_con_index_set(int argc, VALUE *argv, VALUE obj) { xupd *upd; XmlUpdateContext *xmlupd = 0; bool freeupd = true; VALUE a, b; rb_secure(4); xcon *con = get_con(obj); XmlTransaction *xmltxn = get_con_txn(con); if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { upd = get_upd(b); xmlupd = upd->upd; freeupd = false; } xind *ind = get_ind(a); if (freeupd) { xman *man = get_man(con->man); xmlupd = new XmlUpdateContext(man->man->createUpdateContext()); } if (xmltxn) { PROTECT2(con->con->setIndexSpecification(*xmltxn, *ind->ind, *xmlupd), if (freeupd) delete xmlupd); } else { PROTECT2(con->con->setIndexSpecification(*ind->ind, *xmlupd), if (freeupd) delete xmlupd); } add_ind(obj, a); return obj; } #if HAVE_DBXML_CON_INDEX_NODES static VALUE xb_con_index_p(VALUE obj) { xcon *con = get_con(obj); if (con->con->getIndexNodes()) { return Qtrue; } return Qfalse; } #endif #if HAVE_DBXML_CON_PAGESIZE static VALUE xb_con_pagesize(VALUE obj) { xcon *con = get_con(obj); return INT2NUM(con->con->getPageSize()); } #endif static VALUE xb_xml_val(XmlValue *, VALUE); #if HAVE_DBXML_CON_FLAGS static VALUE xb_con_flags(VALUE obj) { xcon *con = get_con(obj); return INT2NUM(con->con->getFlags()); } #endif #if HAVE_DBXML_CON_NODE static VALUE xb_con_node(int argc, VALUE *argv, VALUE obj) { VALUE a, b; XmlValue xmlval; int flags = 0; xcon *con = get_con(obj); XmlTransaction *xmltxn = get_con_txn(con); if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { flags = NUM2INT(b); } char *node = StringValuePtr(a); if (xmltxn) { PROTECT(xmlval = con->con->getNode(*xmltxn, node, flags)); } else { PROTECT(xmlval = con->con->getNode(node, flags)); } return xb_xml_val(&xmlval, con->man); } #endif #if HAVE_DBXML_XML_EVENT_WRITER static void xb_ewr_mark(xewr *ewr) { rb_gc_mark(ewr->con); } static void xb_ewr_free(xewr *ewr) { if (ewr->ewr) { PROTECT(ewr->ewr->close()); ewr->ewr = 0; } ::free(ewr); } static VALUE xb_con_ewr(int argc, VALUE *argv, VALUE obj) { VALUE a, b, c; XmlEventWriter *xmlewr; xewr *ewr; int flags = 0; xcon *con = get_con(obj); XmlTransaction *xmltxn = get_con_txn(con); if (rb_scan_args(argc, argv, "21", &a, &b, &c) == 3) { flags = NUM2INT(b); } xdoc *doc = get_doc(a); xupd *upd = get_upd(b); if (xmltxn) { PROTECT(XmlEventWriter &rex = con->con->putDocumentAsEventWriter(*xmltxn, *doc->doc, *upd->upd, flags); xmlewr = (XmlEventWriter *)&rex); } else { PROTECT(XmlEventWriter &rex = con->con->putDocumentAsEventWriter(*doc->doc, *upd->upd, flags); xmlewr = (XmlEventWriter *)&rex); } VALUE res = Data_Make_Struct(xb_cEwr, xewr, (RDF)xb_ewr_mark, (RDF)xb_ewr_free, ewr); ewr->ewr = xmlewr; ewr->con = obj; return res; } #endif static VALUE xb_con_get(int argc, VALUE *argv, VALUE obj) { XmlDocument *xmldoc; VALUE res; xdoc *doc; VALUE a, b; int flags = 0; if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { flags = NUM2INT(b); } char *name = StringValuePtr(a); xcon *con = get_con(obj); XmlTransaction *xmltxn = get_con_txn(con); if (xmltxn) { PROTECT(xmldoc = new XmlDocument(con->con->getDocument(*xmltxn, name, flags))); } else { PROTECT(xmldoc = new XmlDocument(con->con->getDocument(name, flags))); } res = Data_Make_Struct(xb_cDoc, xdoc, (RDF)xb_doc_mark, (RDF)xb_doc_free, doc); get_man(con->man); doc->doc = xmldoc; doc->man = con->man; return res; } static VALUE xb_con_stat(int argc, VALUE *argv, VALUE obj) { VALUE a, b, c, d, e, f; XmlValue xmlval = XmlValue(); XmlStatistics *stats; char *index = 0, *p_uri = 0, *p_name = 0; bool has_parent = false; double total, uniq; switch (rb_scan_args(argc, argv, "33", &a, &b, &c, &d, &e, &f)) { case 6: xmlval = xb_val_xml(f); /* ... */ case 5: p_uri = StringValuePtr(c); p_name = StringValuePtr(d); index = StringValuePtr(e); has_parent = true; break; case 4: xmlval = xb_val_xml(d); /* ... */ case 3: index = StringValuePtr(c); } char *uri = StringValuePtr(a); char *name = StringValuePtr(b); xcon *con = get_con(obj); XmlTransaction *xmltxn = get_con_txn(con); if (xmltxn) { PROTECT( if (has_parent) { stats = new XmlStatistics( con->con->lookupStatistics(*xmltxn, uri, name, p_uri, p_name, index, xmlval)); } else { stats = new XmlStatistics( con->con->lookupStatistics(*xmltxn, uri, name, index, xmlval)); } total = stats->getNumberOfIndexedKeys(); uniq = stats->getNumberOfUniqueKeys(); delete stats; ); } else { PROTECT( if (has_parent) { stats = new XmlStatistics( con->con->lookupStatistics(uri, name, p_uri, p_name, index, xmlval)); } else { stats = new XmlStatistics( con->con->lookupStatistics(uri, name, index, xmlval)); } total = stats->getNumberOfIndexedKeys(); uniq = stats->getNumberOfUniqueKeys(); delete stats; ); } return rb_assoc_new(rb_float_new(total), rb_float_new(uniq)); } static VALUE xb_con_lookup(int argc, VALUE *argv, VALUE obj) { VALUE a, b, c, d, e, f; XmlValue xmlval = XmlValue(); XmlResults *xmlres; char *index = 0, *p_uri = 0, *p_name = 0; bool has_parent = false; XmlQueryContext *xmlcxt; bool freecxt = false; if (argc && TYPE(argv[0]) == T_DATA && RDATA(argv[0])->dfree == (RDF)xb_cxt_free) { xcxt *cxt = get_cxt(argv[0]); xmlcxt = cxt->cxt; argc--; argv++; } else { xcon *con = get_con(obj); xman *man = get_man(con->man); xmlcxt = new XmlQueryContext(man->man->createQueryContext()); freecxt = true; } switch (rb_scan_args(argc, argv, "33", &a, &b, &c, &d, &e, &f)) { case 6: xmlval = xb_val_xml(f); /* ... */ case 5: p_uri = StringValuePtr(c); p_name = StringValuePtr(d); index = StringValuePtr(e); has_parent = true; break; case 4: xmlval = xb_val_xml(d); /* ... */ case 3: index = StringValuePtr(c); } char *uri = StringValuePtr(a); char *name = StringValuePtr(b); xcon *con = get_con(obj); XmlTransaction *xmltxn = get_con_txn(con); if (xmltxn) { PROTECT2( if (has_parent) { xmlres = new XmlResults( con->con->lookupIndex(*xmltxn, *xmlcxt, uri, name, p_uri, p_name, index, xmlval)); } else { xmlres = new XmlResults( con->con->lookupIndex(*xmltxn, *xmlcxt, uri, name, index, xmlval)); }, if (freecxt) delete xmlcxt); } else { PROTECT2( if (has_parent) { xmlres = new XmlResults( con->con->lookupIndex(*xmlcxt, uri, name, p_uri, p_name, index, xmlval)); } else { xmlres = new XmlResults( con->con->lookupIndex(*xmlcxt, uri, name, index, xmlval)); }, if (freecxt) delete xmlcxt); } xres *res; VALUE result = Data_Make_Struct(xb_cRes, xres, (RDF)xb_res_mark, (RDF)xb_res_free, res); res->res = xmlres; res->man = con->man; return result; } static VALUE xb_ind_manager(VALUE obj) { xind *ind = get_ind(obj); return xb_con_manager(ind->con); } static VALUE xb_ind_container(VALUE obj) { xind *ind = get_ind(obj); if (RTEST(ind->con)) return ind->con; return Qnil; } static VALUE xb_ind_default(VALUE obj) { std::string def; xind *ind = get_ind(obj); PROTECT(def = ind->ind->getDefaultIndex()); return rb_tainted_str_new2(def.c_str()); } static VALUE xb_ind_add_default(int argc, VALUE *argv, VALUE obj) { VALUE a, b; xind *ind = get_ind(obj); if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { XmlIndexSpecification::Type type = XmlIndexSpecification::Type(NUM2INT(a)); XmlValue::Type syntax = XmlValue::Type(NUM2INT(b)); PROTECT(ind->ind->addDefaultIndex(type, syntax)); } else { char *as = StringValuePtr(a); PROTECT(ind->ind->addDefaultIndex(as)); } return obj; } static VALUE xb_ind_add(int argc, VALUE *argv, VALUE obj) { VALUE a, b, c, d; char *uri, *name; xind *ind = get_ind(obj); switch (rb_scan_args(argc, argv, "31", &a, &b, &c, &d)) { case 4: { XmlIndexSpecification::Type type = XmlIndexSpecification::Type(NUM2INT(c)); XmlValue::Type syntax = XmlValue::Type(NUM2INT(d)); uri = StringValuePtr(a); name = StringValuePtr(b); PROTECT(ind->ind->addIndex(uri, name, type, syntax)); break; } case 3: { char *index = StringValuePtr(c); uri = StringValuePtr(a); name = StringValuePtr(b); PROTECT(ind->ind->addIndex(uri, name, index)); break; } default: rb_raise(rb_eArgError, "invalid number of arguments"); } return obj; } static VALUE xb_ind_delete_default(int argc, VALUE *argv, VALUE obj) { VALUE a, b; xind *ind = get_ind(obj); if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { XmlIndexSpecification::Type type = XmlIndexSpecification::Type(NUM2INT(a)); XmlValue::Type syntax = XmlValue::Type(NUM2INT(b)); PROTECT(ind->ind->deleteDefaultIndex(type, syntax)); } else { char *as = StringValuePtr(a); PROTECT(ind->ind->deleteDefaultIndex(as)); } return obj; } static VALUE xb_ind_delete(int argc, VALUE *argv, VALUE obj) { VALUE a, b, c, d; char *uri, *name; xind *ind = get_ind(obj); switch (rb_scan_args(argc, argv, "22", &a, &b, &c, &d)) { case 4: { XmlIndexSpecification::Type type = XmlIndexSpecification::Type(NUM2INT(c)); XmlValue::Type syntax = XmlValue::Type(NUM2INT(d)); uri = StringValuePtr(a); name = StringValuePtr(b); PROTECT(ind->ind->deleteIndex(uri, name, type, syntax)); break; } case 3: { char *index = StringValuePtr(c); uri = StringValuePtr(a); name = StringValuePtr(b); PROTECT(ind->ind->deleteIndex(uri, name, index)); break; } default: rb_raise(rb_eArgError, "invalid number of arguments"); } return obj; } static VALUE xb_ind_replace_default(int argc, VALUE *argv, VALUE obj) { VALUE a, b; xind *ind = get_ind(obj); if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { XmlIndexSpecification::Type type = XmlIndexSpecification::Type(NUM2INT(a)); XmlValue::Type syntax = XmlValue::Type(NUM2INT(b)); PROTECT(ind->ind->replaceDefaultIndex(type, syntax)); } else { char *as = StringValuePtr(a); PROTECT(ind->ind->replaceDefaultIndex(as)); } return obj; } static VALUE xb_ind_replace(int argc, VALUE *argv, VALUE obj) { VALUE a, b, c, d; char *uri, *name; xind *ind = get_ind(obj); switch (rb_scan_args(argc, argv, "31", &a, &b, &c, &d)) { case 4: { XmlIndexSpecification::Type type = XmlIndexSpecification::Type(NUM2INT(c)); XmlValue::Type syntax = XmlValue::Type(NUM2INT(d)); uri = StringValuePtr(a); name = StringValuePtr(b); PROTECT(ind->ind->replaceIndex(uri, name, type, syntax)); break; } case 3: { char *index = StringValuePtr(c); uri = StringValuePtr(a); name = StringValuePtr(b); PROTECT(ind->ind->replaceIndex(uri, name, index)); break; } default: rb_raise(rb_eArgError, "invalid number of arguments"); } return obj; } static VALUE xb_ind_each(VALUE obj) { std::string uri, name, index; VALUE ret; xind *ind = get_ind(obj); PROTECT(ind->ind->reset()); while (ind->ind->next(uri, name, index)) { ret = rb_ary_new2(3); rb_ary_push(ret, rb_tainted_str_new2(uri.c_str())); rb_ary_push(ret, rb_tainted_str_new2(name.c_str())); rb_ary_push(ret, rb_tainted_str_new2(index.c_str())); rb_yield(ret); } return Qnil; } static VALUE xb_ind_to_a(VALUE obj) { std::string uri, name, index; VALUE ret, res; xind *ind = get_ind(obj); PROTECT(ind->ind->reset()); res = rb_ary_new(); while (ind->ind->next(uri, name, index)) { ret = rb_ary_new2(3); rb_ary_push(ret, rb_tainted_str_new2(uri.c_str())); rb_ary_push(ret, rb_tainted_str_new2(name.c_str())); rb_ary_push(ret, rb_tainted_str_new2(index.c_str())); rb_ary_push(res, ret); } return res; } static VALUE xb_ind_each_type(VALUE obj) { std::string uri, name; XmlIndexSpecification::Type type; XmlValue::Type syntax; VALUE ret; xind *ind = get_ind(obj); PROTECT(ind->ind->reset()); while (ind->ind->next(uri, name, type, syntax)) { ret = rb_ary_new2(4); rb_ary_push(ret, rb_tainted_str_new2(uri.c_str())); rb_ary_push(ret, rb_tainted_str_new2(name.c_str())); rb_ary_push(ret, INT2NUM(type)); rb_ary_push(ret, INT2NUM(syntax)); rb_yield(ret); } return Qnil; } static VALUE xb_ind_find(int argc, VALUE *argv, VALUE obj) { char *uri, *name; std::string index; xind *ind = get_ind(obj); if (argc == 1) { name = StringValuePtr(argv[0]); uri = (char *)""; } else { if (argc != 2) { rb_raise(xb_eFatal, "invalid number of arguments (%d for 2)", argc); } uri = StringValuePtr(argv[0]); name = StringValuePtr(argv[1]); } if (ind->ind->find(uri, name, index)) { return rb_tainted_str_new2(index.c_str()); } return Qnil; } #if HAVE_DBXML_XML_INDEX_LOOKUP static void xb_look_mark(xlook *look) { rb_gc_mark(look->txn); rb_gc_mark(look->man); rb_gc_mark(look->con); } static void xb_look_free(xlook *look) { FREE_DEBUG("xb_look_free %x\n", look); if (look->look) { delete look->look; if (RTEST(look->con)) { xcon *con = get_con(look->con); con->look = 0; } } ::free(look); } static void add_look(VALUE obj, VALUE a) { xcon *con = get_con(obj); if (con->look == a) return; if (RTEST(con->look)) { xlook *look = get_look(con->look); delete look->look; rset_obj(con->look); } xlook *look = get_look(a); if (look->con != obj) { xcon *tmp = get_con(look->con); tmp->look = 0; } con->look = a; } static VALUE xb_man_create_look(int argc, VALUE *argv, VALUE obj) { XmlIndexLookup *xmllook; xlook *look; XmlValue xmlval = XmlValue(); XmlIndexLookup::Operation xmlop = XmlIndexLookup::EQ; VALUE a, b, c, d, e, f, res; rb_secure(4); xman *man = get_man_txn(obj); switch(rb_scan_args(argc, argv, "42", &a, &b, &c, &d, &e, &f)) { case 6: xmlop = XmlIndexLookup::Operation(NUM2INT(f)); /* ... */ case 5: if (!NIL_P(e)) { xmlval = xb_val_xml(e); } /* ... */ } xcon *con = get_con(a); char *uri = StringValuePtr(b); char *name = StringValuePtr(c); char *index = StringValuePtr(d); PROTECT(xmllook = new XmlIndexLookup(man->man->createIndexLookup(*con->con, uri, name, index, xmlval, xmlop))); res = Data_Make_Struct(xb_cLook, xlook, (RDF)xb_look_mark, (RDF)xb_look_free, look); look->look = xmllook; if (rb_obj_is_kind_of(obj, xb_cTxn)) { look->txn = obj; look->man = get_txn_man(obj); } else { look->man = obj; } look->con = a; add_look(a, res); return res; } static VALUE xb_look_manager(VALUE obj) { xlook *look = get_look(obj); return look->man; } static VALUE xb_look_transaction(VALUE obj) { xlook *look = get_look(obj); return look->txn; } static VALUE xb_look_transaction_p(VALUE obj) { xlook *look = get_look(obj); if (RTEST(look->txn)) { return Qtrue; } return Qfalse; } static VALUE xb_look_container_set(VALUE obj, VALUE a) { xlook *look = get_look(obj); xcon *con = get_con(a); PROTECT(look->look->setContainer(*con->con)); look->con = a; add_look(a, obj); return a; } static VALUE xb_look_container_get(VALUE obj) { xlook *look = get_look(obj); return look->con; } static VALUE xb_look_highbound_set(VALUE obj, VALUE a) { xlook *look = get_look(obj); a = rb_Array(a); if (RARRAY_LEN(a) != 2) { rb_raise(rb_eArgError, "invalid argument [value, operation]"); } XmlValue xmlval = xb_val_xml(RARRAY_PTR(a)[0]); XmlIndexLookup::Operation xmlop = XmlIndexLookup::Operation(NUM2INT(RARRAY_PTR(a)[1])); PROTECT(look->look->setHighBound(xmlval, xmlop)); return a; } static VALUE xb_look_highbound_get(VALUE obj) { xlook *look = get_look(obj); XmlIndexLookup::Operation xmlop = look->look->getHighBoundOperation(); XmlValue xmlval; PROTECT(xmlval = look->look->getHighBoundValue()); VALUE a = xb_xml_val(&xmlval, look->man); return rb_assoc_new(a, INT2NUM(xmlop)); } static VALUE xb_look_lowbound_set(VALUE obj, VALUE a) { xlook *look = get_look(obj); a = rb_Array(a); if (RARRAY_LEN(a) != 2) { rb_raise(rb_eArgError, "invalid argument [value, operation]"); } XmlValue xmlval = xb_val_xml(RARRAY_PTR(a)[0]); XmlIndexLookup::Operation xmlop = XmlIndexLookup::Operation(NUM2INT(RARRAY_PTR(a)[1])); PROTECT(look->look->setLowBound(xmlval, xmlop)); return a; } static VALUE xb_look_lowbound_get(VALUE obj) { xlook *look = get_look(obj); XmlIndexLookup::Operation xmlop = look->look->getLowBoundOperation(); XmlValue xmlval; PROTECT(xmlval = look->look->getLowBoundValue()); VALUE a = xb_xml_val(&xmlval, look->man); return rb_assoc_new(a, INT2NUM(xmlop)); } static VALUE xb_look_index_set(VALUE obj, VALUE a) { xlook *look = get_look(obj); char *index = StringValuePtr(a); PROTECT(look->look->setIndex(index)); return a; } static VALUE xb_look_index_get(VALUE obj) { xlook *look = get_look(obj); std::string index; PROTECT(index = look->look->getIndex()); return rb_tainted_str_new2(index.c_str()); } static VALUE xb_look_node_set(VALUE obj, VALUE a) { xlook *look = get_look(obj); a = rb_Array(a); if (RARRAY_LEN(a) != 2) { rb_raise(rb_eArgError, "invalid argument [uri, name]"); } char *uri = StringValuePtr(RARRAY_PTR(a)[0]); char *name = StringValuePtr(RARRAY_PTR(a)[1]); PROTECT(look->look->setNode(uri, name)); return a; } static VALUE xb_look_node_uri_get(VALUE obj) { xlook *look = get_look(obj); std::string uri; PROTECT(uri = look->look->getNodeURI()); return rb_tainted_str_new2(uri.c_str()); } static VALUE xb_look_node_uri_set(VALUE obj, VALUE a) { xlook *look = get_look(obj); char *uri = StringValuePtr(a); PROTECT(look->look->setNode(uri, look->look->getNodeName())); return a; } static VALUE xb_look_node_name_get(VALUE obj) { xlook *look = get_look(obj); std::string name; PROTECT(name = look->look->getNodeName()); return rb_tainted_str_new2(name.c_str()); } static VALUE xb_look_node_name_set(VALUE obj, VALUE a) { xlook *look = get_look(obj); char *name = StringValuePtr(a); PROTECT(look->look->setNode(look->look->getNodeURI(), name)); return a; } static VALUE xb_look_node_get(VALUE obj) { return rb_assoc_new(xb_look_node_uri_get(obj), xb_look_node_name_get(obj)); } static VALUE xb_look_parent_set(VALUE obj, VALUE a) { xlook *look = get_look(obj); a = rb_Array(a); if (RARRAY_LEN(a) != 2) { rb_raise(rb_eArgError, "invalid argument [uri, name]"); } char *uri = StringValuePtr(RARRAY_PTR(a)[0]); char *name = StringValuePtr(RARRAY_PTR(a)[1]); PROTECT(look->look->setParent(uri, name)); return a; } static VALUE xb_look_parent_uri_get(VALUE obj) { xlook *look = get_look(obj); std::string uri; PROTECT(uri = look->look->getParentURI()); return rb_tainted_str_new2(uri.c_str()); } static VALUE xb_look_parent_uri_set(VALUE obj, VALUE a) { xlook *look = get_look(obj); char *uri = StringValuePtr(a); PROTECT(look->look->setParent(uri, look->look->getParentName())); return a; } static VALUE xb_look_parent_name_get(VALUE obj) { xlook *look = get_look(obj); std::string name; PROTECT(name = look->look->getParentName()); return rb_tainted_str_new2(name.c_str()); } static VALUE xb_look_parent_name_set(VALUE obj, VALUE a) { xlook *look = get_look(obj); char *name = StringValuePtr(a); PROTECT(look->look->setParent(look->look->getParentURI(), name)); return a; } static VALUE xb_look_parent_get(VALUE obj) { return rb_assoc_new(xb_look_parent_uri_get(obj), xb_look_parent_name_get(obj)); } static VALUE xb_look_execute(int argc, VALUE *argv, VALUE obj) { xlook *look = get_look(obj); XmlQueryContext *xmlcxt; xcxt *cxt; VALUE a, b; int flags = 0; bool freecxt = true; switch(rb_scan_args(argc, argv, "02", &a, &b)) { case 2: flags = NUM2INT(b); /* ... */ case 1: if (!NIL_P(a)) { cxt = get_cxt(a); xmlcxt = cxt->cxt; freecxt = false; } } if (freecxt) { xman *man = get_man(look->man); xmlcxt = new XmlQueryContext(man->man->createQueryContext()); } XmlResults *xmlres; if (!RTEST(look->txn)) { PROTECT2(xmlres = new XmlResults(look->look->execute(*xmlcxt, flags)), if (freecxt) delete xmlcxt;); } else { bdb_TXN *txnst; GetTxnDBErr(look->txn, txnst, xb_eFatal); XmlTransaction *xmltxn = (XmlTransaction *)txnst->txn_cxx; PROTECT2(xmlres = new XmlResults(look->look->execute(*xmltxn, *xmlcxt, flags)), if (freecxt) delete xmlcxt;); } xres *res; VALUE result = Data_Make_Struct(xb_cRes, xres, (RDF)xb_res_mark, (RDF)xb_res_free, res); res->res = xmlres; res->man = look->man; if (rb_block_given_p()) { #if HAVE_RB_BLOCK_CALL return rb_block_call(result, rb_intern("each"), 0, 0, (VALUE(*)(ANYARGS))rb_yield, Qnil); #else return rb_iterate(rb_each, result, (VALUE(*)(ANYARGS))rb_yield, Qnil); #endif } return result; } #endif static void xb_val_mark(xval *val) { rb_gc_mark(val->man); } static void val_free(xval *val) { if (val->val) { delete val->val; val->val = 0; } } static void xb_val_free(xval *val) { FREE_DEBUG("xb_val_free %x\n", val); val_free(val); ::free(val); } static VALUE xb_val_close(VALUE obj) { xval *val; Data_Get_Struct(obj, xval, val); val_free(val); rset_obj(obj); return Qnil; } static VALUE xb_xml_val(XmlValue *xmlval, VALUE man) { VALUE res; if (xmlval->isNull()) { return Qnil; } if (xmlval->isString()) { return rb_tainted_str_new2(xmlval->asString().c_str()); } if (xmlval->isNumber()) { return rb_float_new(xmlval->asNumber()); } if (xmlval->isBoolean()) { if (xmlval->asBoolean()) { return Qtrue; } return Qfalse; } xval *val; res = Data_Make_Struct(xb_cVal, xval, (RDF)xb_val_mark, (RDF)xb_val_free, val); val->val = new XmlValue(*xmlval); val->man = man; return res; } static XmlValue xb_val_xml(VALUE a) { XmlValue xmlval; if (NIL_P(a)) { return XmlValue(); } switch (TYPE(a)) { case T_STRING: xmlval = XmlValue(StringValuePtr(a)); break; case T_FIXNUM: case T_FLOAT: case T_BIGNUM: xmlval = XmlValue(NUM2DBL(a)); break; case T_TRUE: xmlval = XmlValue(true); break; case T_FALSE: xmlval = XmlValue(false); break; case T_DATA: if (RDATA(a)->dmark == (RDF)xb_doc_mark) { xdoc *doc; Data_Get_Struct(a, xdoc, doc); xmlval = XmlValue(*(doc->doc)); break; } if (RDATA(a)->dmark == (RDF)xb_val_mark) { xval *val; Data_Get_Struct(a, xval, val); xmlval = XmlValue(*(val->val)); break; } /* ... */ default: xmlval = XmlValue(StringValuePtr(a)); break; } return xmlval; } static VALUE xb_doc_manager(VALUE obj) { xdoc *doc = get_doc(obj); return doc->man; } static VALUE xb_doc_name_get(VALUE obj) { xdoc *doc = get_doc(obj); return rb_tainted_str_new2(doc->doc->getName().c_str()); } static VALUE xb_doc_name_set(VALUE obj, VALUE a) { xdoc *doc = get_doc(obj); char *str = StringValuePtr(a); PROTECT(doc->doc->setName(str)); return a; } static VALUE xb_doc_content_str(VALUE obj) { std::string str; xdoc *doc = get_doc(obj); PROTECT(str = doc->doc->getContent(str)); return rb_tainted_str_new2(str.c_str()); } static VALUE xb_doc_content_set(VALUE obj, VALUE a) { xdoc *doc = get_doc(obj); #if HAVE_DBXML_XML_EVENT_READER if (TYPE(a) == T_DATA && RDATA(a)->dmark == (RDF)xb_erd_mark) { xerd *erd = get_erd(a); PROTECT(doc->doc->setContentAsEventReader(*erd->erd)); erd->erd = 0; return a; } #endif char *str = StringValuePtr(a); PROTECT(doc->doc->setContent(str)); return a; } static VALUE xb_doc_get(int argc, VALUE *argv, VALUE obj) { std::string uri = ""; std::string name; XmlValue val; VALUE a, b; if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { if (!NIL_P(a)) { uri = StringValuePtr(a); } name = StringValuePtr(b); } else { name = StringValuePtr(a); } xdoc *doc = get_doc(obj); if (doc->doc->getMetaData(uri, name, val)) { return xb_xml_val(&val, doc->man); } return Qnil; } static VALUE xb_doc_set(int argc, VALUE *argv, VALUE obj) { std::string uri = ""; std::string name; XmlValue val; VALUE a, b, c; if (rb_scan_args(argc, argv, "21", &a, &b, &c) == 3) { uri = StringValuePtr(a); name = StringValuePtr(b); val = xb_val_xml(c); } else { name = StringValuePtr(a); val = xb_val_xml(b); } xdoc *doc = get_doc(obj); PROTECT(doc->doc->setMetaData(uri, name, val)); return obj; } static VALUE xb_doc_remove(int argc, VALUE *argv, VALUE obj) { std::string uri = ""; std::string name; VALUE a, b; if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { uri = StringValuePtr(a); name = StringValuePtr(b); } else { name = StringValuePtr(a); } xdoc *doc = get_doc(obj); PROTECT(doc->doc->removeMetaData(uri, name)); return obj; } static VALUE xb_doc_each(VALUE obj) { std::string uri = ""; std::string name; XmlValue val; VALUE ary; xdoc *doc = get_doc(obj); XmlMetaDataIterator iter = doc->doc->getMetaDataIterator(); while (iter.next(uri, name, val)) { ary = rb_ary_new2(3); rb_ary_push(ary, rb_tainted_str_new2(uri.c_str())); rb_ary_push(ary, rb_tainted_str_new2(name.c_str())); rb_ary_push(ary, xb_xml_val(&val, doc->man)); rb_yield(ary); } return obj; } static VALUE xb_doc_fetch(VALUE obj) { xdoc *doc = get_doc(obj); doc->doc->fetchAllData(); return obj; } static VALUE xb_cxt_manager(VALUE obj) { xcxt *cxt = get_cxt(obj); return cxt->man; } static VALUE xb_cxt_uri_set(VALUE obj, VALUE a) { xcxt *cxt = get_cxt(obj); char *uri = StringValuePtr(a); PROTECT(cxt->cxt->setBaseURI(uri)); return a; } static VALUE xb_cxt_uri_get(VALUE obj) { xcxt *cxt = get_cxt(obj); std::string uri; PROTECT(uri = cxt->cxt->getBaseURI()); return rb_tainted_str_new2(uri.c_str()); } static VALUE xb_cxt_name_get(VALUE obj, VALUE a) { std::string uri; xcxt *cxt = get_cxt(obj); char *prefix = StringValuePtr(a); PROTECT(uri = cxt->cxt->getNamespace(prefix)); return rb_tainted_str_new2(uri.c_str()); } static VALUE xb_cxt_name_set(VALUE obj, VALUE a, VALUE b) { xcxt *cxt = get_cxt(obj); char *prefix = StringValuePtr(a); char *uri = StringValuePtr(b); PROTECT(cxt->cxt->setNamespace(prefix, uri)); return obj; } static VALUE xb_cxt_name_del(VALUE obj, VALUE a) { xcxt *cxt = get_cxt(obj); char *prefix = StringValuePtr(a); PROTECT(cxt->cxt->removeNamespace(prefix)); return obj; } static VALUE xb_cxt_clear(VALUE obj) { xcxt *cxt = get_cxt(obj); PROTECT(cxt->cxt->clearNamespaces()); return obj; } static VALUE xb_cxt_get(VALUE obj, VALUE a) { xcxt *cxt = get_cxt(obj); char *name = StringValuePtr(a); XmlValue xmlval; PROTECT(cxt->cxt->getVariableValue(name, xmlval)); return xb_xml_val(&xmlval, cxt->man); } #if HAVE_DBXML_CXT_VARIABLE_VALUE static VALUE xb_cxt_get_results(VALUE obj, VALUE a) { xcxt *cxt = get_cxt(obj); char *name = StringValuePtr(a); XmlResults xmlres; PROTECT(cxt->cxt->getVariableValue(name, xmlres)); xres *res; VALUE result = Data_Make_Struct(xb_cRes, xres, (RDF)xb_res_mark, (RDF)xb_res_free, res); res->res = new XmlResults(xmlres); res->man = cxt->man; return result; } #endif static VALUE xb_cxt_set(VALUE obj, VALUE a, VALUE b) { xcxt *cxt = get_cxt(obj); char *name = StringValuePtr(a); if (TYPE(b) == T_DATA && RDATA(b)->dfree == (RDF)xb_res_free) { xres *res = get_res(b); PROTECT(cxt->cxt->setVariableValue(name, res->res)); } else { XmlValue xmlval = xb_val_xml(b); PROTECT(cxt->cxt->setVariableValue(name, xmlval)); } return obj; } static VALUE xb_cxt_eval_set(VALUE obj, VALUE a) { xcxt *cxt = get_cxt(obj); XmlQueryContext::EvaluationType type = XmlQueryContext::EvaluationType(NUM2INT(a)); PROTECT(cxt->cxt->setEvaluationType(type)); return a; } static VALUE xb_cxt_eval_get(VALUE obj) { xcxt *cxt = get_cxt(obj); XmlQueryContext::EvaluationType type; PROTECT(type = cxt->cxt->getEvaluationType()); return INT2NUM(type); } static VALUE xb_cxt_return_set(VALUE obj, VALUE a) { xcxt *cxt = get_cxt(obj); XmlQueryContext::ReturnType type = XmlQueryContext::ReturnType(NUM2INT(a)); PROTECT(cxt->cxt->setReturnType(type)); return a; } static VALUE xb_cxt_return_get(VALUE obj) { xcxt *cxt = get_cxt(obj); XmlQueryContext::ReturnType type; PROTECT(type = cxt->cxt->getReturnType()); return INT2NUM(type); } #if HAVE_DBXML_CXT_COLLECTION static VALUE xb_cxt_coll_set(VALUE obj, VALUE a) { xcxt *cxt = get_cxt(obj); char *uri = StringValuePtr(a); PROTECT(cxt->cxt->setDefaultCollection(uri)); return a; } static VALUE xb_cxt_coll_get(VALUE obj) { xcxt *cxt = get_cxt(obj); std::string uri; PROTECT(uri = cxt->cxt->getDefaultCollection()); return rb_tainted_str_new2(uri.c_str()); } #endif #if HAVE_DBXML_CXT_INTERRUPT static VALUE xb_cxt_interrupt(VALUE obj) { xcxt *cxt = get_cxt(obj); cxt->cxt->interruptQuery(); return Qnil; } #endif #if HAVE_DBXML_CXT_TIMEOUT static VALUE xb_cxt_get_timeout(VALUE obj) { xcxt *cxt = get_cxt(obj); int to; PROTECT(to = cxt->cxt->getQueryTimeoutSeconds()); return INT2NUM(to); } static VALUE xb_cxt_set_timeout(VALUE obj, VALUE a) { xcxt *cxt = get_cxt(obj); PROTECT(cxt->cxt->setQueryTimeoutSeconds(NUM2INT(a))); return a; } #endif static VALUE xb_que_manager(VALUE obj) { xque *que = get_que(obj); return que->man; } static VALUE xb_que_txn_p(VALUE obj) { xque *que = get_que(obj); if (RTEST(que->txn)) { return Qtrue; } return Qfalse; } static VALUE xb_que_txn(VALUE obj) { xque *que = get_que(obj); if (RTEST(que->txn)) { return que->txn; } return Qnil; } static VALUE xb_que_to_str(VALUE obj) { xque *que = get_que(obj); std::string qe; PROTECT(qe = que->que->getQuery()); return rb_tainted_str_new2(qe.c_str()); } static VALUE xb_que_exec(int argc, VALUE *argv, VALUE obj) { XmlTransaction *xmltxn = 0; XmlQueryContext *xmlcxt; xcxt *cxt; XmlValue xmlval; bool has_cxt = true; bool has_val = false; int flags = 0; xque *que = get_que(obj); switch (argc) { case 0: { xman *man = get_man(que->man); xmlcxt = new XmlQueryContext(man->man->createQueryContext()); has_cxt = false; } break; case 1: if (TYPE(argv[0]) == T_DATA && RDATA(argv[0])->dfree == (RDF)xb_cxt_free) { cxt = get_cxt(argv[0]); xmlcxt = cxt->cxt; } else { xmlval = xb_val_xml(argv[0]); has_val = true; xman *man = get_man(que->man); xmlcxt = new XmlQueryContext(man->man->createQueryContext()); has_cxt = false; } break; case 2: if (TYPE(argv[0]) == T_DATA && RDATA(argv[0])->dfree == (RDF)xb_cxt_free) { cxt = get_cxt(argv[0]); xmlcxt = cxt->cxt; flags = NUM2INT(argv[1]); } else { cxt = get_cxt(argv[1]); xmlcxt = cxt->cxt; xmlval = xb_val_xml(argv[0]); has_val = true; } break; case 3: cxt = get_cxt(argv[1]); xmlcxt = cxt->cxt; xmlval = xb_val_xml(argv[0]); has_val = true; flags = NUM2INT(argv[2]); break; default: rb_raise(rb_eArgError, "invalid number of arguments"); break; } if (RTEST(que->txn)) { bdb_TXN *txnst; GetTxnDBErr(que->txn, txnst, xb_eFatal); xmltxn = (XmlTransaction *)txnst->txn_cxx; } XmlResults *xmlres; if (has_val) { if (xmltxn) { PROTECT2(xmlres = new XmlResults(que->que->execute(*xmltxn, xmlval, *xmlcxt, flags)), if (!has_cxt) delete xmlcxt;); } else { PROTECT2(xmlres = new XmlResults(que->que->execute(xmlval, *xmlcxt, flags)), if (!has_cxt) delete xmlcxt;); } } else { if (xmltxn) { PROTECT2(xmlres = new XmlResults(que->que->execute(*xmltxn, *xmlcxt, flags)), if (!has_cxt) delete xmlcxt;); } else { PROTECT2(xmlres = new XmlResults(que->que->execute(*xmlcxt, flags)), if (!has_cxt) delete xmlcxt;); } } xres *res; VALUE result = Data_Make_Struct(xb_cRes, xres, (RDF)xb_res_mark, (RDF)xb_res_free, res); res->res = xmlres; res->man = que->man; if (rb_block_given_p()) { #if HAVE_RB_BLOCK_CALL return rb_block_call(result, rb_intern("each"), 0, 0, (VALUE(*)(ANYARGS))rb_yield, Qnil); #else return rb_iterate(rb_each, result, (VALUE(*)(ANYARGS))rb_yield, Qnil); #endif } return result; } #if HAVE_DBXML_QUE_UPDATE static VALUE xb_que_update(VALUE obj) { xque *que = get_que(obj); if (que->que->isUpdateExpression()) { return Qtrue; } return Qfalse; } #endif static VALUE xb_res_manager(VALUE obj) { xres *res = get_res(obj); return res->man; } static VALUE xb_res_add(VALUE obj, VALUE a) { xres *res = get_res(obj); XmlValue val = xb_val_xml(a); PROTECT(res->res->add(val)); return a; } static VALUE xb_res_size(VALUE obj) { size_t size; xres *res = get_res(obj); PROTECT(size = res->res->size()); return INT2NUM(size); } #if HAVE_DBXML_RES_EVAL static VALUE xb_res_eval(VALUE obj) { XmlQueryContext::EvaluationType eval; xres *res = get_res(obj); PROTECT(eval = res->res->getEvaluationType()); return INT2NUM(eval); } #endif static VALUE xb_res_each(VALUE obj) { XmlValue xmlval; if (!rb_block_given_p()) { rb_raise(rb_eArgError, "block not supplied"); } xres *res = get_res(obj); PROTECT(res->res->reset()); while (res->res->next(xmlval)) { rb_yield(xb_xml_val(&xmlval, res->man)); } return obj; } static VALUE xb_con_each(VALUE obj) { if (!rb_block_given_p()) { rb_raise(rb_eArgError, "block not supplied"); } return xb_res_each(xb_con_all(0, NULL, obj)); } static void xb_mod_mark(xmod *mod) { rb_gc_mark(mod->man); } static void xb_mod_free(xmod *mod) { FREE_DEBUG("xb_mod_free %x\n", mod); if (mod->mod) { delete mod->mod; } ::free(mod); } static VALUE xb_int_create_mod(VALUE obj, VALUE orig) { XmlModify *xmlmod; xmod *mod; xman *man = get_man(obj); PROTECT(xmlmod = new XmlModify(man->man->createModify())); VALUE res; if (!orig) { res = Data_Make_Struct(xb_cMod, xmod, (RDF)xb_mod_mark, (RDF)xb_mod_free, mod); } else { res = orig; Data_Get_Struct(res, xmod, mod); RDATA(res)->dfree = (RDF)xb_mod_free; } mod->man = obj; mod->mod = xmlmod; return res; } static VALUE xb_man_create_mod(VALUE obj) { return xb_int_create_mod(obj, 0); } static VALUE xb_mod_s_alloc(VALUE obj) { xmod *mod; return Data_Make_Struct(obj, xmod, (RDF)xb_mod_mark, (RDF)free, mod); } static VALUE xb_mod_init(VALUE obj, VALUE a) { return xb_int_create_mod(a, obj); } static VALUE xb_mod_manager(VALUE obj) { xmod *mod = get_mod(obj); return mod->man; } static VALUE xb_mod_txn_p(VALUE obj) { xmod *mod = get_mod(obj); if (RTEST(mod->txn)) { return Qtrue; } return Qfalse; } static VALUE xb_mod_txn(VALUE obj) { xmod *mod = get_mod(obj); if (RTEST(mod->txn)) { return mod->txn; } return Qnil; } #if HAVE_DBXML_MOD_ENCODING static VALUE xb_mod_encoding(VALUE obj, VALUE a) { char *encoding = StringValuePtr(a); xmod *mod = get_mod(obj); PROTECT(mod->mod->setNewEncoding(encoding)); return a; } #endif static VALUE xb_mod_append(int argc, VALUE *argv, VALUE obj) { VALUE a, b, c, d, e; #if HAVE_DBXML_MOD_APPEND_STEP_RES xres *res = NULL; #endif char *content = 0; int location = -1; if (rb_scan_args(argc, argv, "41", &a, &b, &c, &d, &e) == 5) { location = NUM2INT(e); } xque *que = get_que(a); XmlModify::XmlObject type = XmlModify::XmlObject(NUM2INT(b)); char *name = StringValuePtr(c); #if HAVE_DBXML_MOD_APPEND_STEP_RES if (TYPE(d) == T_DATA && RDATA(obj)->dfree == (RDF)xb_res_free) { res = get_res(d); } else #endif { content = StringValuePtr(d); } xmod *mod = get_mod(obj); #if HAVE_DBXML_MOD_APPEND_STEP_RES if (res != NULL) { PROTECT(mod->mod->addAppendStep(*que->que, type, name, *res->res, location)); } else #endif { PROTECT(mod->mod->addAppendStep(*que->que, type, name, content, location)); } return obj; } static VALUE xb_mod_insert_after(VALUE obj, VALUE a, VALUE b, VALUE c, VALUE d) { #if HAVE_DBXML_MOD_APPEND_STEP_RES xres *res = NULL; #endif char *content; xmod *mod = get_mod(obj); xque *que = get_que(a); XmlModify::XmlObject type = XmlModify::XmlObject(NUM2INT(b)); char *name = StringValuePtr(c); #if HAVE_DBXML_MOD_APPEND_STEP_RES if (TYPE(d) == T_DATA && RDATA(obj)->dfree == (RDF)xb_res_free) { res = get_res(d); } else #endif { content = StringValuePtr(d); } #if HAVE_DBXML_MOD_APPEND_STEP_RES if (res != NULL) { PROTECT(mod->mod->addInsertAfterStep(*que->que, type, name, *res->res)); } else #endif { PROTECT(mod->mod->addInsertAfterStep(*que->que, type, name, content)); } return obj; } static VALUE xb_mod_insert_before(VALUE obj, VALUE a, VALUE b, VALUE c, VALUE d) { #if HAVE_DBXML_MOD_APPEND_STEP_RES xres *res = NULL; #endif char *content; xmod *mod = get_mod(obj); xque *que = get_que(a); XmlModify::XmlObject type = XmlModify::XmlObject(NUM2INT(b)); char *name = StringValuePtr(c); #if HAVE_DBXML_MOD_APPEND_STEP_RES if (TYPE(d) == T_DATA && RDATA(obj)->dfree == (RDF)xb_res_free) { res = get_res(d); } else #endif { content = StringValuePtr(d); } #if HAVE_DBXML_MOD_APPEND_STEP_RES if (res != NULL) { PROTECT(mod->mod->addInsertBeforeStep(*que->que, type, name, *res->res)); } else #endif { PROTECT(mod->mod->addInsertBeforeStep(*que->que, type, name, content)); } return obj; } static VALUE xb_mod_remove(VALUE obj, VALUE a) { xmod *mod = get_mod(obj); xque *que = get_que(a); PROTECT(mod->mod->addRemoveStep(*que->que)); return obj; } static VALUE xb_mod_rename(VALUE obj, VALUE a, VALUE b) { xmod *mod = get_mod(obj); xque *que = get_que(a); char *name = StringValuePtr(b); PROTECT(mod->mod->addRenameStep(*que->que, name)); return obj; } static VALUE xb_mod_update(VALUE obj, VALUE a, VALUE b) { xmod *mod = get_mod(obj); xque *que = get_que(a); char *name = StringValuePtr(b); PROTECT(mod->mod->addUpdateStep(*que->que, name)); return obj; } static VALUE xb_mod_execute(int argc, VALUE *argv, VALUE obj) { xmod *mod = get_mod(obj); XmlValue xmlval; xres *res = 0; bool has_val = false; XmlUpdateContext *xmlupd = 0; XmlQueryContext *xmlcxt = 0; bool freeupd = true, freecxt = true; VALUE a, b, c; rb_secure(4); switch (rb_scan_args(argc, argv, "12", &a, &b, &c)) { case 3: { xupd *upd = get_upd(c); xmlupd = upd->upd; freeupd = false; } /* ... */ case 2: { xcxt *cxt = get_cxt(b); xmlcxt = cxt->cxt; freecxt = false; } } if (TYPE(a) == T_DATA && RDATA(a)->dfree == (RDF)xb_res_free) { res = get_res(a); } else { xmlval = xb_val_xml(a); has_val = true; } XmlTransaction *xmltxn = get_txn(mod->txn); if (freeupd) { xman *man = get_man(mod->man); xmlupd = new XmlUpdateContext(man->man->createUpdateContext()); } if (freecxt) { xman *man = get_man(mod->man); xmlcxt = new XmlQueryContext(man->man->createQueryContext()); } if (has_val) { if (xmltxn) { PROTECT2(mod->mod->execute(*xmltxn, xmlval, *xmlcxt, *xmlupd), if (freeupd) delete xmlupd; if (freecxt) delete xmlcxt); } else { PROTECT2(mod->mod->execute(xmlval, *xmlcxt, *xmlupd), if (freeupd) delete xmlupd; if (freecxt) delete xmlcxt); } } else { if (xmltxn) { PROTECT2(mod->mod->execute(*xmltxn, *res->res, *xmlcxt, *xmlupd), if (freeupd) delete xmlupd; if (freecxt) delete xmlcxt); } else { PROTECT2(mod->mod->execute(*res->res, *xmlcxt, *xmlupd), if (freeupd) delete xmlupd; if (freecxt) delete xmlcxt); } } return obj; } static VALUE xb_val_s_alloc(VALUE obj) { xval *val; VALUE res = Data_Make_Struct(xb_cVal, xval, (RDF)xb_val_mark, (RDF)xb_val_free, val); val->val = new XmlValue(); return res; } static VALUE xb_val_init(int argc, VALUE *argv, VALUE obj) { xval *val; VALUE a, b; Data_Get_Struct(obj, xval, val); if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { XmlValue::Type type = XmlValue::Type(NUM2INT(a)); b = rb_obj_as_string(b); char *str = StringValuePtr(b); delete val->val; val->val = new XmlValue(type, str); return obj; } if (TYPE(a) == T_DATA && RDATA(obj)->dmark != (RDF)xb_doc_mark) { xdoc *doc = get_doc(a); delete val->val; val->val = new XmlValue(*doc->doc); } else if (a == Qtrue || a == Qfalse) { delete val->val; val->val = new XmlValue(a == Qtrue); } else if (FIXNUM_P(a) || TYPE(a) == T_FLOAT || TYPE(a) == T_BIGNUM) { a = rb_funcall2(a, rb_intern("to_f"), 0, 0); delete val->val; val->val = new XmlValue(RFLOAT(a)->value); } else { a = rb_obj_as_string(a); char *str = StringValuePtr(b); delete val->val; val->val = new XmlValue(str); } return obj; } static VALUE xb_val_to_doc(VALUE obj) { xval *val; xdoc *doc; Data_Get_Struct(obj, xval, val); XmlDocument *xmldoc; PROTECT(xmldoc = new XmlDocument(val->val->asDocument())); VALUE res = Data_Make_Struct(xb_cDoc, xdoc, (RDF)xb_doc_mark, (RDF)xb_doc_free, doc); get_man(val->man); doc->doc = xmldoc; doc->man = val->man; return res; } static VALUE xb_val_to_str(VALUE obj) { xval *val; Data_Get_Struct(obj, xval, val); std::string str; PROTECT(str = val->val->asString()); return rb_tainted_str_new2(str.c_str()); } static VALUE xb_val_to_f(VALUE obj) { xval *val; Data_Get_Struct(obj, xval, val); double dbl; PROTECT(dbl = val->val->asNumber()); return rb_float_new(dbl); } static VALUE xb_val_type(VALUE obj) { xval *val; Data_Get_Struct(obj, xval, val); return INT2NUM(val->val->getType()); } static VALUE xb_val_type_p(VALUE obj, VALUE a) { xval *val; Data_Get_Struct(obj, xval, val); XmlValue::Type type = XmlValue::Type(NUM2INT(a)); if (val->val->isType(type)) { return Qtrue; } return Qfalse; } static VALUE xb_val_nil_p(VALUE obj) { xval *val; Data_Get_Struct(obj, xval, val); if (val->val->isNull()) { return Qtrue; } return Qfalse; } static VALUE xb_val_number_p(VALUE obj) { xval *val; Data_Get_Struct(obj, xval, val); if (val->val->isNumber()) { return Qtrue; } return Qfalse; } static VALUE xb_val_string_p(VALUE obj) { xval *val; Data_Get_Struct(obj, xval, val); if (val->val->isString()) { return Qtrue; } return Qfalse; } static VALUE xb_val_boolean_p(VALUE obj) { xval *val; Data_Get_Struct(obj, xval, val); if (val->val->isBoolean()) { return Qtrue; } return Qfalse; } static VALUE xb_val_node_p(VALUE obj) { xval *val; Data_Get_Struct(obj, xval, val); if (val->val->isNode()) { return Qtrue; } return Qfalse; } static VALUE xb_val_node_name(VALUE obj) { xval *val; Data_Get_Struct(obj, xval, val); std::string str; PROTECT(str = val->val->getNodeName()); return rb_tainted_str_new2(str.c_str()); } static VALUE xb_val_node_value(VALUE obj) { xval *val; Data_Get_Struct(obj, xval, val); std::string str; PROTECT(str = val->val->getNodeValue()); return rb_tainted_str_new2(str.c_str()); } static VALUE xb_val_node_type(VALUE obj) { xval *val; Data_Get_Struct(obj, xval, val); short type; PROTECT(type = val->val->getNodeType()); return INT2NUM(type); } static VALUE xb_val_namespace(VALUE obj) { xval *val; Data_Get_Struct(obj, xval, val); std::string str; PROTECT(str = val->val->getNamespaceURI()); return rb_tainted_str_new2(str.c_str()); } static VALUE xb_val_prefix(VALUE obj) { xval *val; Data_Get_Struct(obj, xval, val); std::string str; PROTECT(str = val->val->getPrefix()); return rb_tainted_str_new2(str.c_str()); } static VALUE xb_val_local_name(VALUE obj) { xval *val; Data_Get_Struct(obj, xval, val); std::string str; PROTECT(str = val->val->getLocalName()); return rb_tainted_str_new2(str.c_str()); } static VALUE xb_val_parent_node(VALUE obj) { xval *val, *node; XmlValue *xmlnode, tmp; Data_Get_Struct(obj, xval, val); PROTECT(tmp = val->val->getParentNode(); if (!tmp) return Qnil; xmlnode = new XmlValue(tmp)); VALUE res = Data_Make_Struct(CLASS_OF(obj), xval, (RDF)xb_val_mark, (RDF)free, node); node->val = xmlnode; node->man = val->man; return res; } static VALUE xb_val_first_child(VALUE obj) { xval *val, *node; XmlValue *xmlnode, tmp; Data_Get_Struct(obj, xval, val); PROTECT(tmp = val->val->getFirstChild(); if (!tmp) return Qnil; xmlnode = new XmlValue(tmp)); VALUE res = Data_Make_Struct(CLASS_OF(obj), xval, (RDF)xb_val_mark, (RDF)free, node); node->val = xmlnode; node->man = val->man; return res; } static VALUE xb_val_last_child(VALUE obj) { xval *val, *node; XmlValue *xmlnode, tmp; Data_Get_Struct(obj, xval, val); PROTECT(tmp = val->val->getLastChild(); if (!tmp) return Qnil; xmlnode = new XmlValue(tmp)); VALUE res = Data_Make_Struct(CLASS_OF(obj), xval, (RDF)xb_val_mark, (RDF)free, node); node->val = xmlnode; node->man = val->man; return res; } static VALUE xb_val_previous_sibling(VALUE obj) { xval *val, *node; XmlValue *xmlnode, tmp; Data_Get_Struct(obj, xval, val); PROTECT(tmp = val->val->getPreviousSibling(); if (!tmp) return Qnil; xmlnode = new XmlValue(tmp)); VALUE res = Data_Make_Struct(CLASS_OF(obj), xval, (RDF)xb_val_mark, (RDF)free, node); node->val = xmlnode; node->man = val->man; return res; } static VALUE xb_val_next_sibling(VALUE obj) { xval *val, *node; XmlValue *xmlnode, tmp; Data_Get_Struct(obj, xval, val); PROTECT(tmp = val->val->getNextSibling(); if (!tmp) return Qnil; xmlnode = new XmlValue(tmp)); VALUE res = Data_Make_Struct(CLASS_OF(obj), xval, (RDF)xb_val_mark, (RDF)free, node); node->val = xmlnode; node->man = val->man; return res; } static VALUE xb_val_owner_element(VALUE obj) { xval *val, *node; XmlValue *xmlnode; Data_Get_Struct(obj, xval, val); PROTECT(xmlnode = new XmlValue(val->val->getOwnerElement())); VALUE res = Data_Make_Struct(CLASS_OF(obj), xval, (RDF)xb_val_mark, (RDF)free, node); node->val = xmlnode; node->man = val->man; return res; } static VALUE xb_val_attributes(VALUE obj) { xval *val; xres *res; XmlResults *xmlres; Data_Get_Struct(obj, xval, val); PROTECT(xmlres = new XmlResults(val->val->getAttributes())); VALUE result = Data_Make_Struct(xb_cRes, xres, (RDF)xb_res_mark, (RDF)xb_res_free, res); res->res = xmlres; res->man = val->man; return result; } #if HAVE_DBXML_VAL_TYPE_URI static VALUE xb_val_type_uri(VALUE obj) { xval *val; Data_Get_Struct(obj, xval, val); std::string str; PROTECT(str = val->val->getTypeURI()); return rb_tainted_str_new2(str.c_str()); } #endif #if HAVE_DBXML_VAL_TYPE_NAME static VALUE xb_val_type_name(VALUE obj) { xval *val; Data_Get_Struct(obj, xval, val); std::string str; PROTECT(str = val->val->getTypeName()); return rb_tainted_str_new2(str.c_str()); } #endif #if HAVE_DBXML_VAL_NODE_HANDLE static VALUE xb_val_node_handle(VALUE obj) { xval *val; Data_Get_Struct(obj, xval, val); std::string str; PROTECT(str = val->val->getNodeHandle()); return rb_tainted_str_new2(str.c_str()); } #endif #if HAVE_DBXML_XML_EVENT_WRITER #if HAVE_DBXML_XML_EVENT_WRITER_ALLOC static VALUE xb_ewr_s_alloc(VALUE obj) { xewr *ewr; VALUE res = Data_Make_Struct(xb_cEwr, xewr, (RDF)xb_ewr_mark, (RDF)xb_ewr_free, ewr); ewr->ewr = new XmlEventWriter(); return res; } static VALUE xb_ewr_init(VALUE obj) { return obj; } #endif static VALUE xb_ewr_close(VALUE obj) { xewr *ewr = get_ewr(obj); PROTECT(ewr->ewr->close()); ewr->ewr = 0; return Qnil; } static VALUE xb_ewr_attribute(VALUE obj, VALUE a, VALUE b, VALUE c, VALUE d, VALUE e) { xewr *ewr = get_ewr(obj); unsigned char *prefix = NULL; unsigned char *uri = NULL; unsigned char *localName = (unsigned char *)StringValuePtr(a); if (!NIL_P(b)) { prefix = (unsigned char *)StringValuePtr(b); } if (!NIL_P(c)) { uri = (unsigned char *)StringValuePtr(c); } unsigned char *value = (unsigned char *)StringValuePtr(d); PROTECT(ewr->ewr->writeAttribute(localName, prefix, uri, value, RTEST(e))); return obj; } static VALUE xb_ewr_dtd(VALUE obj, VALUE a) { xewr *ewr = get_ewr(obj); unsigned char *dtd = (unsigned char *)StringValuePtr(a); PROTECT(ewr->ewr->writeDTD(dtd, strlen((char *)dtd))); return obj; } static VALUE xb_ewr_end_doc(VALUE obj) { xewr *ewr = get_ewr(obj); PROTECT(ewr->ewr->writeEndDocument()); return obj; } static VALUE xb_ewr_end_ele(int argc, VALUE *argv, VALUE obj) { xewr *ewr = get_ewr(obj); unsigned char *prefix = NULL; unsigned char *uri = NULL; unsigned char *localName = NULL; VALUE a, b, c; switch (rb_scan_args(argc, argv, "12", &a, &b, &c)) { case 3: if (!NIL_P(c)) { uri = (unsigned char *)StringValuePtr(c); } /* ... */ case 2: if (!NIL_P(b)) { prefix = (unsigned char *)StringValuePtr(b); } } localName = (unsigned char *)StringValuePtr(a); PROTECT(ewr->ewr->writeEndElement(localName, prefix, uri)); return obj; } static VALUE xb_ewr_end_ent(VALUE obj, VALUE a) { xewr *ewr = get_ewr(obj); unsigned char *name = (unsigned char *)StringValuePtr(a); PROTECT(ewr->ewr->writeEndEntity(name)); return obj; } static VALUE xb_ewr_pi(VALUE obj, VALUE a, VALUE b) { xewr *ewr = get_ewr(obj); unsigned char *target = (unsigned char *)StringValuePtr(a); unsigned char *data = (unsigned char *)StringValuePtr(b); PROTECT(ewr->ewr->writeProcessingInstruction(target, data)); return obj; } static VALUE xb_ewr_start_ele(VALUE obj, VALUE a, VALUE b, VALUE c, VALUE d, VALUE e) { xewr *ewr = get_ewr(obj); unsigned char *prefix = NULL; unsigned char *uri = NULL; unsigned char *localName = (unsigned char *)StringValuePtr(a); if (!NIL_P(b)) { prefix = (unsigned char *)StringValuePtr(b); } if (!NIL_P(c)) { uri = (unsigned char *)StringValuePtr(c); } int numAttributes = NUM2INT(d); PROTECT(ewr->ewr->writeStartElement(localName, prefix, uri, numAttributes, RTEST(e))); return obj; } static VALUE xb_ewr_start_ent(VALUE obj, VALUE a, VALUE b) { xewr *ewr = get_ewr(obj); unsigned char *name = (unsigned char *)StringValuePtr(a); PROTECT(ewr->ewr->writeStartEntity(name, RTEST(b))); return obj; } static VALUE xb_ewr_start_doc(int argc, VALUE *argv, VALUE obj) { xewr *ewr = get_ewr(obj); unsigned char *version = NULL; unsigned char *encoding = NULL; unsigned char *standalone = NULL; VALUE a, b, c; switch (rb_scan_args(argc, argv, "03", &a, &b, &c)) { case 3: if (!NIL_P(c)) { standalone = (unsigned char *)StringValuePtr(c); } /* ... */ case 2: if (!NIL_P(b)) { encoding = (unsigned char *)StringValuePtr(b); } /* ... */ case 1: if (!NIL_P(a)) { version = (unsigned char *)StringValuePtr(a); } } PROTECT(ewr->ewr->writeStartDocument(version, encoding, standalone)); return obj; } static VALUE xb_ewr_txt(VALUE obj, VALUE a, VALUE b) { xewr *ewr = get_ewr(obj); XmlEventReader::XmlEventType type = XmlEventReader::XmlEventType(NUM2INT(a)); unsigned char *txt = (unsigned char *)StringValuePtr(b); PROTECT(ewr->ewr->writeText(type, txt, strlen((char *)txt))); return obj; } #endif #if HAVE_DBXML_XML_EVENT_READER static void xb_erd_mark(xerd *erd) { rb_gc_mark(erd->doc); } static void xb_erd_free(xerd *erd) { if (erd->erd) { PROTECT(erd->erd->close()); erd->erd = 0; } ::free(erd); } #if HAVE_DBXML_XML_EVENT_READER_ALLOC static VALUE xb_erd_s_alloc(VALUE obj) { xerd *erd; VALUE res = Data_Make_Struct(xb_cErd, xerd, (RDF)xb_erd_mark, (RDF)xb_erd_free, erd); erd->erd = new XmlEventReader(); return res; } static VALUE xb_erd_init(VALUE obj) { return obj; } #endif static VALUE xb_erd_close(VALUE obj) { xerd *erd = get_erd(obj); PROTECT(erd->erd->close()); erd->erd = 0; return Qnil; } static VALUE xb_doc_erd(VALUE obj) { XmlEventReader *xmlerd; xerd *erd; xdoc *doc = get_doc(obj); PROTECT(XmlEventReader &rex = doc->doc->getContentAsEventReader(); xmlerd = (XmlEventReader *) &rex); VALUE res = Data_Make_Struct(xb_cErd, xerd, (RDF)xb_erd_mark, (RDF)xb_erd_free, erd); erd->erd = xmlerd; erd->doc = obj; return res; } static VALUE xb_erd_ev(VALUE obj) { xerd *erd = get_erd(obj); int xmlt; PROTECT(xmlt = erd->erd->getEventType()); return INT2NUM(xmlt); } static VALUE xb_erd_uri(VALUE obj) { xerd *erd = get_erd(obj); const unsigned char *uri; PROTECT(uri = erd->erd->getNamespaceURI()); return rb_tainted_str_new2((char *)uri); } static VALUE xb_erd_name(VALUE obj) { xerd *erd = get_erd(obj); const unsigned char *uri; PROTECT(uri = erd->erd->getLocalName()); return rb_tainted_str_new2((char *)uri); } static VALUE xb_erd_prefix(VALUE obj) { xerd *erd = get_erd(obj); const unsigned char *uri; PROTECT(uri = erd->erd->getPrefix()); return rb_tainted_str_new2((char *)uri); } static VALUE xb_erd_value(VALUE obj) { xerd *erd = get_erd(obj); const unsigned char *uri; size_t len; PROTECT(uri = erd->erd->getValue(len)); return rb_tainted_str_new((char *)uri, len); } static VALUE xb_erd_attr_count(VALUE obj) { xerd *erd = get_erd(obj); int nb; PROTECT(nb = erd->erd->getAttributeCount()); return INT2NUM(nb); } static VALUE xb_erd_attr_p(VALUE obj, VALUE a) { xerd *erd = get_erd(obj); int nb = NUM2INT(a); bool res; PROTECT(res = erd->erd->isAttributeSpecified(nb)); if (res) return Qtrue; return Qfalse; } static VALUE xb_erd_attr_uri(VALUE obj, VALUE a) { xerd *erd = get_erd(obj); int nb = NUM2INT(a); const unsigned char *uri; PROTECT(uri = erd->erd->getAttributeNamespaceURI(nb)); return rb_tainted_str_new2((char *)uri); } static VALUE xb_erd_attr_name(VALUE obj, VALUE a) { xerd *erd = get_erd(obj); int nb = NUM2INT(a); const unsigned char *uri; PROTECT(uri = erd->erd->getAttributeLocalName(nb)); return rb_tainted_str_new2((char *)uri); } static VALUE xb_erd_attr_prefix(VALUE obj, VALUE a) { xerd *erd = get_erd(obj); int nb = NUM2INT(a); const unsigned char *uri; PROTECT(uri = erd->erd->getAttributePrefix(nb)); return rb_tainted_str_new2((char *)uri); } static VALUE xb_erd_attr_value(VALUE obj, VALUE a) { xerd *erd = get_erd(obj); int nb = NUM2INT(a); const unsigned char *uri; PROTECT(uri = erd->erd->getAttributeValue(nb)); return rb_tainted_str_new2((char *)uri); } static VALUE xb_erd_info_p(VALUE obj) { xerd *erd = get_erd(obj); if (erd->erd->hasEmptyElementInfo()) { return Qtrue; } return Qfalse; } static VALUE xb_erd_escape_p(VALUE obj) { xerd *erd = get_erd(obj); if (erd->erd->hasEntityEscapeInfo()) { return Qtrue; } return Qfalse; } static VALUE xb_erd_next_p(VALUE obj) { xerd *erd = get_erd(obj); bool res; PROTECT(res = erd->erd->hasNext()); if (res) { return Qtrue; } return Qfalse; } static VALUE xb_erd_empty_p(VALUE obj) { xerd *erd = get_erd(obj); bool res; PROTECT(res = erd->erd->isEmptyElement()); if (res) { return Qtrue; } return Qfalse; } static VALUE xb_erd_white_p(VALUE obj) { xerd *erd = get_erd(obj); bool res; PROTECT(res = erd->erd->isWhiteSpace()); if (res) { return Qtrue; } return Qfalse; } static VALUE xb_erd_nescape_p(int argc, VALUE *argv, VALUE obj) { VALUE a; int nb = 0; bool res; xerd *erd = get_erd(obj); if (rb_scan_args(argc, argv, "01", &a) == 1) { nb = NUM2INT(a); } PROTECT(res = erd->erd->needsEntityEscape(nb)); if (res) { return Qtrue; } return Qfalse; } static VALUE xb_erd_next(VALUE obj) { int res; xerd *erd = get_erd(obj); PROTECT(res = erd->erd->next()); return INT2NUM(res); } static VALUE xb_erd_next_tag(VALUE obj) { int res; xerd *erd = get_erd(obj); PROTECT(res = erd->erd->nextTag()); return INT2NUM(res); } static VALUE xb_erd_get_expand(VALUE obj) { xerd *erd = get_erd(obj); if (erd->erd->getExpandEntities()) { return Qtrue; } return Qfalse; } static VALUE xb_erd_set_expand(VALUE obj, VALUE a) { xerd *erd = get_erd(obj); if (RTEST(a)) { erd->erd->setExpandEntities(true); } else { erd->erd->setExpandEntities(false); } return a; } static VALUE xb_erd_get_info(VALUE obj) { xerd *erd = get_erd(obj); if (erd->erd->getReportEntityInfo()) { return Qtrue; } return Qfalse; } static VALUE xb_erd_set_info(VALUE obj, VALUE a) { xerd *erd = get_erd(obj); if (RTEST(a)) { erd->erd->setReportEntityInfo(true); } else { erd->erd->setReportEntityInfo(false); } return a; } static VALUE xb_erd_encoding(VALUE obj) { xerd *erd = get_erd(obj); const unsigned char *uri; PROTECT(uri = erd->erd->getEncoding()); return rb_tainted_str_new2((char *)uri); } static VALUE xb_erd_encoding_p(VALUE obj) { xerd *erd = get_erd(obj); bool res; PROTECT(res = erd->erd->encodingSet()); if (res) return Qtrue; return Qfalse; } static VALUE xb_erd_version(VALUE obj) { xerd *erd = get_erd(obj); const unsigned char *uri; PROTECT(uri = erd->erd->getVersion()); return rb_tainted_str_new2((char *)uri); } static VALUE xb_erd_system(VALUE obj) { xerd *erd = get_erd(obj); const unsigned char *uri; PROTECT(uri = erd->erd->getSystemId()); return rb_tainted_str_new2((char *)uri); } static VALUE xb_erd_doc_stand_p(VALUE obj) { xerd *erd = get_erd(obj); bool res; PROTECT(res = erd->erd->isStandalone()); if (res) return Qtrue; return Qfalse; } static VALUE xb_erd_attr_stand_p(VALUE obj) { xerd *erd = get_erd(obj); bool res; PROTECT(res = erd->erd->standaloneSet()); if (res) return Qtrue; return Qfalse; } static VALUE xb_val_to_erd(VALUE obj) { xval *val; xerd *erd; Data_Get_Struct(obj, xval, val); XmlEventReader *xmlerd; PROTECT(XmlEventReader &rex = val->val->asEventReader(); xmlerd = (XmlEventReader *)&rex); VALUE res = Data_Make_Struct(xb_cErd, xerd, (RDF)xb_erd_mark, (RDF)xb_erd_free, erd); erd->erd = xmlerd; erd->doc = obj; return res; } #endif static VALUE xb_man_resolver(VALUE obj, VALUE a) { xman *man = get_man(obj); XbResolve *rsv = new XbResolve(obj, a); PROTECT(man->man->registerResolver(*rsv)); man->rsv = a; return obj; } extern "C" { static VALUE xb_con_txn_dup(VALUE obj, VALUE a) { xcon *xres; VALUE res; bdb_TXN *txnst; GetTxnDBErr(a, txnst, xb_eFatal); xcon * con = get_con(obj); res = Data_Make_Struct(CLASS_OF(obj), xcon, (RDF)xb_con_mark, (RDF)free, xres); xres->con = con->con; xres->opened = con->opened; xres->txn = a; xres->man = txnst->man; return res; } static VALUE xb_con_txn_close(VALUE obj, VALUE commit, VALUE real) { xcon *con; Data_Get_Struct(obj, xcon, con); con->man = con->txn = Qfalse; con->con = 0; con->opened = 0; delete_ind(con->ind); #if HAVE_DBXML_XML_INDEX_LOOKUP delete_look(con->look); #endif return Qnil; } static VALUE xb_que_txn_dup(VALUE obj, VALUE a) { xque *que, *xres; VALUE res; bdb_TXN *txnst; GetTxnDBErr(a, txnst, xb_eFatal); Data_Get_Struct(obj, xque, que); res = Data_Make_Struct(CLASS_OF(obj), xque, (RDF)xb_que_mark, (RDF)free, xres); xres->que = que->que; xres->txn = a; xres->man = txnst->man; return res; } static VALUE xb_que_txn_close(VALUE obj, VALUE commit, VALUE real) { rset_obj(obj); return Qnil; } static VALUE xb_mod_txn_dup(VALUE obj, VALUE a) { xmod *mod, *xres; VALUE res; bdb_TXN *txnst; GetTxnDBErr(a, txnst, xb_eFatal); Data_Get_Struct(obj, xmod, mod); res = Data_Make_Struct(CLASS_OF(obj), xmod, (RDF)xb_mod_mark, (RDF)free, xres); xres->mod = mod->mod; xres->txn = a; xres->man = txnst->man; return res; } static VALUE xb_mod_txn_close(VALUE obj, VALUE commit, VALUE real) { rset_obj(obj); return Qnil; } static void xb_const_set(VALUE hash, const char *cvalue, const char *ckey) { VALUE key, value; key = rb_str_new2(ckey); rb_obj_freeze(key); value = rb_str_new2(cvalue); rb_obj_freeze(value); rb_hash_aset(hash, key, value); } void Init_bdbxml() { int major, minor, patch; VALUE version; #ifdef BDB_LINK_OBJ extern void Init_bdb(); #endif static VALUE xb_mDb, xb_mXML; if (rb_const_defined_at(rb_cObject, rb_intern("BDB"))) { rb_raise(rb_eNameError, "module already defined"); } #ifdef BDB_LINK_OBJ Init_bdb(); #else rb_require("bdb"); #endif id_current_env = rb_intern("bdb_current_env"); id_read = rb_intern("read"); id_write = rb_intern("write"); id_pos = rb_intern("pos"); id_close = rb_intern("close"); xb_mDb = rb_const_get(rb_cObject, rb_intern("BDB")); major = NUM2INT(rb_const_get(xb_mDb, rb_intern("VERSION_MAJOR"))); minor = NUM2INT(rb_const_get(xb_mDb, rb_intern("VERSION_MINOR"))); patch = NUM2INT(rb_const_get(xb_mDb, rb_intern("VERSION_PATCH"))); if (major != DB_VERSION_MAJOR || minor != DB_VERSION_MINOR || patch != DB_VERSION_PATCH) { rb_raise(rb_eNotImpError, "\nBDB::XML needs compatible versions of BDB\n\tyou have BDB::XML version %d.%d.%d and BDB version %d.%d.%d\n", DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH, major, minor, patch); } version = rb_tainted_str_new2(dbxml_version(&major, &minor, &patch)); if (major != DBXML_VERSION_MAJOR || minor != DBXML_VERSION_MINOR || patch != DBXML_VERSION_PATCH) { rb_raise(rb_eNotImpError, "\nBDB::XML needs compatible versions of DbXml\n\tyou have DbXml.hpp version %d.%d.%d and libdbxml version %d.%d.%d\n", DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH, major, minor, patch); } xb_mObs = rb_const_get(rb_cObject, rb_intern("ObjectSpace")); xb_eFatal = rb_const_get(xb_mDb, rb_intern("Fatal")); xb_cEnv = rb_const_get(xb_mDb, rb_intern("Env")); #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_define_alloc_func(xb_cEnv, RMFS(xb_env_s_alloc)); #else rb_define_singleton_method(xb_cEnv, "allocate", RMFS(xb_env_s_alloc), 0); #endif rb_define_singleton_method(xb_cEnv, "new", RMF(xb_env_s_new), -1); rb_define_singleton_method(xb_cEnv, "create", RMF(xb_env_s_new), -1); rb_define_private_method(xb_cEnv, "initialize", RMF(xb_env_init), -1); rb_define_method(xb_cEnv, "close", RMF(xb_env_close), 0); rb_define_method(xb_cEnv, "manager", RMF(xb_env_manager), -1); rb_define_method(xb_cEnv, "begin", RMF(xb_env_begin), -1); rb_define_method(xb_cEnv, "txn_begin", RMF(xb_env_begin), -1); rb_define_method(xb_cEnv, "transaction", RMF(xb_env_begin), -1); xb_cTxn = rb_const_get(xb_mDb, rb_intern("Txn")); rb_define_method(xb_cTxn, "begin", RMF(xb_man_begin), -1); rb_define_method(xb_cTxn, "txn_begin", RMF(xb_man_begin), -1); rb_define_method(xb_cTxn, "transaction", RMF(xb_man_begin), -1); rb_define_method(xb_cTxn, "create_container", RMF(xb_man_create_con), -1); rb_define_method(xb_cTxn, "open_container", RMF(xb_man_open_con), -1); rb_define_method(xb_cTxn, "rename_container", RMF(xb_man_rename), 2); rb_define_method(xb_cTxn, "remove_container", RMF(xb_man_remove), 1); rb_define_method(xb_cTxn, "prepare", RMF(xb_man_prepare), -1); rb_define_method(xb_cTxn, "query", RMF(xb_man_query), -1); #if HAVE_DBXML_XML_INDEX_LOOKUP rb_define_method(xb_cTxn, "create_index_lookup", RMF(xb_man_create_look), -1); #endif #if HAVE_DBXML_MAN_EXISTS_CONTAINER rb_define_method(xb_cTxn, "container_version", RMF(xb_man_con_version), 1); #endif #if HAVE_DBXML_MAN_REINDEX_CONTAINER rb_define_method(xb_cTxn, "reindex_container", RMF(xb_man_reindex), -1); #endif #if HAVE_DBXML_MAN_COMPACT_CONTAINER rb_define_method(xb_cTxn, "compact_container", RMF(xb_man_compact_con), -1); #endif #if HAVE_DBXML_MAN_TRUNCATE_CONTAINER rb_define_method(xb_cTxn, "truncate_container", RMF(xb_man_truncate_con), -1); #endif rb_define_method(xb_cTxn, "method_missing", RMF(xb_txn_missing), -1); DbXml::setLogLevel(DbXml::LEVEL_ALL, false); DbXml::setLogCategory(DbXml::CATEGORY_ALL, false); xb_io = rb_ary_new(); rb_global_variable(&xb_io); xb_mXML = rb_define_module_under(xb_mDb, "XML"); rb_define_const(xb_mXML, "VERSION", version); rb_define_const(xb_mXML, "VERSION_MAJOR", INT2FIX(major)); rb_define_const(xb_mXML, "VERSION_MINOR", INT2FIX(minor)); rb_define_const(xb_mXML, "VERSION_PATCH", INT2FIX(patch)); #if HAVE_DBXML_CONST_DBXML_ADOPT_DBENV rb_define_const(xb_mXML, "ADOPT_DBENV", INT2NUM(DBXML_ADOPT_DBENV)); #endif #if HAVE_DBXML_CONST_DBXML_ALLOW_EXTERNAL_ACCESS rb_define_const(xb_mXML, "ALLOW_EXTERNAL_ACCESS", INT2NUM(DBXML_ALLOW_EXTERNAL_ACCESS)); #endif #if HAVE_DBXML_CONST_DBXML_ALLOW_AUTO_OPEN rb_define_const(xb_mXML, "ALLOW_AUTO_OPEN", INT2NUM(DBXML_ALLOW_AUTO_OPEN)); #endif #if HAVE_DBXML_CONST_DBXML_ALLOW_VALIDATION rb_define_const(xb_mXML, "ALLOW_VALIDATION", INT2NUM(DBXML_ALLOW_VALIDATION)); #endif #if HAVE_DBXML_CONST_DBXML_TRANSACTIONAL rb_define_const(xb_mXML, "TRANSACTIONAL", INT2NUM(DBXML_TRANSACTIONAL)); #endif #if HAVE_DBXML_CONST_DBXML_GEN_NAME rb_define_const(xb_mXML, "GEN_NAME", INT2NUM(DBXML_GEN_NAME)); #endif #if HAVE_DBXML_CONST_DBXML_LAZY_DOCS rb_define_const(xb_mXML, "LAZY_DOCS", INT2NUM(DBXML_LAZY_DOCS)); #endif #if HAVE_DBXML_CONST_DBXML_INDEX_NODES rb_define_const(xb_mXML, "INDEX_NODES", INT2NUM(DBXML_INDEX_NODES)); #endif #if HAVE_DBXML_CONST_LEVEL_NONE rb_define_const(xb_mXML, "LEVEL_NONE", INT2NUM(LEVEL_NONE)); #endif #if HAVE_DBXML_CONST_LEVEL_DEBUG rb_define_const(xb_mXML, "LEVEL_DEBUG", INT2NUM(LEVEL_DEBUG)); #endif #if HAVE_DBXML_CONST_LEVEL_INFO rb_define_const(xb_mXML, "LEVEL_INFO", INT2NUM(LEVEL_INFO)); #endif #if HAVE_DBXML_CONST_LEVEL_WARNING rb_define_const(xb_mXML, "LEVEL_WARNING", INT2NUM(LEVEL_WARNING)); #endif #if HAVE_DBXML_CONST_LEVEL_ERROR rb_define_const(xb_mXML, "LEVEL_ERROR", INT2NUM(LEVEL_ERROR)); #endif #if HAVE_DBXML_CONST_LEVEL_ALL rb_define_const(xb_mXML, "LEVEL_ALL", INT2NUM(LEVEL_ALL)); #endif #if HAVE_DBXML_CONST_CATEGORY_NONE rb_define_const(xb_mXML, "CATEGORY_NONE", INT2NUM(CATEGORY_NONE)); #endif #if HAVE_DBXML_CONST_CATEGORY_INDEXER rb_define_const(xb_mXML, "CATEGORY_INDEXER", INT2NUM(CATEGORY_INDEXER)); #endif #if HAVE_DBXML_CONST_CATEGORY_QUERY rb_define_const(xb_mXML, "CATEGORY_QUERY", INT2NUM(CATEGORY_QUERY)); #endif #if HAVE_DBXML_CONST_CATEGORY_OPTIMIZER rb_define_const(xb_mXML, "CATEGORY_OPTIMIZER", INT2NUM(CATEGORY_OPTIMIZER)); #endif #if HAVE_DBXML_CONST_CATEGORY_DICTIONARY rb_define_const(xb_mXML, "CATEGORY_DICTIONARY", INT2NUM(CATEGORY_DICTIONARY)); #endif #if HAVE_DBXML_CONST_CATEGORY_CONTAINER rb_define_const(xb_mXML, "CATEGORY_CONTAINER", INT2NUM(CATEGORY_CONTAINER)); #endif #if HAVE_DBXML_CONST_CATEGORY_NODESTORE rb_define_const(xb_mXML, "CATEGORY_NODESTORE", INT2NUM(CATEGORY_NODESTORE)); #endif #if HAVE_DBXML_CONST_CATEGORY_MANAGER rb_define_const(xb_mXML, "CATEGORY_MANAGER", INT2NUM(CATEGORY_MANAGER)); #endif #if HAVE_DBXML_CONST_CATEGORY_ALL rb_define_const(xb_mXML, "CATEGORY_ALL", INT2NUM(CATEGORY_ALL)); #endif #if HAVE_DBXML_CONST_DBXML_CHKSUM_SHA1 rb_define_const(xb_mXML, "CHKSUM_SHA1", INT2NUM(DBXML_CHKSUM_SHA1)); #endif #if HAVE_DBXML_CONST_DBXML_ENCRYPT rb_define_const(xb_mXML, "ENCRYPT", INT2NUM(DBXML_ENCRYPT)); #endif #if HAVE_DBXML_CONST_DBXML_WELL_FORMED_ONLY rb_define_const(xb_mXML, "WELL_FORMED_ONLY", INT2NUM(DBXML_WELL_FORMED_ONLY)); #endif #if HAVE_DBXML_CONST_DBXML_DOCUMENT_PROJECTION rb_define_const(xb_mXML, "DOCUMENT_PROJECTION", INT2NUM(DBXML_DOCUMENT_PROJECTION)); #endif #if HAVE_DBXML_CONST_DBXML_NO_AUTO_COMMIT rb_define_const(xb_mXML, "NO_AUTO_COMMIT", INT2NUM(DBXML_NO_AUTO_COMMIT)); #endif #if HAVE_DBXML_CONST_DBXML_STATISTICS rb_define_const(xb_mXML, "STATISTICS", INT2NUM(DBXML_STATISTICS)); #endif #if HAVE_DBXML_CONST_DBXML_NO_STATISTICS rb_define_const(xb_mXML, "NO_STATISTICS", INT2NUM(DBXML_NO_STATISTICS)); #endif #if HAVE_DBXML_CONST_DBXML_REVERSE_ORDER rb_define_const(xb_mXML, "REVERSE_ORDER", INT2NUM(DBXML_REVERSE_ORDER)); #endif #if HAVE_DBXML_CONST_DBXML_CACHE_DOCUMENTS rb_define_const(xb_mXML, "CACHE_DOCUMENTS", INT2NUM(DBXML_CACHE_DOCUMENTS)); #endif #if HAVE_DBXML_CONST_DBXML_INDEX_VALUES rb_define_const(xb_mXML, "INDEX_VALUES", INT2NUM(DBXML_INDEX_VALUES)); #endif #if HAVE_DBXML_CONST_DBXML_NO_INDEX_NODES rb_define_const(xb_mXML, "NO_INDEX_NODES", INT2NUM(DBXML_NO_INDEX_NODES)); #endif { VALUE name = rb_hash_new(); rb_define_const(xb_mXML, "Name", name); xb_const_set(name, metaDataName_name, "name"); xb_const_set(name, metaDataName_root, "root"); xb_const_set(name, "default", "default"); rb_obj_freeze(name); name = rb_hash_new(); rb_define_const(xb_mXML, "Namespace", name); xb_const_set(name, metaDataNamespace_uri, "uri"); xb_const_set(name, metaDataNamespace_prefix, "prefix"); rb_obj_freeze(name); } xb_cMan = rb_define_class_under(xb_mXML, "Manager", rb_cObject); #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_define_alloc_func(xb_cMan, RMFS(xb_man_s_alloc)); #else rb_define_singleton_method(xb_cMan, "allocate", RMFS(xb_man_s_alloc), 0); #endif rb_define_singleton_method(xb_cMan, "new", RMF(xb_s_new), -1); rb_define_private_method(xb_cMan, "initialize", RMF(xb_man_init), -1); rb_define_method(xb_cMan, "environment", RMF(xb_man_env), 0); rb_define_method(xb_cMan, "env", RMF(xb_man_env), 0); rb_define_method(xb_cMan, "environment?", RMF(xb_man_env_p), 0); rb_define_method(xb_cMan, "env?", RMF(xb_man_env_p), 0); rb_define_method(xb_cMan, "has_environment?", RMF(xb_man_env_p), 0); rb_define_method(xb_cMan, "has_env?", RMF(xb_man_env_p), 0); rb_define_method(xb_cMan, "home", RMF(xb_man_home), 0); rb_define_method(xb_cMan, "pagesize", RMF(xb_man_page_get), 0); rb_define_method(xb_cMan, "pagesize=", RMF(xb_man_page_set), 1); rb_define_method(xb_cMan, "container_flags", RMF(xb_man_flags_get), 0); rb_define_method(xb_cMan, "container_flags=", RMF(xb_man_flags_set), 1); rb_define_method(xb_cMan, "container_type", RMF(xb_man_type_get), 0); rb_define_method(xb_cMan, "container_type=", RMF(xb_man_type_set), 1); rb_define_method(xb_cMan, "begin", RMF(xb_man_begin), -1); rb_define_method(xb_cMan, "txn_begin", RMF(xb_man_begin), -1); rb_define_method(xb_cMan, "transaction", RMF(xb_man_begin), -1); rb_define_method(xb_cMan, "create_container", RMF(xb_man_create_con), -1); rb_define_method(xb_cMan, "open_container", RMF(xb_man_open_con), -1); rb_define_method(xb_cMan, "open", RMF(xb_man_open_con), -1); rb_define_method(xb_cMan, "rename_container", RMF(xb_man_rename), 2); rb_define_method(xb_cMan, "rename", RMF(xb_man_rename), 2); rb_define_method(xb_cMan, "remove_container", RMF(xb_man_remove), 1); rb_define_method(xb_cMan, "remove", RMF(xb_man_remove), 1); rb_define_method(xb_cMan, "upgrade_container", RMF(xb_man_upgrade), 1); rb_define_method(xb_cMan, "upgrade", RMF(xb_man_upgrade), 1); rb_define_method(xb_cMan, "dump_container", RMF(xb_man_dump_con), -1); rb_define_method(xb_cMan, "dump", RMF(xb_man_dump_con), -1); rb_define_method(xb_cMan, "load_container", RMF(xb_man_load_con), -1); rb_define_method(xb_cMan, "load", RMF(xb_man_load_con), -1); rb_define_method(xb_cMan, "verify_container", RMF(xb_man_verify), 1); rb_define_method(xb_cMan, "verify", RMF(xb_man_verify), 1); rb_define_method(xb_cMan, "create_update_context", RMF(xb_man_create_upd), 0); rb_define_method(xb_cMan, "create_query_context", RMF(xb_man_create_cxt), -1); rb_define_method(xb_cMan, "create_results", RMF(xb_man_create_res), 0); rb_define_method(xb_cMan, "create_document", RMF(xb_man_create_doc), 0) ; rb_define_method(xb_cMan, "create_modify", RMF(xb_man_create_mod), 0); rb_define_method(xb_cMan, "prepare", RMF(xb_man_prepare), -1); rb_define_method(xb_cMan, "query", RMF(xb_man_query), -1); rb_define_method(xb_cMan, "resolver=", RMF(xb_man_resolver), 1); rb_define_method(xb_cMan, "close", RMF(xb_man_close), 0); #if HAVE_DBXML_XML_INDEX_LOOKUP rb_define_method(xb_cMan, "create_index_lookup", RMF(xb_man_create_look), -1); #endif #if HAVE_DBXML_MAN_EXISTS_CONTAINER rb_define_method(xb_cMan, "container_version", RMF(xb_man_con_version), 1); #endif #if HAVE_DBXML_MAN_REINDEX_CONTAINER rb_define_method(xb_cMan, "reindex_container", RMF(xb_man_reindex), -1); #endif #if HAVE_DBXML_MAN_DEFAULT_SEQUENCE_INCREMENT rb_define_method(xb_cMan, "sequence_incr", RMF(xb_man_increment_get), 0); rb_define_method(xb_cMan, "sequence_increment", RMF(xb_man_increment_get), 0); rb_define_method(xb_cMan, "sequence_incr=", RMF(xb_man_increment_set), 0); rb_define_method(xb_cMan, "sequence_increment=", RMF(xb_man_increment_set), 0); #endif #if HAVE_DBXML_MAN_GET_FLAGS rb_define_method(xb_cMan, "flags", RMF(xb_man_get_flags), 0); #endif #if HAVE_DBXML_MAN_GET_IMPLICIT_TIMEZONE rb_define_method(xb_cMan, "implicit_timezone", RMF(xb_man_get_itz), 0); rb_define_method(xb_cMan, "implicit_timezone=", RMF(xb_man_set_itz), 1); #endif #if HAVE_DBXML_MAN_COMPACT_CONTAINER rb_define_method(xb_cMan, "compact_container", RMF(xb_man_compact_con), -1); #endif #if HAVE_DBXML_MAN_TRUNCATE_CONTAINER rb_define_method(xb_cMan, "truncate_container", RMF(xb_man_truncate_con), -1); #endif xb_cCon = rb_define_class_under(xb_mXML, "Container", rb_cObject); #if HAVE_DBXML_CONST_XMLCONTAINER_NODECONTAINER rb_define_const(xb_cCon, "NodeContainer", INT2NUM(XmlContainer::NodeContainer)); #endif #if HAVE_DBXML_CONST_XMLCONTAINER_WHOLEDOCCONTAINER rb_define_const(xb_cCon, "WholedocContainer", INT2NUM(XmlContainer::WholedocContainer)); #endif #if HAVE_DBXML_CONST_XMLCONTAINER_NODECONTAINER rb_define_const(xb_cCon, "Node", INT2NUM(XmlContainer::NodeContainer)); #endif #if HAVE_DBXML_CONST_XMLCONTAINER_WHOLEDOCCONTAINER rb_define_const(xb_cCon, "Wholedoc", INT2NUM(XmlContainer::WholedocContainer)); #endif rb_include_module(xb_cCon, rb_mEnumerable); #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_define_alloc_func(xb_cCon, RMFS(xb_con_s_alloc)); #else rb_define_singleton_method(xb_cCon, "allocate", RMFS(xb_con_s_alloc), 0); #endif rb_define_singleton_method(xb_cCon, "new", RMF(xb_s_new), -1); rb_define_singleton_method(xb_cCon, "open", RMF(xb_con_s_open), -1); rb_define_private_method(xb_cCon, "initialize", RMF(xb_con_init), -1); rb_define_private_method(xb_cCon, "__txn_dup__", RMF(xb_con_txn_dup), 1); rb_define_private_method(xb_cCon, "__txn_close__", RMF(xb_con_txn_close), 2); rb_define_method(xb_cCon, "each", RMF(xb_con_each), 0); rb_define_method(xb_cCon, "manager", RMF(xb_con_manager), 0); rb_define_method(xb_cCon, "close", RMF(xb_con_close), 0); rb_define_method(xb_cCon, "transaction", RMF(xb_con_txn), 0); rb_define_method(xb_cCon, "txn", RMF(xb_con_txn), 0); rb_define_method(xb_cCon, "transaction?", RMF(xb_con_txn_p), 0); rb_define_method(xb_cCon, "txn?", RMF(xb_con_txn_p), 0); rb_define_method(xb_cCon, "in_transaction?", RMF(xb_con_txn_p), 0); rb_define_method(xb_cCon, "in_txn?", RMF(xb_con_txn_p), 0); rb_define_method(xb_cCon, "index", RMF(xb_con_index), -1); rb_define_method(xb_cCon, "index=", RMF(xb_con_index_set), -1); #if HAVE_DBXML_CON_INDEX_NODES rb_define_method(xb_cCon, "index?", RMF(xb_con_index_p), 0); #endif #if HAVE_DBXML_CON_PAGESIZE rb_define_method(xb_cCon, "pagesize", RMF(xb_con_pagesize), 0); #endif rb_define_method(xb_cCon, "name", RMF(xb_con_name), 0); rb_define_method(xb_cCon, "alias=", RMF(xb_con_alias_set), 1); rb_define_method(xb_cCon, "delete_alias", RMF(xb_con_alias_del), 1); rb_define_method(xb_cCon, "all_documents", RMF(xb_con_all), -1); rb_define_method(xb_cCon, "type", RMF(xb_con_type), 0); rb_define_method(xb_cCon, "[]", RMF(xb_con_get), -1); rb_define_method(xb_cCon, "get", RMF(xb_con_get), -1); rb_define_method(xb_cCon, "<<", RMF(xb_con_add), -1); rb_define_method(xb_cCon, "put", RMF(xb_con_add), -1); rb_define_method(xb_cCon, "push", RMF(xb_con_add), -1); rb_define_method(xb_cCon, "update", RMF(xb_con_update), -1); rb_define_method(xb_cCon, "[]=", RMF(xb_con_set), 2); rb_define_method(xb_cCon, "delete", RMF(xb_con_delete), -1); rb_define_method(xb_cCon, "sync", RMF(xb_con_sync), 0); rb_define_method(xb_cCon, "statistics", RMF(xb_con_stat), -1); rb_define_method(xb_cCon, "lookup_index", RMF(xb_con_lookup), -1); rb_define_method(xb_cCon, "add_index", RMF(xb_con_add_index), -1); rb_define_method(xb_cCon, "delete_index", RMF(xb_con_delete_index), -1); rb_define_method(xb_cCon, "replace_index", RMF(xb_con_replace_index), -1); rb_define_method(xb_cCon, "add_default_index", RMF(xb_con_add_def_index), -1); rb_define_method(xb_cCon, "delete_default_index", RMF(xb_con_delete_def_index), -1); rb_define_method(xb_cCon, "replace_default_index", RMF(xb_con_replace_def_index), -1); #if HAVE_DBXML_CON_FLAGS rb_define_method(xb_cCon, "flags", RMF(xb_con_flags), 0); #endif #if HAVE_DBXML_CON_NODE rb_define_method(xb_cCon, "node", RMF(xb_con_node), -1); #endif #if HAVE_DBXML_XML_EVENT_WRITER rb_define_method(xb_cCon, "put_document_as_event_writer", RMF(xb_con_ewr), -1); rb_define_method(xb_cCon, "event_writer", RMF(xb_con_ewr), -1); #endif xb_cInd = rb_define_class_under(xb_mXML, "Index", rb_cObject); rb_undef_method(CLASS_OF(xb_cInd), "allocate"); rb_undef_method(CLASS_OF(xb_cInd), "new"); #if HAVE_DBXML_CONST_XMLINDEXSPECIFICATION_UNIQUE_OFF rb_define_const(xb_cInd, "UNIQUE_OFF", INT2NUM(XmlIndexSpecification::UNIQUE_OFF)); #endif #if HAVE_DBXML_CONST_XMLINDEXSPECIFICATION_UNIQUE_ON rb_define_const(xb_cInd, "UNIQUE_ON", INT2NUM(XmlIndexSpecification::UNIQUE_ON)); #endif #if HAVE_DBXML_CONST_XMLINDEXSPECIFICATION_PATH_NONE rb_define_const(xb_cInd, "PATH_NONE", INT2NUM(XmlIndexSpecification::PATH_NONE)); #endif #if HAVE_DBXML_CONST_XMLINDEXSPECIFICATION_PATH_NODE rb_define_const(xb_cInd, "PATH_NODE", INT2NUM(XmlIndexSpecification::PATH_NODE)); #endif #if HAVE_DBXML_CONST_XMLINDEXSPECIFICATION_PATH_EDGE rb_define_const(xb_cInd, "PATH_EDGE", INT2NUM(XmlIndexSpecification::PATH_EDGE)); #endif #if HAVE_DBXML_CONST_XMLINDEXSPECIFICATION_NODE_NONE rb_define_const(xb_cInd, "NODE_NONE", INT2NUM(XmlIndexSpecification::NODE_NONE)); #endif #if HAVE_DBXML_CONST_XMLINDEXSPECIFICATION_NODE_ELEMENT rb_define_const(xb_cInd, "NODE_ELEMENT", INT2NUM(XmlIndexSpecification::NODE_ELEMENT)); #endif #if HAVE_DBXML_CONST_XMLINDEXSPECIFICATION_NODE_ATTRIBUTE rb_define_const(xb_cInd, "NODE_ATTRIBUTE", INT2NUM(XmlIndexSpecification::NODE_ATTRIBUTE)); #endif #if HAVE_DBXML_CONST_XMLINDEXSPECIFICATION_NODE_METADATA rb_define_const(xb_cInd, "NODE_METADATA", INT2NUM(XmlIndexSpecification::NODE_METADATA)); #endif #if HAVE_DBXML_CONST_XMLINDEXSPECIFICATION_KEY_NONE rb_define_const(xb_cInd, "KEY_NONE", INT2NUM(XmlIndexSpecification::KEY_NONE)); #endif #if HAVE_DBXML_CONST_XMLINDEXSPECIFICATION_KEY_PRESENCE rb_define_const(xb_cInd, "KEY_PRESENCE", INT2NUM(XmlIndexSpecification::KEY_PRESENCE)); #endif #if HAVE_DBXML_CONST_XMLINDEXSPECIFICATION_KEY_EQUALITY rb_define_const(xb_cInd, "KEY_EQUALITY", INT2NUM(XmlIndexSpecification::KEY_EQUALITY)); #endif #if HAVE_DBXML_CONST_XMLINDEXSPECIFICATION_KEY_SUBSTRING rb_define_const(xb_cInd, "KEY_SUBSTRING", INT2NUM(XmlIndexSpecification::KEY_SUBSTRING)); #endif rb_define_method(xb_cInd, "manager", RMF(xb_ind_manager), 0); rb_define_method(xb_cInd, "container", RMF(xb_ind_container), 0); rb_define_method(xb_cInd, "default", RMF(xb_ind_default), 0); rb_define_method(xb_cInd, "add", RMF(xb_ind_add), -1); rb_define_method(xb_cInd, "add_default", RMF(xb_ind_add_default), -1); rb_define_method(xb_cInd, "delete", RMF(xb_ind_delete), -1); rb_define_method(xb_cInd, "delete_default", RMF(xb_ind_delete_default), -1); rb_define_method(xb_cInd, "replace", RMF(xb_ind_replace), -1); rb_define_method(xb_cInd, "replace_default", RMF(xb_ind_replace_default), -1); rb_define_method(xb_cInd, "each", RMF(xb_ind_each), 0); rb_define_method(xb_cInd, "each_type", RMF(xb_ind_each_type), 0); rb_define_method(xb_cInd, "find", RMF(xb_ind_find), -1); rb_define_method(xb_cInd, "to_a", RMF(xb_ind_to_a), 0); #if HAVE_DBXML_XML_INDEX_LOOKUP xb_cLook = rb_define_class_under(xb_mXML, "IndexLookup", rb_cObject); rb_undef_method(CLASS_OF(xb_cLook), "allocate"); rb_undef_method(CLASS_OF(xb_cLook), "new"); #if HAVE_DBXML_CONST_XMLINDEXLOOKUP_NONE rb_define_const(xb_cLook, "NONE", INT2NUM(XmlIndexLookup::NONE)); #endif #if HAVE_DBXML_CONST_XMLINDEXLOOKUP_EQ rb_define_const(xb_cLook, "EQ", INT2NUM(XmlIndexLookup::EQ)); #endif #if HAVE_DBXML_CONST_XMLINDEXLOOKUP_GT rb_define_const(xb_cLook, "GT", INT2NUM(XmlIndexLookup::GT)); #endif #if HAVE_DBXML_CONST_XMLINDEXLOOKUP_GTE rb_define_const(xb_cLook, "GTE", INT2NUM(XmlIndexLookup::GTE)); #endif #if HAVE_DBXML_CONST_XMLINDEXLOOKUP_LT rb_define_const(xb_cLook, "LT", INT2NUM(XmlIndexLookup::LT)); #endif #if HAVE_DBXML_CONST_XMLINDEXLOOKUP_LTE rb_define_const(xb_cLook, "LTE", INT2NUM(XmlIndexLookup::LTE)); #endif rb_define_method(xb_cLook, "manager", RMF(xb_look_manager), 0); rb_define_method(xb_cLook, "transaction", RMF(xb_look_transaction), 0); rb_define_method(xb_cLook, "transaction?", RMF(xb_look_transaction_p), 0); rb_define_method(xb_cLook, "execute", RMF(xb_look_execute), -1); rb_define_method(xb_cLook, "container", RMF(xb_look_container_get), 0); rb_define_method(xb_cLook, "container=", RMF(xb_look_container_set), 1); rb_define_method(xb_cLook, "high_bound", RMF(xb_look_highbound_get), 0); rb_define_method(xb_cLook, "high_bound=", RMF(xb_look_highbound_set), 1); rb_define_method(xb_cLook, "low_bound", RMF(xb_look_lowbound_get), 0); rb_define_method(xb_cLook, "low_bound=", RMF(xb_look_lowbound_set), 1); rb_define_method(xb_cLook, "index", RMF(xb_look_index_get), 0); rb_define_method(xb_cLook, "index=", RMF(xb_look_index_set), 1); rb_define_method(xb_cLook, "node", RMF(xb_look_node_get), 0); rb_define_method(xb_cLook, "node_uri", RMF(xb_look_node_uri_get), 0); rb_define_method(xb_cLook, "node_name", RMF(xb_look_node_name_get), 0); rb_define_method(xb_cLook, "node=", RMF(xb_look_node_set), 1); rb_define_method(xb_cLook, "node_uri=", RMF(xb_look_node_uri_set), 1); rb_define_method(xb_cLook, "node_name=", RMF(xb_look_node_name_set), 1); rb_define_method(xb_cLook, "parent", RMF(xb_look_parent_get), 0); rb_define_method(xb_cLook, "parent_uri", RMF(xb_look_parent_uri_get), 0); rb_define_method(xb_cLook, "parent_name", RMF(xb_look_parent_name_get), 0); rb_define_method(xb_cLook, "parent=", RMF(xb_look_parent_set), 1); rb_define_method(xb_cLook, "parent_uri=", RMF(xb_look_parent_uri_set), 1); rb_define_method(xb_cLook, "parent_name=", RMF(xb_look_parent_name_set), 1); #endif xb_cUpd = rb_define_class_under(xb_mXML, "UpdateContext", rb_cObject); #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_define_alloc_func(xb_cUpd, RMFS(xb_upd_s_alloc)); #else rb_define_singleton_method(xb_cUpd, "allocate", RMFS(xb_upd_s_alloc), 0); #endif rb_define_singleton_method(xb_cUpd, "new", RMF(xb_s_new), -1); rb_define_private_method(xb_cUpd, "initialize", RMF(xb_upd_init), 1); rb_define_method(xb_cUpd, "manager", RMF(xb_upd_manager), 0); #if HAVE_DBXML_UPDATE_APPLY_CHANGES rb_define_method(xb_cUpd, "apply_changes", RMF(xb_upd_changes_get), 0); rb_define_method(xb_cUpd, "apply_changes=", RMF(xb_upd_changes_set), 1); #endif xb_cDoc = rb_define_class_under(xb_mXML, "Document", rb_cObject); rb_include_module(xb_cDoc, rb_mEnumerable); #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_define_alloc_func(xb_cDoc, RMFS(xb_doc_s_alloc)); #else rb_define_singleton_method(xb_cDoc, "allocate", RMFS(xb_doc_s_alloc), 0); #endif rb_define_singleton_method(xb_cDoc, "new", RMF(xb_s_new), -1); rb_define_private_method(xb_cDoc, "initialize", RMF(xb_doc_init), 1); rb_define_method(xb_cDoc, "manager", RMF(xb_doc_manager), 0); rb_define_method(xb_cDoc, "name", RMF(xb_doc_name_get), 0); rb_define_method(xb_cDoc, "name=", RMF(xb_doc_name_set), 1); rb_define_method(xb_cDoc, "content", RMF(xb_doc_content_str), 0); rb_define_method(xb_cDoc, "content=", RMF(xb_doc_content_set), 1); rb_define_method(xb_cDoc, "[]", RMF(xb_doc_get), -1); rb_define_method(xb_cDoc, "[]=", RMF(xb_doc_set), -1); rb_define_method(xb_cDoc, "get", RMF(xb_doc_get), -1); rb_define_method(xb_cDoc, "set", RMF(xb_doc_set), -1); rb_define_method(xb_cDoc, "get_metadata", RMF(xb_doc_get), -1); rb_define_method(xb_cDoc, "set_metadata", RMF(xb_doc_set), -1); rb_define_method(xb_cDoc, "remove_metadata", RMF(xb_doc_remove), -1); rb_define_method(xb_cDoc, "each", RMF(xb_doc_each), 0); rb_define_method(xb_cDoc, "each_metadata", RMF(xb_doc_each), 0); rb_define_method(xb_cDoc, "fetch_alldata", RMF(xb_doc_fetch), 0); rb_define_method(xb_cDoc, "fetch", RMF(xb_doc_fetch), 0); rb_define_method(xb_cDoc, "to_s", RMF(xb_doc_content_str), 0); rb_define_method(xb_cDoc, "to_str", RMF(xb_doc_content_str), 0); rb_define_method(xb_cDoc, "release", RMF(xb_doc_close), 0); #if HAVE_DBXML_XML_EVENT_READER rb_define_method(xb_cDoc, "event_reader", RMF(xb_doc_erd), 0); rb_define_method(xb_cDoc, "get_content_as_event_reader", RMF(xb_doc_erd), 0); #endif xb_cCxt = rb_define_class_under(xb_mXML, "Context", rb_cObject); rb_const_set(xb_mXML, rb_intern("QueryContext"), xb_cCxt); #if HAVE_DBXML_CONST_XMLQUERYCONTEXT_LIVEVALUES rb_define_const(xb_cCxt, "LiveValues", INT2NUM(XmlQueryContext::LiveValues)); #endif #if HAVE_DBXML_CONST_XMLQUERYCONTEXT_DEADVALUES rb_define_const(xb_cCxt, "DeadValues", INT2NUM(XmlQueryContext::DeadValues)); #endif #if HAVE_DBXML_CONST_XMLQUERYCONTEXT_EAGER rb_define_const(xb_cCxt, "Eager", INT2NUM(XmlQueryContext::Eager)); #endif #if HAVE_DBXML_CONST_XMLQUERYCONTEXT_LAZY rb_define_const(xb_cCxt, "Lazy", INT2NUM(XmlQueryContext::Lazy)); #endif #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_define_alloc_func(xb_cCxt, RMFS(xb_cxt_s_alloc)); #else rb_define_singleton_method(xb_cCxt, "allocate", RMFS(xb_cxt_s_alloc), 0); #endif rb_define_singleton_method(xb_cCxt, "new", RMF(xb_s_new), -1); rb_define_private_method(xb_cCxt, "initialize", RMF(xb_cxt_init), -1); rb_define_method(xb_cCxt, "manager", RMF(xb_cxt_manager), 0); rb_define_method(xb_cCxt, "set_namespace", RMF(xb_cxt_name_set), 2); rb_define_method(xb_cCxt, "get_namespace", RMF(xb_cxt_name_get), 1); rb_define_method(xb_cCxt, "del_namespace", RMF(xb_cxt_name_del), 1); rb_define_method(xb_cCxt, "remove_namespace", RMF(xb_cxt_name_del), 1); rb_define_method(xb_cCxt, "clear", RMF(xb_cxt_clear), 0); rb_define_method(xb_cCxt, "clear_namespaces", RMF(xb_cxt_clear), 0); rb_define_method(xb_cCxt, "[]", RMF(xb_cxt_get), 1); rb_define_method(xb_cCxt, "[]=", RMF(xb_cxt_set), 2); rb_define_method(xb_cCxt, "returntype", RMF(xb_cxt_return_get), 0); rb_define_method(xb_cCxt, "returntype=", RMF(xb_cxt_return_set), 1); rb_define_method(xb_cCxt, "evaltype", RMF(xb_cxt_eval_get), 0); rb_define_method(xb_cCxt, "evaltype=", RMF(xb_cxt_eval_set), 1); rb_define_method(xb_cCxt, "uri", RMF(xb_cxt_uri_get), 0); rb_define_method(xb_cCxt, "uri=", RMF(xb_cxt_uri_set), 1); rb_define_method(xb_cCxt, "base_uri", RMF(xb_cxt_uri_get), 0); rb_define_method(xb_cCxt, "base_uri=", RMF(xb_cxt_uri_set), 1); #if HAVE_DBXML_CXT_VARIABLE_VALUE rb_define_method(xb_cCxt, "get_results", RMF(xb_cxt_get_results), 1); #endif #if HAVE_DBXML_CXT_COLLECTION rb_define_method(xb_cCxt, "collection", RMF(xb_cxt_coll_get), 0); rb_define_method(xb_cCxt, "collection=", RMF(xb_cxt_coll_set), 1); #endif #if HAVE_DBXML_CXT_INTERRUPT rb_define_method(xb_cCxt, "interrupt_query", RMF(xb_cxt_interrupt), 0); #endif #if HAVE_DBXML_CXT_TIMEOUT rb_define_method(xb_cCxt, "query_timeout", RMF(xb_cxt_get_timeout), 0); rb_define_method(xb_cCxt, "query_timeout=", RMF(xb_cxt_set_timeout), 1); #endif xb_cQue = rb_define_class_under(xb_mXML, "Query", rb_cObject); rb_const_set(xb_mXML, rb_intern("QueryExpression"), xb_cQue); rb_undef_method(CLASS_OF(xb_cQue), "allocate"); rb_undef_method(CLASS_OF(xb_cQue), "new"); rb_define_private_method(xb_cQue, "__txn_dup__", RMF(xb_que_txn_dup), 1); rb_define_private_method(xb_cQue, "__txn_close__", RMF(xb_que_txn_close), 2); rb_define_method(xb_cQue, "manager", RMF(xb_que_manager), 0); rb_define_method(xb_cQue, "transaction", RMF(xb_que_txn), 0); rb_define_method(xb_cQue, "txn", RMF(xb_que_txn), 0); rb_define_method(xb_cQue, "transaction?", RMF(xb_que_txn_p), 0); rb_define_method(xb_cQue, "txn?", RMF(xb_que_txn_p), 0); rb_define_method(xb_cQue, "in_transaction?", RMF(xb_que_txn_p), 0); rb_define_method(xb_cQue, "in_txn?", RMF(xb_que_txn_p), 0); rb_define_method(xb_cQue, "execute", RMF(xb_que_exec), -1); rb_define_method(xb_cQue, "to_s", RMF(xb_que_to_str), 0); rb_define_method(xb_cQue, "to_str", RMF(xb_que_to_str), 0); #if HAVE_DBXML_QUE_UPDATE rb_define_method(xb_cQue, "update?", RMF(xb_que_update), 0); #endif xb_cRes = rb_define_class_under(xb_mXML, "Results", rb_cObject); rb_include_module(xb_cRes, rb_mEnumerable); #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_define_alloc_func(xb_cRes, RMFS(xb_res_s_alloc)); #else rb_define_singleton_method(xb_cRes, "allocate", RMFS(xb_res_s_alloc), 0); #endif rb_define_singleton_method(xb_cRes, "new", RMF(xb_s_new), -1); rb_define_private_method(xb_cRes, "initialize", RMF(xb_res_init), 1); rb_define_method(xb_cRes, "manager", RMF(xb_res_manager), 0); rb_define_method(xb_cRes, "add", RMF(xb_res_add), 1); rb_define_method(xb_cRes, "each", RMF(xb_res_each), 0); rb_define_method(xb_cRes, "size", RMF(xb_res_size), 0); #if HAVE_DBXML_RES_EVAL rb_define_method(xb_cRes, "evaluation_type", RMF(xb_res_eval), 0); #endif xb_cMod = rb_define_class_under(xb_mXML, "Modify", rb_cObject); #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_define_alloc_func(xb_cMod, RMFS(xb_mod_s_alloc)); #else rb_define_singleton_method(xb_cMod, "allocate", RMFS(xb_mod_s_alloc), 0); #endif rb_define_singleton_method(xb_cMod, "new", RMF(xb_s_new), -1); rb_define_private_method(xb_cMod, "initialize", RMF(xb_mod_init), 1); #if HAVE_DBXML_CONST_XMLMODIFY_ELEMENT rb_define_const(xb_cMod, "Element", INT2NUM(XmlModify::Element)); #endif #if HAVE_DBXML_CONST_XMLMODIFY_ATTRIBUTE rb_define_const(xb_cMod, "Attribute", INT2NUM(XmlModify::Attribute)); #endif #if HAVE_DBXML_CONST_XMLMODIFY_TEXT rb_define_const(xb_cMod, "Text", INT2NUM(XmlModify::Text)); #endif #if HAVE_DBXML_CONST_XMLMODIFY_COMMENT rb_define_const(xb_cMod, "Comment", INT2NUM(XmlModify::Comment)); #endif #if HAVE_DBXML_CONST_XMLMODIFY_PROCESSINGINSTRUCTION rb_define_const(xb_cMod, "PI", INT2NUM(XmlModify::ProcessingInstruction)); #endif #if HAVE_DBXML_CONST_XMLMODIFY_PROCESSINGINSTRUCTION rb_define_const(xb_cMod, "ProcessingInstruction", INT2NUM(XmlModify::ProcessingInstruction)); #endif rb_define_private_method(xb_cMod, "__txn_dup__", RMF(xb_mod_txn_dup), 1); rb_define_private_method(xb_cMod, "__txn_close__", RMF(xb_mod_txn_close), 2); rb_define_method(xb_cMod, "manager", RMF(xb_mod_manager), 0); rb_define_method(xb_cMod, "transaction", RMF(xb_mod_txn), 0); rb_define_method(xb_cMod, "txn", RMF(xb_mod_txn), 0); rb_define_method(xb_cMod, "transaction?", RMF(xb_mod_txn_p), 0); rb_define_method(xb_cMod, "txn?", RMF(xb_mod_txn_p), 0); rb_define_method(xb_cMod, "in_transaction?", RMF(xb_mod_txn_p), 0); rb_define_method(xb_cMod, "in_txn?", RMF(xb_mod_txn_p), 0); #if HAVE_DBXML_MOD_ENCODING rb_define_method(xb_cMod, "encoding=", RMF(xb_mod_encoding), 1); #endif rb_define_method(xb_cMod, "append", RMF(xb_mod_append), -1); rb_define_method(xb_cMod, "insert_after", RMF(xb_mod_insert_after), 4); rb_define_method(xb_cMod, "insert_before", RMF(xb_mod_insert_before), 4); rb_define_method(xb_cMod, "remove", RMF(xb_mod_remove), 1); rb_define_method(xb_cMod, "rename", RMF(xb_mod_rename), 2); rb_define_method(xb_cMod, "update", RMF(xb_mod_update), 2); rb_define_method(xb_cMod, "execute", RMF(xb_mod_execute), -1); xb_cVal = rb_define_class_under(xb_mXML, "Value", rb_cObject); #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_define_alloc_func(xb_cVal, RMFS(xb_val_s_alloc)); #else rb_define_singleton_method(xb_cVal, "allocate", RMFS(xb_val_s_alloc), 0); #endif rb_define_singleton_method(xb_cVal, "new", RMF(xb_s_new), -1); rb_define_private_method(xb_cVal, "initialize", RMF(xb_val_init), -1); #if HAVE_DBXML_CONST_XMLVALUE_NONE rb_define_const(xb_cVal, "NONE", INT2NUM(XmlValue::NONE)); #endif #if HAVE_DBXML_CONST_XMLVALUE_NODE rb_define_const(xb_cVal, "NODE", INT2NUM(XmlValue::NODE)); #endif #if HAVE_DBXML_CONST_XMLVALUE_ANY_SIMPLE_TYPE rb_define_const(xb_cVal, "ANY_SIMPLE_TYPE", INT2NUM(XmlValue::ANY_SIMPLE_TYPE)); #endif #if HAVE_DBXML_CONST_XMLVALUE_ANY_URI rb_define_const(xb_cVal, "ANY_URI", INT2NUM(XmlValue::ANY_URI)); #endif #if HAVE_DBXML_CONST_XMLVALUE_BASE_64_BINARY rb_define_const(xb_cVal, "BASE_64_BINARY", INT2NUM(XmlValue::BASE_64_BINARY)); #endif #if HAVE_DBXML_CONST_XMLVALUE_BOOLEAN rb_define_const(xb_cVal, "BOOLEAN", INT2NUM(XmlValue::BOOLEAN)); #endif #if HAVE_DBXML_CONST_XMLVALUE_DATE rb_define_const(xb_cVal, "DATE", INT2NUM(XmlValue::DATE)); #endif #if HAVE_DBXML_CONST_XMLVALUE_DATE_TIME rb_define_const(xb_cVal, "DATE_TIME", INT2NUM(XmlValue::DATE_TIME)); #endif #if HAVE_DBXML_CONST_XMLVALUE_DAY_TIME_DURATION rb_define_const(xb_cVal, "DAY_TIME_DURATION", INT2NUM(XmlValue::DAY_TIME_DURATION)); #endif #if HAVE_DBXML_CONST_XMLVALUE_DECIMAL rb_define_const(xb_cVal, "DECIMAL", INT2NUM(XmlValue::DECIMAL)); #endif #if HAVE_DBXML_CONST_XMLVALUE_DOUBLE rb_define_const(xb_cVal, "DOUBLE", INT2NUM(XmlValue::DOUBLE)); #endif #if HAVE_DBXML_CONST_XMLVALUE_DURATION rb_define_const(xb_cVal, "DURATION", INT2NUM(XmlValue::DURATION)); #endif #if HAVE_DBXML_CONST_XMLVALUE_FLOAT rb_define_const(xb_cVal, "FLOAT", INT2NUM(XmlValue::FLOAT)); #endif #if HAVE_DBXML_CONST_XMLVALUE_G_DAY rb_define_const(xb_cVal, "G_DAY", INT2NUM(XmlValue::G_DAY)); #endif #if HAVE_DBXML_CONST_XMLVALUE_G_MONTH rb_define_const(xb_cVal, "G_MONTH", INT2NUM(XmlValue::G_MONTH)); #endif #if HAVE_DBXML_CONST_XMLVALUE_G_MONTH_DAY rb_define_const(xb_cVal, "G_MONTH_DAY", INT2NUM(XmlValue::G_MONTH_DAY)); #endif #if HAVE_DBXML_CONST_XMLVALUE_G_YEAR rb_define_const(xb_cVal, "G_YEAR", INT2NUM(XmlValue::G_YEAR)); #endif #if HAVE_DBXML_CONST_XMLVALUE_G_YEAR_MONTH rb_define_const(xb_cVal, "G_YEAR_MONTH", INT2NUM(XmlValue::G_YEAR_MONTH)); #endif #if HAVE_DBXML_CONST_XMLVALUE_HEX_BINARY rb_define_const(xb_cVal, "HEX_BINARY", INT2NUM(XmlValue::HEX_BINARY)); #endif #if HAVE_DBXML_CONST_XMLVALUE_NOTATION rb_define_const(xb_cVal, "NOTATION", INT2NUM(XmlValue::NOTATION)); #endif #if HAVE_DBXML_CONST_XMLVALUE_QNAME rb_define_const(xb_cVal, "QNAME", INT2NUM(XmlValue::QNAME)); #endif #if HAVE_DBXML_CONST_XMLVALUE_STRING rb_define_const(xb_cVal, "STRING", INT2NUM(XmlValue::STRING)); #endif #if HAVE_DBXML_CONST_XMLVALUE_TIME rb_define_const(xb_cVal, "TIME", INT2NUM(XmlValue::TIME)); #endif #if HAVE_DBXML_CONST_XMLVALUE_YEAR_MONTH_DURATION rb_define_const(xb_cVal, "YEAR_MONTH_DURATION", INT2NUM(XmlValue::YEAR_MONTH_DURATION)); #endif #if HAVE_DBXML_CONST_XMLVALUE_UNTYPED_ATOMIC rb_define_const(xb_cVal, "UNTYPED_ATOMIC", INT2NUM(XmlValue::UNTYPED_ATOMIC )); #endif rb_define_method(xb_cVal, "to_document", RMF(xb_val_to_doc), 0); rb_define_method(xb_cVal, "to_f", RMF(xb_val_to_f), 0); rb_define_method(xb_cVal, "to_s", RMF(xb_val_to_str), 0); rb_define_method(xb_cVal, "to_str", RMF(xb_val_to_str), 0); rb_define_method(xb_cVal, "type", RMF(xb_val_type), 0); rb_define_method(xb_cVal, "type?", RMF(xb_val_type_p), 1); rb_define_method(xb_cVal, "nil?", RMF(xb_val_nil_p), 1); rb_define_method(xb_cVal, "number?", RMF(xb_val_number_p), 1); rb_define_method(xb_cVal, "string?", RMF(xb_val_string_p), 1); rb_define_method(xb_cVal, "boolean?", RMF(xb_val_boolean_p), 1); rb_define_method(xb_cVal, "node?", RMF(xb_val_node_p), 1); rb_define_method(xb_cVal, "node_name", RMF(xb_val_node_name), 0); rb_define_method(xb_cVal, "node_value", RMF(xb_val_node_value), 0); rb_define_method(xb_cVal, "node_type", RMF(xb_val_node_type), 0); rb_define_method(xb_cVal, "namespace", RMF(xb_val_namespace), 0); rb_define_method(xb_cVal, "namespace_uri", RMF(xb_val_namespace), 0); rb_define_method(xb_cVal, "prefix", RMF(xb_val_prefix), 0); rb_define_method(xb_cVal, "local_name", RMF(xb_val_local_name), 0); rb_define_method(xb_cVal, "parent_node", RMF(xb_val_parent_node), 0); rb_define_method(xb_cVal, "first_child", RMF(xb_val_first_child), 0); rb_define_method(xb_cVal, "last_child", RMF(xb_val_last_child), 0); rb_define_method(xb_cVal, "previous_sibling", RMF(xb_val_previous_sibling), 0); rb_define_method(xb_cVal, "next_sibling", RMF(xb_val_next_sibling), 0); rb_define_method(xb_cVal, "owner_element", RMF(xb_val_owner_element), 0); rb_define_method(xb_cVal, "attributes", RMF(xb_val_attributes), 0); #if HAVE_DBXML_VAL_TYPE_URI rb_define_method(xb_cVal, "type_uri", RMF(xb_val_type_uri), 0); #endif #if HAVE_DBXML_VAL_TYPE_NAME rb_define_method(xb_cVal, "type_name", RMF(xb_val_type_name), 0); #endif #if HAVE_DBXML_VAL_NODE_HANDLE rb_define_method(xb_cVal, "node_handle", RMF(xb_val_node_handle), 0); #endif #if HAVE_DBXML_XML_EVENT_WRITER xb_cEwr = rb_define_class_under(xb_mXML, "EventWriter", rb_cObject); #if HAVE_DBXML_XML_EVENT_WRITER_ALLOC #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_define_alloc_func(xb_cEwr, RMFS(xb_ewr_s_alloc)); #else rb_define_singleton_method(xb_cEwr, "allocate", RMFS(xb_ewr_s_alloc), 0); #endif rb_define_singleton_method(xb_cEwr, "new", RMF(xb_s_new), -1); rb_define_private_method(xb_cEwr, "initialize", RMF(xb_ewr_init), 0); #else rb_undef_alloc_func(xb_cEwr); #endif rb_define_method(xb_cEwr, "close", RMF(xb_ewr_close), 0); rb_define_method(xb_cEwr, "attribute", RMF(xb_ewr_attribute), 5); rb_define_method(xb_cEwr, "dtd", RMF(xb_ewr_dtd), 1); rb_define_method(xb_cEwr, "end_document", RMF(xb_ewr_end_doc), 0); rb_define_method(xb_cEwr, "end_element", RMF(xb_ewr_end_ele), -1); rb_define_method(xb_cEwr, "end_entity", RMF(xb_ewr_end_ent), 1); rb_define_method(xb_cEwr, "processing_instruction", RMF(xb_ewr_pi), 2); rb_define_method(xb_cEwr, "start_element", RMF(xb_ewr_start_ele), 5); rb_define_method(xb_cEwr, "start_entity", RMF(xb_ewr_start_ent), 2); rb_define_method(xb_cEwr, "start_document", RMF(xb_ewr_start_doc), -1); rb_define_method(xb_cEwr, "text", RMF(xb_ewr_txt), 2); #endif #if HAVE_DBXML_XML_EVENT_READER xb_cErd = rb_define_class_under(xb_mXML, "EventReader", rb_cObject); #if HAVE_DBXML_XML_EVENT_READER_ALLOC #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_define_alloc_func(xb_cErd, RMFS(xb_erd_s_alloc)); #else rb_define_singleton_method(xb_cErd, "allocate", RMFS(xb_erd_s_alloc), 0); #endif rb_define_singleton_method(xb_cErd, "new", RMF(xb_s_new), -1); rb_define_private_method(xb_cErd, "initialize", RMF(xb_erd_init), 0); #else rb_undef_alloc_func(xb_cErd); #endif #if HAVE_DBXML_CONST_XMLEVENTREADER_STARTELEMENT rb_define_const(xb_cErd, "StartElement", INT2NUM(XmlEventReader::StartElement)); #endif #if HAVE_DBXML_CONST_XMLEVENTREADER_ENDELEMENT rb_define_const(xb_cErd, "EndElement", INT2NUM(XmlEventReader::EndElement)); #endif #if HAVE_DBXML_CONST_XMLEVENTREADER_CHARACTERS rb_define_const(xb_cErd, "Characters", INT2NUM(XmlEventReader::Characters)); #endif #if HAVE_DBXML_CONST_XMLEVENTREADER_CDATA rb_define_const(xb_cErd, "CDATA", INT2NUM(XmlEventReader::CDATA)); #endif #if HAVE_DBXML_CONST_XMLEVENTREADER_COMMENT rb_define_const(xb_cErd, "Comment", INT2NUM(XmlEventReader::Comment)); #endif #if HAVE_DBXML_CONST_XMLEVENTREADER_WHITESPACE rb_define_const(xb_cErd, "Whitespace", INT2NUM(XmlEventReader::Whitespace)); #endif #if HAVE_DBXML_CONST_XMLEVENTREADER_STARTDOCUMENT rb_define_const(xb_cErd, "StartDocument", INT2NUM(XmlEventReader::StartDocument)); #endif #if HAVE_DBXML_CONST_XMLEVENTREADER_ENDDOCUMENT rb_define_const(xb_cErd, "EndDocument", INT2NUM(XmlEventReader::EndDocument)); #endif #if HAVE_DBXML_CONST_XMLEVENTREADER_STARTENTITYREFERENCE rb_define_const(xb_cErd, "StartEntityReference", INT2NUM(XmlEventReader::StartEntityReference)); #endif #if HAVE_DBXML_CONST_XMLEVENTREADER_ENDENTITYREFERENCE rb_define_const(xb_cErd, "EndEntityReference", INT2NUM(XmlEventReader::EndEntityReference)); #endif #if HAVE_DBXML_CONST_XMLEVENTREADER_PROCESSINGINSTRUCTION rb_define_const(xb_cErd, "ProcessingInstruction", INT2NUM(XmlEventReader::ProcessingInstruction)); #endif #if HAVE_DBXML_CONST_XMLEVENTREADER_DTD rb_define_const(xb_cErd, "DTD", INT2NUM(XmlEventReader::DTD)); #endif rb_define_method(xb_cErd, "close", RMF(xb_erd_close), 0); rb_define_method(xb_cErd, "event_type", RMF(xb_erd_ev), 0); rb_define_method(xb_cErd, "namespace_uri", RMF(xb_erd_uri), 0); rb_define_method(xb_cErd, "local_name", RMF(xb_erd_name), 0); rb_define_method(xb_cErd, "prefix", RMF(xb_erd_prefix), 0); rb_define_method(xb_cErd, "value", RMF(xb_erd_value), 0); rb_define_method(xb_cErd, "attribute_count", RMF(xb_erd_attr_count), 0); rb_define_method(xb_cErd, "attribute_specified?", RMF(xb_erd_attr_p), 1); rb_define_method(xb_cErd, "attribute_namespace_uri", RMF(xb_erd_attr_uri), 1); rb_define_method(xb_cErd, "attribute_local_name", RMF(xb_erd_attr_name), 1); rb_define_method(xb_cErd, "attribute_prefix", RMF(xb_erd_attr_prefix), 1); rb_define_method(xb_cErd, "attribute_value", RMF(xb_erd_attr_value), 1); rb_define_method(xb_cErd, "empty_element_info?", RMF(xb_erd_info_p), 0); rb_define_method(xb_cErd, "entity_escape_info?", RMF(xb_erd_escape_p), 0); rb_define_method(xb_cErd, "next?", RMF(xb_erd_next_p), 0); rb_define_method(xb_cErd, "empty_element?", RMF(xb_erd_empty_p), 0); rb_define_method(xb_cErd, "whitespace?", RMF(xb_erd_white_p), 0); rb_define_method(xb_cErd, "entity_escape?", RMF(xb_erd_nescape_p), -1); rb_define_method(xb_cErd, "next", RMF(xb_erd_next), 0); rb_define_method(xb_cErd, "next_tag", RMF(xb_erd_next_tag), 0); rb_define_method(xb_cErd, "expand_entities?", RMF(xb_erd_get_expand), 0); rb_define_method(xb_cErd, "expand_entities=", RMF(xb_erd_set_expand), 1); rb_define_method(xb_cErd, "entity_info?", RMF(xb_erd_get_info), 0); rb_define_method(xb_cErd, "entity_info=", RMF(xb_erd_set_info), 1); rb_define_method(xb_cErd, "encoding", RMF(xb_erd_encoding), 0); rb_define_method(xb_cErd, "encoding?", RMF(xb_erd_encoding_p), 0); rb_define_method(xb_cErd, "version", RMF(xb_erd_version), 0); rb_define_method(xb_cErd, "system_id", RMF(xb_erd_system), 0); rb_define_method(xb_cErd, "document_standalone?", RMF(xb_erd_doc_stand_p), 0); rb_define_method(xb_cErd, "standalone?", RMF(xb_erd_attr_stand_p), 0); rb_define_method(xb_cVal, "to_event_reader", RMF(xb_val_to_erd), 0); rb_define_method(xb_cVal, "event_reader", RMF(xb_val_to_erd), 0); #endif } } ruby-bdb-0.6.6/bdbxml2/bdbxml.h000066400000000000000000000221301154714021300162000ustar00rootroot00000000000000#include "bdb.h" #include "bdbxml_features.h" #include #include using namespace DbXml; #define RMF(func) RUBY_METHOD_FUNC(func) #define RDF RUBY_DATA_FUNC #if HAVE_DBXML_RB_NEW_PROTO #define RMFS(func) ((VALUE (*)(VALUE))func) #define RMFF(func) ((void (*)(VALUE))func) #else #define RMFS(func) RMF(func) #define RMFF(func) ((void (*)())func) #endif #define BDBXML_VERSION (10000*DBXML_VERSION_MAJOR+100*DBXML_VERSION_MINOR+DBXML_VERSION_PATCH) #define PROTECT2(comm_, libr_) \ try { \ comm_; \ libr_; \ } \ catch (XmlException &e) { \ VALUE xb_err = Qnil; \ libr_; \ if ((xb_err = bdb_return_err()) != Qnil) { \ rb_raise(xb_eFatal, StringValuePtr(xb_err)); \ } \ rb_raise(xb_eFatal, e.what()); \ } \ catch (DbException &e) { \ VALUE xb_err = Qnil; \ libr_; \ if ((xb_err = bdb_return_err()) != Qnil) { \ rb_raise(xb_eFatal, StringValuePtr(xb_err)); \ } \ rb_raise(xb_eFatal, e.what()); \ } \ catch (std::exception &e) { \ libr_; \ rb_raise(xb_eFatal, e.what()); \ } \ catch (...) { \ libr_; \ rb_raise(xb_eFatal, "Unknown error"); \ } #define PROTECT(comm_) PROTECT2(comm_,) typedef struct { XmlManager *man; VALUE env; VALUE rsv; VALUE ori; } xman; typedef struct { XmlContainer *con; VALUE ind; VALUE txn; VALUE man; int opened; #if HAVE_DBXML_XML_INDEX_LOOKUP VALUE look; #endif } xcon; typedef struct { XmlIndexSpecification *ind; VALUE con; } xind; #if HAVE_DBXML_XML_INDEX_LOOKUP typedef struct { XmlIndexLookup *look; VALUE man; VALUE txn; VALUE con; } xlook; #endif #if HAVE_DBXML_XML_EVENT_WRITER typedef struct { XmlEventWriter *ewr; VALUE con; } xewr; #endif #if HAVE_DBXML_XML_EVENT_READER typedef struct { XmlEventReader *erd; VALUE doc; } xerd; #endif typedef struct { XmlResults *res; VALUE man; } xres; typedef struct { XmlDocument *doc; VALUE man; } xdoc; typedef struct { XmlUpdateContext *upd; VALUE man; } xupd; typedef struct { XmlModify *mod; VALUE txn; VALUE man; } xmod; typedef struct { XmlQueryContext *cxt; VALUE man; } xcxt; typedef struct { XmlQueryExpression *que; VALUE txn; VALUE man; } xque; typedef struct { XmlValue *val; VALUE man; } xval; static VALUE xb_eFatal, xb_cTxn; static void xb_man_free(xman *); static inline xman * get_man(VALUE obj) { xman *man; if (TYPE(obj) != T_DATA || RDATA(obj)->dfree != (RDF)xb_man_free) { rb_raise(xb_eFatal, "invalid Manager objects"); } Data_Get_Struct(obj, xman, man); if (!man->man) { rb_raise(rb_eArgError, "invalid Manager object"); } return man; } static inline xres * get_res(VALUE obj) { xres *res; Data_Get_Struct(obj, xres, res); if (!res->res) { rb_raise(rb_eArgError, "invalid Results"); } get_man(res->man); return res; } static inline xval * get_val(VALUE obj) { xval *val; Data_Get_Struct(obj, xval, val); if (!val->val) { rb_raise(rb_eArgError, "invalid Value"); } get_man(val->man); return val; } static void xb_doc_mark(xdoc *); static inline xdoc * get_doc(VALUE obj) { xdoc *doc; if (TYPE(obj) != T_DATA || RDATA(obj)->dmark != (RDF)xb_doc_mark) { rb_raise(rb_eArgError, "invalid document"); } Data_Get_Struct(obj, xdoc, doc); if (!doc->doc) { rb_raise(rb_eArgError, "invalid document"); } return doc; } static inline XmlTransaction * get_txn(VALUE obj) { if (rb_obj_is_kind_of(obj, xb_cTxn)) { bdb_TXN *txnst; GetTxnDBErr(obj, txnst, xb_eFatal); return (XmlTransaction *)txnst->txn_cxx; } return 0; } static inline xman * get_man_txn(VALUE obj) { if (rb_obj_is_kind_of(obj, xb_cTxn)) { bdb_TXN *txnst; GetTxnDBErr(obj, txnst, xb_eFatal); return get_man(txnst->man); } else { return get_man(obj); } } static void xb_upd_free(xupd *); static inline xupd * get_upd(VALUE obj) { xupd *upd; if (TYPE(obj) != T_DATA || RDATA(obj)->dfree != (RDF)xb_upd_free) { rb_raise(rb_eArgError, "expected an Update Context"); } Data_Get_Struct(obj, xupd, upd); if (!upd->upd) { rb_raise(rb_eArgError, "invalid Update Context"); } get_man(upd->man); return upd; } static inline VALUE get_txn_man(VALUE obj) { if (rb_obj_is_kind_of(obj, xb_cTxn)) { bdb_TXN *txnst; GetTxnDBErr(obj, txnst, xb_eFatal); return txnst->man; } return 0; } static void xb_cxt_free(xcxt *); static inline xcxt * get_cxt(VALUE obj) { xcxt *cxt; if (TYPE(obj) != T_DATA || RDATA(obj)->dfree != (RDF)xb_cxt_free) { rb_raise(rb_eArgError, "expected a Query Context"); } Data_Get_Struct(obj, xcxt, cxt); if (!cxt->cxt) { rb_raise(rb_eArgError, "invalid QueryContext"); } get_man(cxt->man); return cxt; } static void xb_con_mark(xcon *); static inline xcon * get_con(VALUE obj) { xcon *con; if (TYPE(obj) != T_DATA || RDATA(obj)->dmark != (RDF)xb_con_mark) { rb_raise(rb_eArgError, "invalid Container"); } Data_Get_Struct(obj, xcon, con); if (!con->opened) { rb_raise(rb_eArgError, "closed container"); } if (!con->con || !con->man) { rb_raise(rb_eArgError, "invalid Container"); } get_man(con->man); return con; } static inline XmlTransaction * get_con_txn(xcon *con) { if (RTEST(con->txn)) { bdb_TXN *txnst; GetTxnDBErr(con->txn, txnst, xb_eFatal); return (XmlTransaction *)txnst->txn_cxx; } return 0; } static void xb_ind_free(xind *); static inline xind * get_ind(VALUE obj) { if (TYPE(obj) != T_DATA || RDATA(obj)->dfree != (RDF)xb_ind_free) { rb_raise(rb_eArgError, "expected an IndexSpecification object"); } xind *ind; Data_Get_Struct(obj, xind, ind); if (!ind->ind) { rb_raise(rb_eArgError, "expected an IndexSpecification object"); } return ind; } #if HAVE_DBXML_XML_INDEX_LOOKUP static void xb_look_mark(xlook *); static inline xlook * get_look(VALUE obj) { xlook *look; if (TYPE(obj) != T_DATA || RDATA(obj)->dmark != (RDF)xb_look_mark) { rb_raise(rb_eArgError, "invalid IndexLookup"); } Data_Get_Struct(obj, xlook, look); if (!look->look || !look->man || !look->con) { rb_raise(rb_eArgError, "invalid IndexLookup"); } get_man(look->man); get_con(look->con); return look; } #endif static void xb_que_mark(xque *); static inline xque * get_que(VALUE obj) { xque *que; if (TYPE(obj) != T_DATA || RDATA(obj)->dmark != (RDF)xb_que_mark) { rb_raise(rb_eArgError, "expected a Query Expression"); } Data_Get_Struct(obj, xque, que); if (!que->que) { rb_raise(rb_eArgError, "invalid QueryExpression"); } get_man(que->man); return que; } static inline xmod * get_mod(VALUE obj) { xmod *mod; Data_Get_Struct(obj, xmod, mod); if (!mod->mod) { rb_raise(rb_eArgError, "invalid Modify"); } get_man(mod->man); return mod; } static inline void rset_obj(VALUE obj) { RBASIC(obj)->klass = rb_cData; RDATA(obj)->dfree = (RDF)free; RDATA(obj)->dmark = 0; } static void xb_res_free(xres *res); static void xb_res_mark(xres *res); #if HAVE_DBXML_XML_EVENT_WRITER static void xb_ewr_free(xewr *ewr); static void xb_ewr_mark(xewr *ewr); static inline xewr * get_ewr(VALUE obj) { xewr *ewr; if (TYPE(obj) != T_DATA || RDATA(obj)->dmark != (RDF)xb_ewr_mark) { rb_raise(rb_eArgError, "expected a XML::EventWriter"); } Data_Get_Struct(obj, xewr, ewr); if (!ewr->ewr) { rb_raise(rb_eArgError, "closed XML::EventWriter"); } get_con(ewr->con); return ewr; } #endif #if HAVE_DBXML_XML_EVENT_READER static void xb_erd_free(xerd *erd); static void xb_erd_mark(xerd *erd); static inline xerd * get_erd(VALUE obj) { xerd *erd; if (TYPE(obj) != T_DATA || RDATA(obj)->dmark != (RDF)xb_erd_mark) { rb_raise(rb_eArgError, "expected a XML::EventReader"); } Data_Get_Struct(obj, xerd, erd); if (!erd->erd) { rb_raise(rb_eArgError, "closed XML::EventReader"); } return erd; } #endif ruby-bdb-0.6.6/bdbxml2/bdbxml.rd000066400000000000000000000100231154714021300163540ustar00rootroot00000000000000=begin Berkeley DB XML is an embedded native XML datastore that provides for the efficient storage and retrieval of XML encoded information. Retrieval is supported by an Query query engine that derives its efficiency from indices generated from the stored XML data. The following classes are defined (()) Provides a high-level object used to manage various aspects of Berkeley DB XML usage. You use XML::Manager to perform activities such as container management (including creation and open), preparing XQuery queries, executing one-off queries, creating transaction objects, creating update and query context objects A XML::Manager object can be created with BDB::Envmanager BDB::Transaction respond to the same method than BDB::XML::Manager (()) The XML::Container class encapsulates a document container and its related indices and statistics. XML::Container exposes methods for managing (putting and deleting) XML::Document objects, managing indices, and retrieving container statistics. (()) Define the indexing strategy for a Container Indexing is specified by providing the name of a node and a list of indexing strategies for that node. (()) A Document is the unit of storage within a Container. A document consists of content, a name, and a set of metadata attributes. The document content is a byte stream. It must be well formed XML, but need not be valid. (()) The Context class encapsulates the context within which a query is performed against an Container. The context includes namespace mappings, variable bindings, and flags that indicate how the query result set should be determined and returned to the caller. Multiple queries can be executed within the same Context; Context allows you to define whether queries executed within the context are to be evaluated lazily or eagerly, and whether the query is to return live or dead values. The Query syntax permits expressions to refer to namespace prefixes, but not to define them. The Context class provides namespace management methods so that the caller may manage the namespace prefix to URI mapping. By default the prefix "dbxml" is defined to be "http://www.sleepycat.com/2002/dbxml". The Query syntax also permits expressions to refer to externally defined variables. The XmlQueryContext class provides methods that allow the caller to manage the externally-declared variable to value bindings. (()) The XML::Modify class encapsulates the context within which a set of one or more documents specified by an XML::Query query can be modified in place. The modification is performed using an XML::Modify object, and a series of methods off that object that identify how the document is to be modified. Using these methods, the modification steps are identified. When the object is executed, these steps are performed in the order that they were specified. The modification steps are executed against one or more documents using XML::Modify::execute. This method can operate on a single document stored in an XML::Value, or against multiple documents stored in an XML::Results set that was created as the result of a container or document query. (()) The results of a query are a collection of values. The values could be either String, Float, true, false, BDB::XML::Value (()) Class which encapsulates the value of a node in an XML document. (()) Class which enables applications to construct document content without using serialized XML. (()) Class which enables applications to read document content via a pull interface without materializing XML as text. =end ruby-bdb-0.6.6/bdbxml2/docs/000077500000000000000000000000001154714021300155115ustar00rootroot00000000000000ruby-bdb-0.6.6/bdbxml2/docs/bdbxml.rb000066400000000000000000000076761154714021300173260ustar00rootroot00000000000000# # Berkeley DB XML is an embedded native XML datastore that provides for # the efficient storage and retrieval of XML encoded information. # # Retrieval is supported by an Query query engine that derives its efficiency # from indices generated from the stored XML data. # # The following classes are defined # # * BDB::XML::Manager # # Provides a high-level object used to manage various aspects of Berkeley # DB XML usage. You use XML::Manager to perform activities such as container # management (including creation and open), preparing XQuery queries, # executing one-off queries, creating transaction objects, # creating update and query context objects # # A XML::Manager object can be created with BDB::Env#manager # # BDB::Transaction respond to the same method than BDB::XML::Manager # # * BDB::XML::Container # # The XML::Container class encapsulates a document container and its # related indices and statistics. XML::Container exposes methods for # managing (putting and deleting) XML::Document objects, managing indices, # and retrieving container statistics. # # * BDB::XML::Index # # Define the indexing strategy for a Container # # Indexing is specified by providing the name of a node and a list of # indexing strategies for that node. # # * BDB::XML::Document # # A Document is the unit of storage within a Container. A document consists # of content, a name, and a set of metadata attributes. # # The document content is a byte stream. It must be well formed XML, # but need not be valid. # # * BDB::XML::Context # # The Context class encapsulates the context within which a query # is performed against an Container. The context includes namespace # mappings, variable bindings, and flags that indicate how the query result # set should be determined and returned to the caller. Multiple queries can # be executed within the same Context; # # Context allows you to define whether queries executed within the # context are to be evaluated lazily or eagerly, and whether the query # is to return live or dead values. # # The Query syntax permits expressions to refer to namespace prefixes, # but not to define them. The Context class provides namespace # management methods so that the caller may manage the namespace prefix to # URI mapping. By default the prefix "dbxml" is defined to be # "http://www.sleepycat.com/2002/dbxml". # # The Query syntax also permits expressions to refer to externally # defined variables. The XmlQueryContext class provides methods that # allow the caller to manage the externally-declared variable to value # bindings. # # * BDB::XML::Modify # # The XML::Modify class encapsulates the context within which a set of one # or more documents specified by an XML::Query query can be modified in # place. The modification is performed using an XML::Modify object, and a # series of methods off that object that identify how the document is to # be modified. Using these methods, the modification steps are # identified. When the object is executed, these steps are performed in # the order that they were specified. # # The modification steps are executed against one or more documents # using XML::Modify::execute. This method can operate on a single document # stored in an XML::Value, or against multiple documents stored in an # XML::Results set that was created as the result of a container or # document query. # # * BDB::XML::Results # # The results of a query are a collection of values. The values could # be either String, Float, true, false, BDB::XML::Value # # * BDB::XML::Value # # Class which encapsulates the value of a node in an XML document. # # * BDB::XML::EventWriter # # Class which enables applications to construct document content without using serialized XML. # # * BDB::XML::EventReader # # Class which enables applications to read document content via a pull interface without # materializing XML as text. # # module BDB::XML end ruby-bdb-0.6.6/bdbxml2/docs/container.rb000066400000000000000000000105101154714021300200150ustar00rootroot00000000000000# # The XML::Container class encapsulates a document container and its # related indices and statistics. XML::Container exposes methods for # managing (putting and deleting) XML::Document objects, managing indices, # and retrieving container statistics. class BDB::XML::Container include Enumerable # Remove the document from the container # # * doc_or_name # doc_or_name is an BDB::XML::Document previously stored, # or the name of an existent document # # * context an optional Update context def delete(doc_or_name, context = nil) end # return the current manager for the container, or nil # def manager end #Iterate over all documents # def each yield doc end #Fetch the document from the container # #* id # the id assigned to the document when it was first added to a container # #* flags # flags can has the value 0 or BDB::DIRTY_READ, BDB::RMW # def self[id] end #same than self[id] def get(id, flags = 0) end #Replace the document (see also #update) # def self[id] = document end #set the indexing : index must be an XML::Index object # def index=(index) end #Retrieve the BDB::XML::Index # #Return nil if no indexing was specified # def index end # return the name of the container # def name end # Return the type of the container def type end # Add a document to the container and return an ID # # * document # an object BDB::XML::Document # # * flags # flags can be 0 or BDB::XML::GEN_NAME # def put(document, flags = 0) end # return the transaction associated with the container, or nil # def transaction end # return true if the container is associated with a transaction # def in_transaction? end #same than in_transaction? def transaction? end # Update a document within the container # # * document an XML::Document to be updated # * context an optional Update context def update(document, context = nil) end # Flush database pages for the container to disk def sync end # Returns true if the container is configured to create node indexes. def index? end # Return database page size. def pagesize end # call-seq: # add_index(uri, name, index, context = nil) # add_index(uri, name, type, syntax, context = nil) # # Add a new index : this is a convenient method. See XML::Index#add def add_index() end # Add the default index : this is a convenient method. See # XML::Index#add_default def add_default(index, context = nil) end # call-seq: # delete_index(uri, name, index, context = nil) # delete_index(uri, name, type, syntax, context = nil) # # Delete the index : this is a convenient method. See XML::Index#delete def delete_index() end # Delete the default index : this is a convenient method. See # XML::Index#delete_default def delete_default(index, context = nil) end # call-seq: # replace_index(uri, name, index, context = nil) # replace_index(uri, name, type, syntax, context = nil) # # Replace the index : this is a convenient method. See XML::Index#replace def replace_index() end # Replace the default index : this is a convenient method. See # XML::Index#replace_default def replace_default(index, context = nil) end # Get the flags used to open the container. def flags end # Get the specified node. # # * handle must be obtained using XML::Value.node_handle # * flags must be set to 0 or, BDB::READ_UNCOMMITED # BDB::READ_UNCOMMITED, BDB::RMW # BDB::XML::LAZY_DOCS def node(handle, flags = 0) end # Begins insertion of an XML::Document into the container through use of an # XML::EventWriter object. # # Return the XML::EventWriter which must be closed at end. # def event_writer(document, update_context, flags = 0) end end ruby-bdb-0.6.6/bdbxml2/docs/container.rd000066400000000000000000000073341154714021300200310ustar00rootroot00000000000000=begin == BDB::XML::Container The XML::Container class encapsulates a document container and its related indices and statistics. XML::Container exposes methods for managing (putting and deleting) XML::Document objects, managing indices, and retrieving container statistics. Module included : Enumerable === Methods --- delete(doc_or_name, context = nil) Remove the document from the container : ((|doc_or_name|)) doc_or_name is an ((|BDB::XML::Document|)) previously stored, or the name of an existent document : ((|context|)) an optional Update context --- index? Returns true if the container is configured to create node indexes. --- manager return the current manager for the container, or ((|nil|)) --- pagesize Returns true if the container is configured to create node indexes. --- each {|doc| ... } Iterate over all documents --- self[id] Fetch the document from the container : ((|id|)) the id assigned to the document when it was first added to a container : ((|flags|)) flags can has the value 0 or ((|BDB::DIRTY_READ|)), ((|BDB::RMW|)) --- get(id, flags = 0) same than ((| self[id]|)) --- self[id] = document Replace the document (see also #update) --- index = index set the indexing : ((|index|)) must be an ((|XML::Index|)) object --- index Retrieve the ((|BDB::XML::Index|)) Return ((|nil|)) if no indexing was specified --- add_index(uri, name, index, context = nil) --- add_index(uri, name, type, syntax, context = nil) Add a new index : this is a convenient method. See ((|XML::Index#add|)) --- add_default_index(index, context = nil) Add default index : this is a convenient method. See ((|XML::Index#add_default|)) --- delete_index(index, context = nil) Delete an index : this is a convenient method. See ((|XML::Index#delete|)) --- delete_default_index(index, context = nil) Delete default index : this is a convenient method. See ((|XML::Index#delete_default|)) --- replace_index(index, context = nil) Replace an index : this is a convenient method. See ((|XML::Index#replace|)) --- replace_default_index(index, context = nil) Replace default index : this is a convenient method. See ((|XML::Index#replace_default|)) --- name return the name of the container --- type Return the type of the container --- put(document, flags = 0) Add a document to the container and return an ID : ((|document|)) an object ((|BDB::XML::Document|)) : ((|flags|)) flags can be 0 or ((|BDB::XML::GEN_NAME|)) --- transaction return the transaction associated with the container, or ((|nil|)) --- in_transaction? return ((|true|)) if the container is associated with a transaction --- transaction? same than ((| in_transaction?|)) --- update(document, context = nil) Update a document within the container : ((|document|)) an XML::Document to be updated : ((|context|)) an optional Update context --- sync Flush database pages for the container to disk --- flags Get the flags used to open the container. --- node(handle, flags = 0) Get the specified node. : ((|handle|)) must be obtained using XML::Value.node_handle : ((|flags|)) must be set to 0 or, ((|BDB::READ_UNCOMMITED|)) ((|BDB::READ_UNCOMMITED|)), ((|BDB::RMW|)) ((|BDB::XML::LAZY_DOCS|)) --- event_writer(document, update_context, flags = 0) Begins insertion of an ((|XML::Document|)) into the container through use of an ((|XML::EventWriter|)) object. Return the ((|XML::EventWriter|)) which must be closed at end. =end ruby-bdb-0.6.6/bdbxml2/docs/context.rb000066400000000000000000000050711154714021300175250ustar00rootroot00000000000000# The Context class encapsulates the context within which a query # is performed against an Container. The context includes namespace # mappings, variable bindings, and flags that indicate how the query result # set should be determined and returned to the caller. Multiple queries can # be executed within the same Context; # # Context allows you to define whether queries executed within the # context are to be evaluated lazily or eagerly, and whether the query # is to return live or dead values. # # The Query syntax permits expressions to refer to namespace prefixes, # but not to define them. The Context class provides namespace # management methods so that the caller may manage the namespace prefix to # URI mapping. By default the prefix "dbxml" is defined to be # "http://www.sleepycat.com/2002/dbxml". # # The Query syntax also permits expressions to refer to externally # defined variables. The XmlQueryContext class provides methods that # allow the caller to manage the externally-declared variable to value # bindings. class BDB::XML::Context # Get the value bound to a variable # def [](variable) end # Bind a value to a variable # def []=(variable, value) end # Delete all the namespace prefix mappings # def clear_namespaces end # Delete the namespace URI for a particular prefix # def del_namespace(name) end # Return the evaluation type # def evaltype end # Set the evaluation type # def evaltype=(type) end # Get the namespace URI that a namespace prefix maps onto # def get_namespace(name) end # Return the return type # def returntype end # Set the return type # def returntype=(type) end #Define a namespace prefix, providing the URI that it maps onto # #If uri is nil delete the namespace def set_namespace(name, uri) end # Returns the base URI used for relative paths in query expressions. def uri end # Sets the base URI used for relative paths in query expressions. def uri=(val) end # Discover the name of the default collection used by fn:collection() # with no arguments in an XQuery expression. def collection end # Set theURI specifying the name of the collection. # # The default collection is that which is used by fn:collection() # without any arguments in an XQuery expression. def collection=(uri) end # Same than Context#[] but return the sequence of values bound to the variable. def get_results(name) end end ruby-bdb-0.6.6/bdbxml2/docs/context.rd000066400000000000000000000045241154714021300175310ustar00rootroot00000000000000=begin == BDB::XML::Context The Context class encapsulates the context within which a query is performed against an Container. The context includes namespace mappings, variable bindings, and flags that indicate how the query result set should be determined and returned to the caller. Multiple queries can be executed within the same Context; Context allows you to define whether queries executed within the context are to be evaluated lazily or eagerly, and whether the query is to return live or dead values. The Query syntax permits expressions to refer to namespace prefixes, but not to define them. The Context class provides namespace management methods so that the caller may manage the namespace prefix to URI mapping. By default the prefix "dbxml" is defined to be "http://www.sleepycat.com/2002/dbxml". The Query syntax also permits expressions to refer to externally defined variables. The XmlQueryContext class provides methods that allow the caller to manage the externally-declared variable to value bindings. === Methods --- self[variable] Get the value bound to a variable --- self[variable] = value Bind a value to a variable --- clear_namespaces Delete all the namespace prefix mappings --- collection Discover the name of the default collection used by fn:collection() with no arguments in an XQuery expression. --- collection = uri Set theURI specifying the name of the collection. The default collection is that which is used by fn:collection() without any arguments in an XQuery expression. --- del_namespace(name) Delete the namespace URI for a particular prefix --- evaltype Return the evaluation type --- evaltype = type Set the evaluation type --- get_namespace(name) Get the namespace URI that a namespace prefix maps onto --- get_results(name) Same than Context#[] but return the sequence of values bound to the variable. --- returntype Return the return type --- returntype = type Set the return type --- set_namespace(name, uri) Define a namespace prefix, providing the URI that it maps onto If ((|uri|)) is ((|nil|)) delete the namespace --- uri Returns the base URI used for relative paths in query expressions. --- uri = val Sets the base URI used for relative paths in query expressions. =end ruby-bdb-0.6.6/bdbxml2/docs/document.rb000066400000000000000000000042751154714021300176640ustar00rootroot00000000000000# A Document is the unit of storage within a Container. A document consists # of content, a name, and a set of metadata attributes. # # The document content is a byte stream. It must be well formed XML, # but need not be valid. class BDB::XML::Document include Enumerable # Returns the value of the specified metadata. # def [](name) end # Set the value of the specified metadata. # def []=(name, val) end # Return the content of the document # def content end # Set the content of the document # def content=(val) end # call-seq: # each # each_metadata # # Iterate over all metadata def each yield uri, name, value end # call-seq: # get_metadata(name) # get_metadata(uri, name) # get(name) # get(uri, name) # # Get the identified metadata from the document. # # * uri The namespace within which the name resides. # * name The name of the metadata attribute to be retrieved. # def get_metadata(uri, name) end # Return the manager def manager end # Return the name of the document # def name end # Set the name of the document # def name=(val) end # call-seq: # remove_metadata(name) # remove_metadata(uri, name) # # Remove the identified metadata from the document. # # * uri The namespace within which the name resides. # * name The name of the metadata attribute to be removed. # def remove_metadata(uri, name) end # call-seq: # set_metadata(name, value) # set_metadata(uri, name, value) # set(name, value) # set(uri, name, value) # # Set the identified metadata from the document. # # * uri The namespace within which the name resides. # * name The name of the metadata attribute to be set. # * value an XML::Value object # def set_metadata(uri, name, value) end # Return the document as a String object # def to_s end # same than to_s def to_str end # Retrieve content as an XML::EventReader. def event_reader end end ruby-bdb-0.6.6/bdbxml2/docs/document.rd000066400000000000000000000035131154714021300176600ustar00rootroot00000000000000=begin == BDB::XML::Document A Document is the unit of storage within a Container. A document consists of content, a name, and a set of metadata attributes. The document content is a byte stream. It must be well formed XML, but need not be valid. included module : Enumerable === Methods --- self[name] Returns the value of the specified metadata. --- self[name] = val Set the value of the specified metadata. --- content Return the content of the document --- content = val Set the content of the document --- each {|uri, name, value| ... } --- each_metadata {|uri, name, value| ... } Iterate over all metadata --- get_metadata(uri, name) --- get_metadata(name) --- get(uri, name) --- get(name) Get the identified metadata from the document. * ((|uri|)) The namespace within which the name resides. * ((|name|)) The name of the metadata attribute to be retrieved. --- manager Return the manager --- name Return the name of the document --- name = val Set the name of the document --- remove_metadata(uri, name) --- remove_metadata(name) Remove the identified metadata from the document. * ((|uri|)) The namespace within which the name resides. * ((|name|)) The name of the metadata attribute to be removed. --- set_metadata(name, value) --- set_metadata(uri, name, value) --- set(name, value) --- set(uri, name, value) Set the identified metadata from the document. * ((|uri|)) The namespace within which the name resides. * ((|name|)) The name of the metadata attribute to be set. * ((|value|)) an XML::Value object --- to_s Return the document as a String object --- to_str same than ((|to_s|)) --- event_reader Retrieve content as an XML::EventReader. =end ruby-bdb-0.6.6/bdbxml2/docs/event_reader.rb000066400000000000000000000102121154714021300204750ustar00rootroot00000000000000# Class which enables applications to read document content via a pull interface without # materializing XML as text. # # An XML::EventReader can be obtained with the method XML::Document#event_reader # or XML::Value#event_reader class BDB::XML::EventReader # If the current event is StartElement, return the number of attributes available. def attribute_count end # If the current event is StartElement, return the local name for the attribute at the # specified offset def attribute_local_name(index) end # If the current event is StartElement, return the namespace URI for the attribute at the # specified offset. def attribute_namespace_uri(index) end # If the current event is StartElement, return the namespace prefix for the attribute at the # specified offset. def attribute_prefix(index) end # If the current event is StartElement, return whether the attribute at the index indicated # is specified. def attribute_specified?(index) end # If the current event is StartElement, return the value for the attribute at the specified # offset. def attribute_value(index) end # close the object def close end # Return whether the document is standalone def document_standalone? end # Return true if the current event is StartElement and the element has not content. # If the current even is not StartElement, an exception will be raised. def empty_element? end # Returns true if the XML::EventReader object will return whether an element is empty # or not in the context of the StartElement event. def empty_element_info? end # Returns the encoding for the document, if available. def encoding end # Checks if the encoding was explicitly set. def encoding? end # If the current event is Characters, and XML::EventReader#entity_escape_info? is true, # returns whether the current text string requires escaping of entities for XML serialization. def entity_escape? end # Returns true if the XML::EventReader object is able to return information about text strings # indicating that they may have entities requiring escaping for XML serialization. def entity_escape_info? end # Gets whether the XML::EventReader will include events of type StartEntityReference # and EndEntityReference. def entity_info? end # The events of type StartEntityReference and EndEntityReference are used to report the start # and end of XML that was originally an entity reference in the XML text, but has since been # expanded. By default, these events are not reported. def entity_info=(boolean) end # Return the event type of the current event def event_type end # Gets whether the XML::EventReader will include events associated with expanded entities. def expand_entities? end # Sets whether the XML::EventReader should include events associated with expanded entities. def expand_entities=(boolean) end # If the current event is StartElement or EndElement, return the local name for the element def local_name end # If the current event is StartElement or EndElement, return the namespace URI for the element def namespace_uri end # Check if there are additional events available def next? end # Move to the next event def next end # Move to the next StartElement or EndElement def next_tag end # If the current event is StartElement or EndElement, return the namespace prefix for the element def prefix end # Checks if the standalone attribute was explicitly set. def standalone? end # Returns the document's system ID, if available. def system_id end # If the current event is Characters, return the text value. If the current event is # ProcessingInstruction, return the data portion of the processing instruction. def value end # Returns the XML version string, if available. def version end # Return true if the current text value is entirely white space. The current event must be # one of Whitespace, Characters, or CDATA, or an exception will be raised.. def whitespace? end end ruby-bdb-0.6.6/bdbxml2/docs/event_reader.rd000066400000000000000000000075371154714021300205170ustar00rootroot00000000000000=begin == BDB::XML::EventReader Class which enables applications to read document content via a pull interface without materializing XML as text. An XML::EventReader can be obtained with the method XML::Document#event_reader or XML::Value#event_reader === Methods --- attribute_count If the current event is StartElement, return the number of attributes available. --- attribute_local_name(index) If the current event is StartElement, return the local name for the attribute at the specified offset --- attribute_namespace_uri(index) If the current event is StartElement, return the namespace URI for the attribute at the specified offset. --- attribute_prefix(index) If the current event is StartElement, return the namespace prefix for the attribute at the specified offset. --- attribute_specified?(index) If the current event is StartElement, return whether the attribute at the index indicated is specified. --- attribute_value(index) If the current event is StartElement, return the value for the attribute at the specified offset. --- close close the object --- document_standalone? Return whether the document is standalone --- empty_element? Return true if the current event is StartElement and the element has not content. If the current even is not StartElement, an exception will be raised. --- empty_element_info? Returns true if the XML::EventReader object will return whether an element is empty or not in the context of the StartElement event. --- encoding Returns the encoding for the document, if available. --- encoding? Checks if the encoding was explicitly set. --- entity_escape? If the current event is Characters, and XML::EventReader#entity_escape_info? is true, returns whether the current text string requires escaping of entities for XML serialization. --- entity_escape_info? Returns true if the XML::EventReader object is able to return information about text strings indicating that they may have entities requiring escaping for XML serialization. --- entity_info? Gets whether the XML::EventReader will include events of type StartEntityReference and EndEntityReference. --- entity_info=(boolean) The events of type StartEntityReference and EndEntityReference are used to report the start and end of XML that was originally an entity reference in the XML text, but has since been expanded. By default, these events are not reported. --- event_type Return the event type of the current event --- expand_entities? Gets whether the XML::EventReader will include events associated with expanded entities. --- expand_entities=(boolean) Sets whether the XML::EventReader should include events associated with expanded entities. --- local_name If the current event is StartElement or EndElement, return the local name for the element --- namespace_uri If the current event is StartElement or EndElement, return the namespace URI for the element --- next? Check if there are additional events available --- next Move to the next event --- next_tag Move to the next StartElement or EndElement --- prefix If the current event is StartElement or EndElement, return the namespace prefix for the element --- standalone? Checks if the standalone attribute was explicitly set. --- system_id Returns the document's system ID, if available. --- value If the current event is Characters, return the text value. If the current event is ProcessingInstruction, return the data portion of the processing instruction. --- version Returns the XML version string, if available. --- whitespace? Return true if the current text value is entirely white space. The current event must be one of Whitespace, Characters, or CDATA, or an exception will be raised.. =end ruby-bdb-0.6.6/bdbxml2/docs/event_writer.rb000066400000000000000000000023201154714021300205500ustar00rootroot00000000000000# # Class which enables applications to construct document content without using serialized XML. # # An XML::EventWriter can be obtained with the method XML::Document#event_writer # class BDB::XML::EventWriter # Write a single attribute def attribute(local_name, prefix = nil, uri = nil, value, speficied) end # Close the object def close end # Write the DTD def dtd(text) end # Write an EndDocument event def end_document end # Write an EndElement event def end_element(local_name, prefix = nil, uri = nil) end # Write an EndEntity event def end_entity(name) end # Write a ProcessingInstruction event def processing_instruction(target, data) end # Write a StartDocument event def start_document(version = nil, encoding = nil, standalone = nil) end # Write an element event def start_element(local_name, prefix = nil, uri = nil, nattr, empty) end # Write StartEntityReference event def start_entity(name, expanded) end # Write an text event # # type must be one of XML::EventReader::Characters, XML::EventReader::Whitespace, # XML::EventReader::CDATA, or XML::EventReader::Comment def text(type, txt) end end ruby-bdb-0.6.6/bdbxml2/docs/event_writer.rd000066400000000000000000000021451154714021300205570ustar00rootroot00000000000000=begin == BDB::XML::EventWriter Class which enables applications to construct document content without using serialized XML. An XML::EventWriter can be obtained with the method XML::Document#event_writer === Methods --- attribute(local_name, prefix = nil, uri = nil, value, speficied) Write a single attribute --- close Close the object --- dtd(text) Write the DTD --- end_document Write an EndDocument event --- end_element(local_name, prefix = nil, uri = nil) Write an EndElement event --- end_entity(name) Write an EndEntity event --- processing_instruction(target, data) Write a ProcessingInstruction event --- start_document(version = nil, encoding = nil, standalone = nil) Write a StartDocument event --- start_element(local_name, prefix = nil, uri = nil, nattr, empty) Write an element event --- start_entity(name, expanded) Write StartEntityReference event --- text(type, txt) Write an text event type must be one of XML::EventReader::Characters, XML::EventReader::Whitespace, XML::EventReader::CDATA, or XML::EventReader::Comment =end ruby-bdb-0.6.6/bdbxml2/docs/index.rb000066400000000000000000000102421154714021300171440ustar00rootroot00000000000000# The XML::Index class encapsulates the indexing specification of a container. # An indexing specification can be retrieved with the XML::Container#index # method, and modified using the XML::Container#index= method. # # Note that adding an index to a container results in re-indexing all of # the documents in that container, which can take a very long time. It is # good practice to design an application to add useful indices before # populating a container. class BDB::XML::Index # call-seq: # add(uri, name, index) # add(uri, name, type, syntax) # # Add a new index # # * uri # The namespace for the element # # * name # The name parameter provides the fully qualified element type # to be indexed. # # * index # The index string is a comma separated list of strings that represent # the indexing strategy # # * type series of values bitwise OR'd together to form the # index strategy. # # * syntax Identifies the type of information being indexed def add(uri, name, type, syntax) end # Adds an indexing strategy to the default index specification. def add_default(index) end # return the default index specification def default end # call-seq: # delete(uri, name, index) # delete(uri, name, type, syntax) # # Delete the specified index # # * uri # The namespace for the element # # * name # The name parameter provides the fully qualified element type # to be indexed. # # * index # The index string is a comma separated list of strings that represent # the indexing strategy # # * type series of values bitwise OR'd together to form the # index strategy. # # * syntax Identifies the type of information being indexed def delete(uri, name, type, syntax) end # call-seq: # delete_default(index) # delete_default(type, syntax) # # Delete the identified index from the default index specification. # # * index # The index string is a comma separated list of strings that represent # the indexing strategy # # * type series of values bitwise OR'd together to form the # index strategy. # # * syntax Identifies the type of information being indexed def delete_default(type, syntax) end #Iterate over all indexes # def each yield uri, name, index end #Find the indexing startegy associated with uri, and name # #Return nil is no indexing strategy was defined # def find(uri = "", name) end # Return the manager associated with the Index def manager end # call-seq: # replace(uri, name, index) # replace(uri, name, type, syntax) # # Replaces the indexing strategies for a named document or metadata node. # All existing indexing strategies for that node are deleted, and the # indexing strategy identified by this method is set for the node. # # * uri # The namespace for the element # # * name # The name parameter provides the fully qualified element type # to be indexed. # # * index # The index string is a comma separated list of strings that represent # the indexing strategy # # * type series of values bitwise OR'd together to form the # index strategy. # # * syntax Identifies the type of information being indexed def replace(uri, name, type, syntax) end # call-seq: # replace_default(index) # replace_default(type, syntax) # # Replace the default indexing strategy for the container. # # * index # The index string is a comma separated list of strings that represent # the indexing strategy # # * type series of values bitwise OR'd together to form the # index strategy. # # * syntax Identifies the type of information being indexed def replace_default(type, syntax) end #Return an Array of all indexes # def to_a end end ruby-bdb-0.6.6/bdbxml2/docs/index.rd000066400000000000000000000074741154714021300171630ustar00rootroot00000000000000=begin == BDB::XML::Index The XML::Index class encapsulates the indexing specification of a container. An indexing specification can be retrieved with the XML::Container#index method, and modified using the XML::Container#index= method. Note that adding an index to a container results in re-indexing all of the documents in that container, which can take a very long time. It is good practice to design an application to add useful indices before populating a container. Included module : Enumerable === Methods --- add(uri, name, index) --- add(uri, name, type, syntax) call-seq: add(uri, name, index) add(uri, name, type, syntax) Add a new index : ((|uri|)) The namespace for the element : ((|name|)) The name parameter provides the fully qualified element type to be indexed. : ((|index|)) The index string is a comma separated list of strings that represent the indexing strategy : ((|type|)) series of values bitwise OR'd together to form the index strategy. : ((|syntax|)) Identifies the type of information being indexed --- add_default(index) Adds an indexing strategy to the default index specification. --- default return the default index specification --- delete(uri, name, index) --- delete(uri, name, type, syntax) Delete the specified index : ((|uri|)) The namespace for the element : ((|name|)) The name parameter provides the fully qualified element type to be indexed. : ((|index|)) The index string is a comma separated list of strings that represent the indexing strategy : ((|type|)) series of values bitwise OR'd together to form the index strategy. : ((|syntax|)) Identifies the type of information being indexed --- delete_default(index) --- delete_default(type, syntax) Delete the identified index from the default index specification. : ((|index|)) The index string is a comma separated list of strings that represent the indexing strategy : ((|type|)) series of values bitwise OR'd together to form the index strategy. : ((|syntax|)) Identifies the type of information being indexed --- each {|uri, name, index| ... } Iterate over all indexes --- find(uri = "", name) Find the indexing startegy associated with ((|uri|)), and ((|name|)) Return ((|nil|)) is no indexing strategy was defined --- manager Return the manager associated with the Index --- replace(uri, name, index) --- replace(uri, name, type, syntax) Replaces the indexing strategies for a named document or metadata node. All existing indexing strategies for that node are deleted, and the indexing strategy identified by this method is set for the node. : ((|uri|)) The namespace for the element : ((|name|)) The name parameter provides the fully qualified element type to be indexed. : ((|index|)) The index string is a comma separated list of strings that represent the indexing strategy : ((|type|)) series of values bitwise OR'd together to form the index strategy. : ((|syntax|)) Identifies the type of information being indexed --- replace_default(index) --- replace_default(type, syntax) Replace the default indexing strategy for the container. : ((|index|)) The index string is a comma separated list of strings that represent the indexing strategy : ((|type|)) series of values bitwise OR'd together to form the index strategy. : ((|syntax|)) Identifies the type of information being indexed --- to_a Return an Array of all indexes =end ruby-bdb-0.6.6/bdbxml2/docs/indexlookup.rb000066400000000000000000000103211154714021300203740ustar00rootroot00000000000000# The XML::IndexLookup class encapsulates the context within which an # index lookup operation can be performed on an XML::Container object. The # lookup is performed using an XML::IndexLookup object, and a series of # methods of that object that specify how the lookup is to be # performed. Using these methods, it is possible to specify inequality # lookups, range lookups, and simple value lookups, as well as the sort # order of the results. By default, results are returned in the sort # order of the index. # # XML::IndexLookup objects are created using XML::Manager::create_index_lookup, # or Txn::create_index_lookup # # The following constant are defined NONE, EQ, GT, # GTE, LT, LTE class BDB::XML::IndexLookup # Retrieve the current container def container end # Sets the container to be used for the index lookup operation. # The same object may be used for lookup in multiple containers by changing # this configuration. def container=(con) end # Executes the index lookup operation specified by the configuration. # # * context # a XML::QueryContext object to use for this query # # * flags # the flags must be set to 0, OR'ing one of the value # BDB::XML::LAZY_DOCS, BDB::XML::REVERSE_ORDER, # BDB::XML::CACHE_DOCUMENTS, BDB::DEGREE_2, # BDB::DIRTY_READ, BDB::RMW # def execute(context = nil, flags = 0) end # Retrieve the operation and value used for the upper bound # def high_bound end # call-seq: # self.high_bound = [value, operation] # # Sets the operation and value to be used for the upper bound for a range # index lookup operation. The high bound must be specified to indicate a # range lookup. def high_bound=([value, operation]) end # Retrieve the indexing strategy def index end # Set the indexing strategy to be used for the index lookup operation. # Only one index may be specified, and substring indexes are not supported. def index=(string) end # Retrieve the operation and value used for the lower bound # def low_bound end # call-seq: # self.low_bound = [value, operation] # # Sets the operation and value to be used for the index lookup operation. # If the operation is a simple inequality lookup, the lower bound is used as # the single value and operation for the lookup. If the operation is a range # lookup, in which an upper bound is specified, the lower bound is used # as the lower boundary value and operation for the lookup. def low_bound=([value, operation]) end # Return the manager associated with the IndexLookup def manager end # Retrieve the namespace and the name of the node def node end # Retrieve the namespace of the node def node_uri end # Retrieve the name of the node def node_name end # Sets the name of the node to be used along with the indexing strategy # for the index lookup operation. # # * uri # The namespace of the node to be used. The default namespace is selected # by passing an empty string for the namespace # # * name # The name of the element or attribute node to be used. # def node=([uri, name]) end # Retrieve the namespace and the name of the parent node def parent end # Retrieve the namespace of the parent node def parent_uri end # Retrieve the name of the parent node def parent_name end # Sets the name of the parent node to be used for an edge index lookup # operation. If the index is not an edge index, this configuration is ignored. # # * uri # The namespace of the parent node to be used. The default namespace is # selected by passing an empty string for the namespace # # * name # The name of the parent element node to be used. # def parent=([uri, name]) end # Return the transaction associated with the IndexLookup, if it was opened # in a transaction def transaction end # Return true if the IndexLookup was opened in a transaction def transaction? end end ruby-bdb-0.6.6/bdbxml2/docs/indexlookup.rd000066400000000000000000000075751154714021300204170ustar00rootroot00000000000000=begin == BDB::XML::IndexLookup The XML::IndexLookup class encapsulates the context within which an index lookup operation can be performed on an XML::Container object. The lookup is performed using an XML::IndexLookup object, and a series of methods of that object that specify how the lookup is to be performed. Using these methods, it is possible to specify inequality lookups, range lookups, and simple value lookups, as well as the sort order of the results. By default, results are returned in the sort order of the index. XML::IndexLookup objects are created using XML::Manager::create_index_lookup, or Txn::create_index_lookup The following constant are defined ((|NONE|)), ((|EQ|)), ((|GT|)), ((|GTE|)), ((|LT|)), ((|LTE|)) === Methods --- container Retrieve the current container --- container=(con) Sets the container to be used for the index lookup operation. The same object may be used for lookup in multiple containers by changing this configuration. --- execute(context = nil, flags = 0) Executes the index lookup operation specified by the configuration. : ((|context|)) a XML::QueryContext object to use for this query : ((|flags|)) the flags must be set to ((|0|)), OR'ing one of the value ((|BDB::XML::LAZY_DOCS|)), ((|BDB::XML::REVERSE_ORDER|)), ((|BDB::XML::CACHE_DOCUMENTS|)), ((|BDB::DEGREE_2|)), ((|BDB::DIRTY_READ|)), ((|BDB::RMW|)) --- high_bound Retrieve the operation and value used for the upper bound --- high_bound=([value, operation]) call-seq: self.high_bound = [value, operation] Sets the operation and value to be used for the upper bound for a range index lookup operation. The high bound must be specified to indicate a range lookup. --- index Retrieve the indexing strategy --- index=(string) Set the indexing strategy to be used for the index lookup operation. Only one index may be specified, and substring indexes are not supported. --- low_bound Retrieve the operation and value used for the lower bound --- low_bound=([value, operation]) call-seq: self.low_bound = [value, operation] Sets the operation and value to be used for the index lookup operation. If the operation is a simple inequality lookup, the lower bound is used as the single value and operation for the lookup. If the operation is a range lookup, in which an upper bound is specified, the lower bound is used as the lower boundary value and operation for the lookup. --- manager Return the manager associated with the IndexLookup --- node Retrieve the namespace and the name of the node --- node_uri Retrieve the namespace of the node --- node_name Retrieve the name of the node --- node=([uri, name]) Sets the name of the node to be used along with the indexing strategy for the index lookup operation. : ((|uri|)) The namespace of the node to be used. The default namespace is selected by passing an empty string for the namespace : ((|name|)) The name of the element or attribute node to be used. --- parent Retrieve the namespace and the name of the parent node --- parent_uri Retrieve the namespace of the parent node --- parent_name Retrieve the name of the parent node --- parent=([uri, name]) Sets the name of the parent node to be used for an edge index lookup operation. If the index is not an edge index, this configuration is ignored. : ((|uri|)) The namespace of the parent node to be used. The default namespace is selected by passing an empty string for the namespace : ((|name|)) The name of the parent element node to be used. --- transaction Return the transaction associated with the IndexLookup, if it was opened in a transaction --- transaction? Return true if the IndexLookup was opened in a transaction =end ruby-bdb-0.6.6/bdbxml2/docs/manager.rb000066400000000000000000000240131154714021300174500ustar00rootroot00000000000000# # Provides a high-level object used to manage various aspects of Berkeley # DB XML usage. You use XML::Manager to perform activities such as container # management (including creation and open), preparing XML::Query queries, # executing one-off queries, creating transaction objects, # creating update and query context objects # # A XML::Manager object can be created with BDB::Env#manager # # BDB::Transaction respond to the same method than BDB::XML::Manager # class BDB::XML::Manager class << self # create a new Manager object that uses a private internal # database environment # # * flags # flags can have the value # # * BDB::XML::ALLOW_EXTERNAL_ACCESS to allow queries to access # external data sources # * BDB::XML::ALLOW_AUTO_OPEN to allow queries that reference # unopened containers will automatically open those containers def new(flags = 0) end end # Creates and opens a container. If the container already exists at # the time this method is called, an exception is thrown. # # * name container's name # * flags the flags to use for this container creation. # * type the type of container to create. # * mode mode for creation (see chmod(2)) def create_container(name, flags = 0, type = XML::Container::NodeContainer, mode = 0) end # create a XML::Document object def create_document end # create a XML::Modify object def create_modify end # create a XML::Context object # * rt specifies whether to return live (XML::Context::LiveValues) # or dead values (XML::Context::DeadValues) # * et specifies if the resultants values are derived and # stored in-memory before query evaluation is completed # (XML::Context::Eager) or if they are calculated as you ask for them # (XML::Query::Lazy) def create_query_context(rt = XML::Context::LiveValues, et = XML::Context::Eager) end # create a XML::Results object def create_results end # create a new transaction # *flags def begin(flags = 0) end # Examines the named file, and if it is a container, returns a non-zero # database format version. If the file does not exist, or is not a container, # zero is returned. def container_version(file) end # Instantiates an new XML::IndexLookup object for performing index lookup # operations. Only a single index may be specified, and substring indexes # are not supported. # # * container # The target container for the lookup operation # # * uri # The namespace of the node to be used. The default namespace is selected # by passing an empty string for the namespace. # # * name # The name of the element or attribute node to be used. # # * index # A comma-separated list of strings that represent the indexing strategy. # # * value # The value to be used as the single value for an equality or inequality # lookup, or as the lower bound of a range lookup. # # * op # Selects the operation to be performed. Must be one of: # XML::IndexLookup::NONE, XML::IndexLookup::EQ, XML::IndexLookup::GT, # XML::IndexLookup::GTE, XML::IndexLookup::LT, XML::IndexLookup::LTE . # def create_index_lookup(container, uri, name, index, value = nil, op = XML::IndexLookup::EQ) end # create a XML::Update object def create_update_context end # call-seq: # dump_container(name, path) # dump_container(name, io, to_close = false) # # Dumps the contents of the specified container. # # * name name of the container # * path or the pathname of the file where the contents # will be dumped # * io object which respond to #write # * to_close if an IO object was given, specify if this object # must be closed at the end. def dump_container(name, io, to_close = false) end # Returns the underlying environnement def env end # Returns the home directory for the underlying database environment def home end # call-seq: # load_container(name, path, update = nil) # load_container(nmae, io, to_close = false, update = nil) # # Loads data from the specified path (or io) into the container. # # * name name of the container to load. # * path the pathname of the file which contains the data. # * io an object which respond to #read # * to_close if true, the object will be closed at end # * update an optional update context def load_container(name, path, update = nil) end # Opens a container and return an XML::Container object # * name the container's name # * flags the flags to use for this container open. Specify # BDB::CREATE to create and open a new container. def open_container(name, flags = 0) end # Compile a Query expression and return a new XML::Query object. # # You can then use XML::Query#execute # # * query the query to compile # * context an optional query context def prepare(query, context = nil) end # Execute a query. If a block is given it will call XML::::Results#each for # the results, or it will return an XML::::Results object # # This is equivalent to call XML::Manager#prepare and then # XML::Query#execute # # * query the query to compile # * context an optional query context def query(query, context = nil) yield value end # Reindex an entire container. The container should be backed up prior to using # this method, as it destroys existing indexes before reindexing. If the operation # fails, and your container is not backed up, you may lose information. # # Use this call to change the type of indexing used for a container between # document-level indexes and node-level indexes. This method can take a very # long time to execute, depending on the size of the container, and should # not be used casually. # # * name The path to the container to be reindexed. # * context The update context to use for the reindex operation. # * flags Use XML::INDEX_NODES in order to index the container at # the node level; otherwise, it will be indexed at the document level. def reindex_container(name, context = nil, flags = 0) end # Register a resolver # # A resolver is an object which can respond to #resolve_collection, # #resolve_document, #resolve_entity, #resolve_schema, #resolve_module # or #resolve_module_location # # These methods (if implemented) must return nil if they can't resolve # # # def resolve_collection(txn_or_manager, uri) # Xml::Results.new # end # # def resolve_document(txn_or_manager, uri) # Xml::Value.new # end # # def resolve_entity(txn_or_manager, system_id, public_id) # 'an object which respond to #read' # end # # def resolve_schema(txn_or_manager, schema_location, namespace) # 'an object which respond to #read' # end # # def resolve_module(txn_or_manager, module_location, namespace) # 'an object which respond to #read' # end # # def resolve_module_location(txn_or_manager, namespace) # Xml::Results.new # end # def resolver=(object) end # Remove a container # # * name the name of the container to be removed. The container # must be closed def remove_container(name) end # Rename a container # # * old_name the name of the container to be renamed. # The container must be closed and must have been opened at least once # * new_name its new name def rename_container(old_name, new_name) end # Return the default container flags def container_flags end # Set the default container flags for new XML::Container def container_flags=(flags) end # Return the default container type def container_type end # Set the default container type for new XML::Container def container_type=(type) end # Return the current page size value def pagesize end # Set the current page size value def pagesize=(size) end # Upgrades the container from a previous version of Berkeley DB XML # # * name name of the container to be upgraded # * context an optional update context def update_container(name, context = nil) end # call-seq: # verify_container(name, flags = 0) # verify_container(name, path, flags = BDB::SALVAGE) # verify_container(name, io, to_close = false, flags = BDB::SALVAGE) # # Checks that the container data files are not corrupt, and optionally # writes the salvaged container data to the specified pathname. # # * name name of the container # * path name of the file where the container will be # dumped if BDB::SALVAGE is set. # * io an object which respond to #write if BDB::SALVAGE is set # * if true, the io will be closed at end # * flags can have the value BDB::SALVAGE, BDB::AGGRESSIVE def verify_container(name, path, flags = 0) end # Sets the integer increment to be used when pre-allocating document ids # for new documents created by XML::Container::put def sequence_increment=(increment) end # Retrieve the integer increment. def sequence_increment end # Get the flags used to open the manager. def flags end # Get the implicit timezone used for queries def implicit_timezone end # Set the implicit timezone used for queries def implicit_timezone=(tz) end # Compact the databases comprising the container. def compact_container(name, context = Xml::Context.new) end # Truncate the container. def truncate_container(name, context = XML::Context.new) end end ruby-bdb-0.6.6/bdbxml2/docs/manager.rd000066400000000000000000000223131154714021300174530ustar00rootroot00000000000000=begin == BDB::XML::Manager Provides a high-level object used to manage various aspects of Berkeley DB XML usage. You use XML::Manager to perform activities such as container management (including creation and open), preparing XML::Query queries, executing one-off queries, creating transaction objects, creating update and query context objects A XML::Manager object can be created with BDB::Env#manager BDB::Transaction respond to the same method than BDB::XML::Manager === Class Methods --- new(flags = 0) create a new Manager object that uses a private internal database environment : ((|flags|)) flags can have the value : BDB::XML::ALLOW_EXTERNAL_ACCESS to allow queries to access external data sources : BDB::XML::ALLOW_AUTO_OPEN to allow queries that reference unopened containers will automatically open those containers === Methods --- create_container(name, flags = 0, type = XML::Container::NodeContainer, mode = 0) Creates and opens a container. If the container already exists at the time this method is called, an exception is thrown. : ((|name|)) container's name : ((|flags|)) the flags to use for this container creation. : ((|type|)) the type of container to create. : ((|mode|)) mode for creation (see chmod(2)) --- create_document create a XML::Document object --- create_modify create a XML::Modify object --- create_query_context(rt = XML::Context::LiveValues, et = XML::Context::Eager) create a XML::Context object : ((|rt|)) specifies whether to return live (XML::Context::LiveValues) or dead values (XML::Context::DeadValues) : ((|et|)) specifies if the resultants values are derived and stored in-memory before query evaluation is completed (XML::Context::Eager) or if they are calculated as you ask for them (XML::Query::Lazy) --- create_results create a XML::Results object --- begin(flags = 0) create a new transaction *((|flags|)) --- create_update_context create a XML::Update object --- dump_container(name, path) --- dump_container(name, io, to_close = false) Dumps the contents of the specified container. : ((|name|)) name of the container : ((|path|)) the pathname of the file where the contents will be dumped : ((|io|)) object which respond to #write : ((|to_close|)) if an IO object was given, specify if this object must be closed at the end. --- env Returns the underlying environnement --- home Returns the home directory for the underlying database environment --- load_container(name, path, update = nil) --- load_container(name, io, to_close = false, update = nil) Loads data from the specified path (or io) into the container. : ((|name|)) name of the container to load. : ((|path|)) the pathname of the file which contains the data. : ((|io|)) an object which respond to #read : ((|update|)) an optional update context --- open_container(name, flags = 0) Opens a container and return an XML::Container object : ((|name|)) the container's name : ((|flags|)) the flags to use for this container open. Specify BDB::CREATE to create and open a new container. --- prepare(query, context = nil) Compile a Query expression and return a new XML::Query object. You can then use XML::Query#execute : ((|query|)) the query to compile : ((|context|)) an optional query context --- query(query, context = nil) [{res| ... } Execute a query. If a block is given it will call Xml::Results#each for the results, or it will return an Xml::Results object This is equivalent to call XML::Manager#prepare and then XML::Query#execute : ((|query|)) the query to compile : ((|context|)) an optional query context --- resolver = object Register a resolver A resolver is an object which can respond to #resolve_collection, #resolve_document, #resolve_entity, #resolve_schema, #resolve_module or #resolve_module_location These methods (if implemented) must return ((|nil|)) if they can't resolve def resolve_collection(txn_or_manager, uri) Xml::Results.new end def resolve_document(txn_or_manager, uri) Xml::Value.new end def resolve_entity(txn_or_manager, system_id, public_id) 'an object which respond to #read' end def resolve_schema(txn_or_manager, schema_location, namespace) 'an object which respond to #read' end def resolve_module(txn_or_manager, module_location, namespace) 'an object which respond to #read' end def resolve_module_location(txn_or_manager, namespace) Xml::Results.new end --- remove_container(name) Remove a container : ((|name|)) the name of the container to be removed. The container must be closed --- rename_container(old_name, new_name) Rename a container : ((|old_name|)) the name of the container to be renamed. The container must be closed and must have been opened at least once : ((|new_name|)) its new name --- container_flags Return the default container flags --- container_flags = flags Set the default container flags for new XML::Container --- container_type Return the default container type --- container_type = type Set the default container type for new XML::Container --- container_version(file) Examines the named ((|file|)), and if it is a container, returns a non-zero database format version. If the ((|file|)) does not exist, or is not a container, zero is returned. --- create_index_lookup(container, uri, name, index, value = nil, op = XML::IndexLookup::EQ) Instantiates an new XML::IndexLookup object for performing index lookup operations. Only a single index may be specified, and substring indexes are not supported. : ((|container|)) The target container for the lookup operation : ((|uri|)) The namespace of the node to be used. The default namespace is selected by passing an empty string for the namespace. : ((|name|)) The name of the element or attribute node to be used. : ((|index|)) A comma-separated list of strings that represent the indexing strategy. : ((|value|)) The value to be used as the single value for an equality or inequality lookup, or as the lower bound of a range lookup. : ((|op|)) Selects the operation to be performed. Must be one of: XML::IndexLookup::NONE, XML::IndexLookup::EQ, XML::IndexLookup::GT, XML::IndexLookup::GTE, XML::IndexLookup::LT, XML::IndexLookup::LTE . --- pagesize Return the current page size value --- pagesize = size Set the current page size value --- reindex_container(name, context = nil, flags = 0) Reindex an entire container. The container should be backed up prior to using this method, as it destroys existing indexes before reindexing. If the operation fails, and your container is not backed up, you may lose information. Use this call to change the type of indexing used for a container between document-level indexes and node-level indexes. This method can take a very long time to execute, depending on the size of the container, and should not be used casually. : ((|name|)) The path to the container to be reindexed. : ((|context|)) The update context to use for the reindex operation. : ((|flags|)) Use XML::INDEX_NODES in order to index the container at the node level; otherwise, it will be indexed at the document level. --- sequence_increment = increment Sets the integer ((|increment|)) to be used when pre-allocating document ids for new documents created by XML::Container::put --- sequence_increment Retrieve the integer increment. --- update_container(name, context = nil) Upgrades the container from a previous version of Berkeley DB XML : ((|name|)) name of the container to be upgraded : ((|context|)) an optional update context --- verify_container(name, flags = 0) --- verify_container(name, path, flags = BDB::SALVAGE) --- verify_container(name, io, to_close = false, flags = BDB::SALVAGE) Checks that the container data files are not corrupt, and optionally writes the salvaged container data to the specified pathname. : ((|name|)) name of the container : ((|path|)) name of the file where the container will be dumped if BDB::SALVAGE is set. : ((|io|)) an object which respond to #write if BDB::SALVAGE is set : ((|to_close|)) if true the io will be closed at end. : ((|flags|)) can have the value BDB::SALVAGE, BDB::AGGRESSIVE --- flags Get the flags used to open the manager. --- implicit_timezone Get the implicit timezone used for queries --- implicit_timezone=(tz) Set the implicit timezone used for queries --- compact_container(name, context = Xml::Context.new) Compact the databases comprising the container. --- truncate_container(name, context = XML::Context.new) Truncate the container. =end ruby-bdb-0.6.6/bdbxml2/docs/modify.rb000066400000000000000000000105421154714021300173270ustar00rootroot00000000000000# The XML::Modify class encapsulates the context within which a set of one # or more documents specified by an XML::Query query can be modified in # place. The modification is performed using an XML::Modify object, and a # series of methods off that object that identify how the document is to # be modified. Using these methods, the modification steps are # identified. When the object is executed, these steps are performed in # the order that they were specified. # # The modification steps are executed against one or more documents # using XML::Modify::execute. This method can operate on a single document # stored in an XML::Value, or against multiple documents stored in an # XML::Results set that was created as the result of a container or # document query. class BDB::XML::Modify # Appends the provided data to the selected node's child nodes. # # * query provides the Query expression used to target the # location in the document where the modification is to be performed. # # * typeIdentifies the type of information to be inserted. # It can have the value XML::Modify::Element, XML::Modify::Attribute, # XML::Modify::Text, XML::Modify::Comment, orXML::Modify::PI # # * namethe name of the node, attribute, or processing instruction # to insert # # * contentThe content to insert. # # * location Identifies the position in the child node list # where the provided content is to be inserted def append(query, type, name, content, location = -1) end # Inserts the provided data into the document after the selected node. # # * query provides the Query expression used to target the # location in the document where the modification is to be performed. # # * typeIdentifies the type of information to be inserted. # It can have the value XML::Modify::Element, XML::Modify::Attribute, # XML::Modify::Text, XML::Modify::Comment, orXML::Modify::PI # # * namethe name of the node, attribute, or processing instruction # to insert # # * contentThe content to insert. # def insert_after(query, type, name, content) end # Inserts the provided data into the document before the selected node. # # * query provides the Query expression used to target the # location in the document where the modification is to be performed. # # * typeIdentifies the type of information to be inserted. # It can have the value XML::Modify::Element, XML::Modify::Attribute, # XML::Modify::Text, XML::Modify::Comment, orXML::Modify::PI # # * namethe name of the node, attribute, or processing instruction # to insert # # * contentThe content to insert. # def insert_before(query, type, name, content) end # Removes the node targeted by the selection expression. # # * query provides the Query expression used to target the # location in the document where the modification is to be performed. def remove(query) end # Renames an element node, attribute node, or processing instruction. # # * query provides the Query expression used to target the # location in the document where the modification is to be performed. # # * name The new name to give the targeted node. def rename(query, name) end # Replaces the targeted node's content with text. # # * query provides the Query expression used to target the # location in the document where the modification is to be performed. # # * content The content to use as the targeted node's content. def update(query, content) end # Executes one or more document modification operations (or steps) against # an XML::Results or XML::Value object. Upon completing the modification, # the modified document is automatically updated in the backing # XML::Container for you. # # * objThe object to modify using this collection of # modification steps. # # * contextThe XML::Context object to use for this modification. # # * updateThe XML::Update object to use for this modification. def execute(obj, context, update = nil) end # Specify a new character encoding for the modified documents. # def encoding=(string) end end ruby-bdb-0.6.6/bdbxml2/docs/modify.rd000066400000000000000000000104551154714021300173340ustar00rootroot00000000000000=begin == BDB::XML::Modify The XML::Modify class encapsulates the context within which a set of one or more documents specified by an XML::Query query can be modified in place. The modification is performed using an XML::Modify object, and a series of methods off that object that identify how the document is to be modified. Using these methods, the modification steps are identified. When the object is executed, these steps are performed in the order that they were specified. The modification steps are executed against one or more documents using XML::Modify::execute. This method can operate on a single document stored in an XML::Value, or against multiple documents stored in an XML::Results set that was created as the result of a container or document query. === Methods --- append(query, type, name, content, location = -1) Appends the provided data to the selected node's child nodes. : ((|query|)) provides the Query expression used to target the location in the document where the modification is to be performed. : ((|type|)) Identifies the type of information to be inserted. It can have the value XML::Modify::Element, XML::Modify::Attribute, XML::Modify::Text, XML::Modify::Comment, orXML::Modify::PI : ((|name|)) the name of the node, attribute, or processing instruction to insert : ((|content|)) The content to insert. : ((|location|)) Identifies the position in the child node list where the provided content is to be inserted --- insert_after(query, type, name, content) Inserts the provided data into the document after the selected node. : ((|query|)) provides the Query expression used to target the location in the document where the modification is to be performed. : ((|type|)) Identifies the type of information to be inserted. It can have the value XML::Modify::Element, XML::Modify::Attribute, XML::Modify::Text, XML::Modify::Comment, orXML::Modify::PI : ((|name|)) the name of the node, attribute, or processing instruction to insert : ((|content|)) The content to insert. --- insert_before(query, type, name, content) Inserts the provided data into the document before the selected node. : ((|query|)) provides the Query expression used to target the location in the document where the modification is to be performed. : ((|type|)) Identifies the type of information to be inserted. It can have the value XML::Modify::Element, XML::Modify::Attribute, XML::Modify::Text, XML::Modify::Comment, orXML::Modify::PI : ((|name|)) the name of the node, attribute, or processing instruction to insert : ((|content|))The content to insert. --- remove(query) Removes the node targeted by the selection expression. : ((|query|)) provides the Query expression used to target the location in the document where the modification is to be performed. --- rename(query, name) Renames an element node, attribute node, or processing instruction. : ((|query|)) provides the Query expression used to target the location in the document where the modification is to be performed. : ((|name|)) The new name to give the targeted node. --- update(query, content) Replaces the targeted node's content with text. : ((|query|)) provides the Query expression used to target the location in the document where the modification is to be performed. : ((|content|)) The content to use as the targeted node's content. --- execute(obj, context, update = nil) Executes one or more document modification operations (or steps) against an XML::Results or XML::Value object. Upon completing the modification, the modified document is automatically updated in the backing XML::Container for you. : ((|obj|)) The object to modify using this collection of modification steps. : ((|context|)) The XML::Context object to use for this modification. : ((|update|)) The XML::Update object to use for this modification. --- encoding = string Specify a new character encoding for the modified documents. =end ruby-bdb-0.6.6/bdbxml2/docs/results.rb000066400000000000000000000005741154714021300175450ustar00rootroot00000000000000# # The results of a query are a collection of values. The values could # be either String, Float, true, false, BDB::XML::Documents or BDB::XML::Nodes # class BDB::XML::Results include Enumerable # Add a new value def add(val) end # Iterate on each values # def each yield val end # Return the number of elements def size end end ruby-bdb-0.6.6/bdbxml2/docs/results.rd000066400000000000000000000005021154714021300175360ustar00rootroot00000000000000=begin == BDB::XML::Results The results of a query are a collection of values. The values could be either String, Float, true, false, BDB::XML::Documents or BDB::XML::Nodes === Methods --- add(val) Add a new value --- each {|val| ... } Iterate on each values --- size Returns the number of elements =end ruby-bdb-0.6.6/bdbxml2/docs/value.rb000066400000000000000000000043551154714021300171610ustar00rootroot00000000000000# # The XML::Value class encapsulates the value of a node in an XML document. # class BDB::XML::Value # return an XML::Results that contains all of the attributes appearing # on this node. # # node type must be XML::Value::Node def attributes end # return true if type is XML::Value::BOOLEAN def boolean? end # returns current node's first child node, or nil # # node type must be XML::Value::Node def first_child end # returns current node's last child node, or nil # # node type must be XML::Value::Node def last_child end # returns the node's local name. # # node type must be XML::Value::Node def local_name end # returns the URI used for the node's namespace. # # node type must be XML::Value::Node def namespace end # returns the sibling node immediately following this node in the # document, or nil. # # node type must be XML::Value::Node def next_sibling end # return true if type is XML::Value::NONE def nil? end # return true if type is XML::Value::NODE def node? end # return the type of the value contained in this value # # node type must be XML::Value::Node def node_name end # return the node's value # # node type must be XML::Value::Node def node_value end # return true if type is one of the numeric types def number? end # If the current node is an attribute node, returns the document # element node that contains this attribute node. Otherwise, raise # an exception # # node type must be XML::Value::Node def owner_element end # returns current node's parent, or nil # # node type must be XML::Value::Node def parent_node end # returns the prefix set for the node's namespace. # # node type must be XML::Value::Node def prefix end # returns the sibling node immediately preceding this node # in the document, or nil # # node type must be XML::Value::Node def previous_sibling end # return true if type is XML::Value::STRING def string? end # return true if the value has the specified type def type?(type) end # return the type associated with a value def type end end ruby-bdb-0.6.6/bdbxml2/docs/value.rd000066400000000000000000000040361154714021300171570ustar00rootroot00000000000000=begin == BDB::XML::Value The XML::Value class encapsulates the value of a node in an XML document. === Methods --- attributes return an XML::Results that contains all of the attributes appearing on this node. node type must be XML::Value::Node --- boolean? return true if type is XML::Value::BOOLEAN --- first_child returns current node's first child node, or nil node type must be XML::Value::Node --- last_child returns current node's last child node, or nil node type must be XML::Value::Node --- local_name returns the node's local name. node type must be XML::Value::Node --- namespace returns the URI used for the node's namespace. node type must be XML::Value::Node --- next_sibling returns the sibling node immediately following this node in the document, or nil. node type must be XML::Value::Node --- nil? return true if type is XML::Value::NONE --- node? return true if type is XML::Value::NODE --- node_name return the type of the value contained in this value node type must be XML::Value::Node --- node_value return the node's value node type must be XML::Value::Node --- number? return true if type is one of the numeric types --- owner_element If the current node is an attribute node, returns the document element node that contains this attribute node. Otherwise, raise an exception node type must be XML::Value::Node --- parent_node returns current node's parent, or nil node type must be XML::Value::Node --- prefix returns the prefix set for the node's namespace. node type must be XML::Value::Node --- previous_sibling returns the sibling node immediately preceding this node in the document, or nil node type must be XML::Value::Node --- string? return true if type is XML::Value::STRING --- type?(type) return true if the value has the specified type --- type return the type associated with a value =end ruby-bdb-0.6.6/bdbxml2/examples/000077500000000000000000000000001154714021300163775ustar00rootroot00000000000000ruby-bdb-0.6.6/bdbxml2/examples/create.rb000077500000000000000000000012041154714021300201670ustar00rootroot00000000000000#!/usr/local/bin/ruby $LOAD_PATH.unshift("..", "../../src") require 'bdbxml' include BDB::XML File.unlink("exa.dbxml") rescue nil man = Manager.new con = man.create_container("exa.dbxml") at_exit { con.close man.close } con.put("book12", "Knowledge Discovery in Databases I") con.put("book21", "Knowledge Discovery in Databases II") doc = con.get("book12") puts "#{doc.name} = #{doc}" res = Results.new(man) res.add(doc) man.query("collection('exa.dbxml')/book") do |val| puts "#{val.to_document.name} = #{val}" end man.query("collection('exa.dbxml')/book") ruby-bdb-0.6.6/bdbxml2/examples/dbxml/000077500000000000000000000000001154714021300175055ustar00rootroot00000000000000ruby-bdb-0.6.6/bdbxml2/examples/dbxml/README000066400000000000000000000051141154714021300203660ustar00rootroot00000000000000 This directory contains example "DBXML Getting Started Examples" translated in ruby You must first load the database, to do this 1) change the variable data in load.rb data = "#{ENV['HOME']}/ruby/db/dbxml-2.4.13/dbxml/examples/xmlData" to specify where are located the 2 directories simpleData and nsData 2) execute load.rb You can then use the examples. * query.rb Executes several XPath queries and prints query results to the console. * context.rb Identical to query.rb, except that contexts are used to define namespaces and variables. * document.rb Identical to context.rb, except that specific document data is retrieved from each document found in the query's result set. * names.rb Identical to context.rb, except that the query is performed using the document name that was set when load.rb placed the document into the container. * metadata.rb Identical to context.rb, except that the timestamp that was stored as metadata is retrieved and displayed. This timestamp was set on the document when load.rb placed the document into the container. * update.rb Identical to context.rb, except that the document retrieved as the result of the query is updated in a trivial way and then stored back into the container. * delete.rb Identical to context.rb, except that every document retrieved as the result of the query is deleted from the container. * add_index.rb Adds indexes to a specific document node. * replace_index.rb Replaces the indexes on a specific document node with new indexes. Iterates through the indexes maintained for the container and shows what is being used. For best results, run add_index.rb before running this example. * delete_index.rb Deletes indexes from a specific document. Iterates through the indexes maintained for the container and shows what is being used. For best results, run add_index.rb before running this example. * build_db.rb Illustrates how a DBXML container can be used with a Berkeley DB database. A Berkeley DB database is created in the same environment as the container and data corresponding to documents in the container is loaded into the database. The DBXML query and database put are all wrapped in a common transaction. * retrieve_db.rb Illustrates how a DBXML container can be used with a Berkeley DB database. Documents are retrieved from the container and then data corresponding to each document is retrieved from the Berkeley DB database. Again, all queries are wrapped in a common transaction. For best results, run build_db.rb before running this example. ruby-bdb-0.6.6/bdbxml2/examples/dbxml/a.sh000066400000000000000000000015621154714021300202650ustar00rootroot00000000000000#!/bin/sh echo "=================================== query.rb" ruby query.rb echo "=================================== context.rb" ruby context.rb echo "=================================== document.rb" ruby document.rb echo "=================================== names.rb" ruby names.rb echo "=================================== metadata.rb" ruby metadata.rb echo "=================================== update.rb" ruby update.rb echo "=================================== delete.rb" # ruby delete.rb echo "=================================== add_index.rb" ruby add_index.rb echo "=================================== replace_index.rb" ruby replace_index.rb echo "=================================== delete_index.rb" ruby delete_index.rb echo "=================================== build_db.rb " ruby build_db.rb echo "=================================== retrieve_db.rb" ruby retrieve_db.rb ruby-bdb-0.6.6/bdbxml2/examples/dbxml/add_index.rb000077500000000000000000000016541154714021300217620ustar00rootroot00000000000000#!/usr/bin/ruby -I../.. -I../../../src require 'bdbxml' def add(container, uri, name, itype) puts "Adding index type : #{itype} to #{name}" index = container.index puts "Before index add" count = 0 index.each do |u, n, i| puts "\tFor node #{n}, found index #{i}." count += 1 end puts "#{count} indexes found" index.add(uri, name, itype) container.index = index puts "After index add" count = 0 index.each do |u, n, i| puts "\tFor node #{n}, found index #{i}." count += 1 end puts "#{count} indexes found" rescue puts "Add index failed #{$!}" end options = {'home' => 'env', 'container' => 'name.xml'} man = BDB::Env.new(options['home'], BDB::INIT_TRANSACTION).manager man.begin do |txn| con = txn.open_container(options['container']) add(con, "", "product", "node-element-equality-string") add(con, "", "product", "edge-element-presence") txn.commit end ruby-bdb-0.6.6/bdbxml2/examples/dbxml/build_db.rb000077500000000000000000000014571154714021300216100ustar00rootroot00000000000000#!/usr/bin/ruby -I../.. -I../../../src require 'bdbxml' def value(manager, document, xpath, context) query = manager.prepare(xpath, context) result = query.execute(document, context).to_a if result.size != 1 raise "Expected 1 got #{result.size}" end result[0].to_s end options = {'home' => 'env', 'container' => 'name.xml'} env = BDB::Env.new(options['home'], BDB::INIT_TRANSACTION) man = env.manager context = man.create_query_context man.begin do |txn| con = txn.open_container(options['container']) bdb = txn.open_db(BDB::Btree, 'bdb', nil, 'a') txn.query("collection('#{options['container']}')/vendor") do |doc| res = value(txn, doc, "/vendor/salesrep/name/text()", context) bdb[res] = "This is the data stored in the database for #{res}" end txn.commit end ruby-bdb-0.6.6/bdbxml2/examples/dbxml/context.rb000077500000000000000000000022621154714021300215230ustar00rootroot00000000000000#!/usr/bin/ruby -I../.. -I../../../src require 'bdbxml' def query_context(manager, name, query, context) query = "collection('#{name}')#{query}" puts "Exercising query '#{query}'" print "Return to continue : " STDIN.gets results = manager.query(query, context) results.each {|r| puts r} puts "#{results.size} objects returned for expression '#{query}'" puts rescue puts "Query #{query} failed : #{$!}" end options = {'home' => 'env', 'container' => 'name.xml'} man = BDB::Env.new(options['home'], BDB::INIT_LOMP).manager con = man.open_container(options['container']) cxt = man.create_query_context cxt.set_namespace("fruits", "http://groceryItem.dbxml/fruits") cxt.set_namespace("vegetables", "http://groceryItem.dbxml/vegetables") cxt.set_namespace("desserts", "http://groceryItem.dbxml/desserts"); cxt["aDessert"] = "Blueberry Boy Bait" query_context(man, con.name, "/vendor", cxt) query_context(man, con.name, "/item/product[text()='Lemon Grass']", cxt) query_context(man, con.name, "/fruits:item/product[text()='Lemon Grass']", cxt) query_context(man, con.name, "/vegetables:item", cxt) query_context(man, con.name, "/desserts:item/product[text()=$aDessert]", cxt) ruby-bdb-0.6.6/bdbxml2/examples/dbxml/delete.rb000077500000000000000000000032271154714021300213030ustar00rootroot00000000000000#!/usr/bin/ruby -I../.. -I../../../src require 'bdbxml' def value(man, doc, query, context) doc_expr = man.prepare(query, context) result = doc_expr.execute(doc, context).to_a if result.size != 1 raise "Expected 1 got #{result.size}" end result[0] end def delete(man, con, query, context) puts "Deleting document for '#{query}'" print "Return to continue : " STDIN.gets results = man.query(query, context) puts "\nFound #{results.size} documents matching the expression '#{query}'" results.each do |r| r = r.to_document puts "Deleting document #{value(man, r, '/*/product/text()', context)}" con.delete(r) puts "Deleted document #{value(man, r, '/*/product/text()', context)}" end puts rescue puts "Query #{query} failed : #{$!}" end def confirm(man, con, query, context) puts "Conforming the delete document" puts "The query : '#{query}' should get result set size 0" if man.query(query, context).size == 0 puts "Deletion confirmed." else puts "Document deletion failed." end end options = {'home' => 'env', 'container' => 'name.xml'} env = BDB::Env.new(options['home'], BDB::INIT_TRANSACTION) man = env.manager man.begin do |txn| con = txn.open_container(options['container']) cxt = man.create_query_context cxt.set_namespace("fruits", "http://groceryItem.dbxml/fruits") cxt.set_namespace("vegetables", "http://groceryItem.dbxml/vegetables") cxt.set_namespace("desserts", "http://groceryItem.dbxml/desserts"); query = "collection('#{con.name}')/fruits:item[product = 'Mabolo']" delete(txn, con, query, cxt) confirm(txn, con, query, cxt) txn.commit end ruby-bdb-0.6.6/bdbxml2/examples/dbxml/delete_index.rb000077500000000000000000000017101154714021300224650ustar00rootroot00000000000000#!/usr/bin/ruby -I../.. -I../../../src require 'bdbxml' def delete(container, uri, name, itype) puts "Deleting index type : #{itype} to #{name}" index = container.index puts "Before index delete" count = 0 index.each do |u, n, i| puts "\tFor node #{n}, found index #{i}." count += 1 end puts "#{count} indexes found" index.delete(uri, name, itype) container.index = index puts "After index delete" count = 0 index.each do |u, n, i| puts "\tFor node #{n}, found index #{i}." count += 1 end puts "#{count} indexes found" rescue puts "delete index failed #{$!}" end options = {'home' => 'env', 'container' => 'name.xml'} man = BDB::Env.new(options['home'], BDB::INIT_TRANSACTION).manager man.begin do |txn| con = txn.open_container(options['container']) delete(con, "", "product", "node-element-equality-string") delete(con, "", "product", "edge-element-presence-none") txn.commit end ruby-bdb-0.6.6/bdbxml2/examples/dbxml/document.rb000077500000000000000000000026751154714021300216650ustar00rootroot00000000000000#!/usr/bin/ruby -I../.. -I../../../src require 'bdbxml' def value(manager, document, xpath, context) doc = manager.prepare(xpath, context) result = doc.execute(document, context).to_a if result.size != 1 raise "Expected 1 got #{result.size}" end result[0] end def details(manager, name, query, context) query = "collection('#{name}')#{query}" puts "Exercising query '#{query}'" print "Return to continue : " STDIN.gets results = manager.query(query, context) puts "\n\tProduct : Price : Inventory Level" results.each do |r| r = r.to_document item = value(manager, r, "/*/product/text()", context) price = value(manager, r, "/*/inventory/price/text()", context) inventory = value(manager, r, "/*/inventory/inventory/text()", context) puts "\t#{item} : #{price} : #{inventory}" end puts rescue puts "Query #{query} failed : #{$!}" end options = {'home' => 'env', 'container' => 'name.xml'} man = BDB::Env.new(options['home'], BDB::INIT_LOMP).manager con = man.open_container(options['container']) cxt = man.create_query_context cxt.set_namespace("fruits", "http://groceryItem.dbxml/fruits") cxt.set_namespace("vegetables", "http://groceryItem.dbxml/vegetables") cxt.set_namespace("desserts", "http://groceryItem.dbxml/desserts"); details(man, con.name, "/fruits:item/product[text() = 'Zulu Nut']", cxt) details(man, con.name, "/vegetables:item/product[starts-with(text(),'A')]", cxt) ruby-bdb-0.6.6/bdbxml2/examples/dbxml/load.rb000077500000000000000000000010041154714021300207470ustar00rootroot00000000000000#!/usr/local/bin/ruby data = "#{ENV['HOME']}/ruby/db/dbxml-2.4.13/dbxml/examples/xmlData" unless FileTest.directory?(data) && FileTest.directory?(data + "/simpleData") puts "Error can't find DbXml examples" puts "path : #{data}" exit end Dir.foreach('env') do |x| if FileTest.file?("env/#{x}") File.unlink("env/#{x}") end end puts "Loading from #{data}" [["simpleData", "simple"], ["nsData", "name"]].each do |dir, name| system("ruby ./loadex.rb -h env -c #{name}.xml -d #{data}/#{dir}") end ruby-bdb-0.6.6/bdbxml2/examples/dbxml/loadex.rb000077500000000000000000000033221154714021300213110ustar00rootroot00000000000000#!/usr/bin/ruby -I../.. -I../../../src require 'bdbxml' require 'getoptlong' opt = GetoptLong.new( ['--container', '-c', GetoptLong::REQUIRED_ARGUMENT], ['--path', '-p', GetoptLong::REQUIRED_ARGUMENT], ['--files', '-f', GetoptLong::REQUIRED_ARGUMENT], ['--home', '-h', GetoptLong::REQUIRED_ARGUMENT], ['--dir', '-d', GetoptLong::REQUIRED_ARGUMENT] ) options = {'path' => ''} opt.each {|name, value| options[name.sub(/^--/, '')] = value} $files = ARGV.dup $files ||= [] options['path'] << '/' if options['path'].size > 0 if options['dir'] Dir["#{options['dir']}/*.xml"].each {|f| $files << f } end if options['files'] IO.foreach(options['files']) {|line| $files << options['path'] + line.chomp} end if !$files || !options['container'] || !options['home'] puts <<-EOT This program loads XML data into an identified container and environment. Provide the directory where you want to place your database environment, the name of the container to use, and the xml files you want inserted into the container. -h -c -f -p file1.xml ... EOT exit(-1) end env = BDB::Env.new(options['home'],BDB::CREATE|BDB::INIT_TRANSACTION) man = env.manager upd = man.create_update_context man.begin do |txn| con = txn.open_container(options['container'], BDB::CREATE) $files.each do |f| doc = man.create_document doc.content = IO.readlines(f, nil)[0] /[^\/]*$/ =~ f doc.name = $& doc.set("http://dbxmlExamples/timestamp", "timeStamp", Time.now.to_s) con.put(doc, upd, BDB::XML::GEN_NAME) puts "added #{f} to container #{options['container']}" end txn.commit end ruby-bdb-0.6.6/bdbxml2/examples/dbxml/metadata.rb000077500000000000000000000017761154714021300216300ustar00rootroot00000000000000#!/usr/bin/ruby -I../.. -I../../../src require 'bdbxml' def timestamp(manager, name, query, context) query = "collection('#{name}')#{query}" puts "Exercising query '#{query}'" print "Return to continue : " STDIN.gets results = manager.query(query, context) results.each do |r| r = r.to_document meta = r.get("http://dbxmlExamples/timestamp", "timeStamp") puts "Document '#{r.name}' stored on #{meta}" end puts "#{results.size} objects returned for expression '#{query}'" puts rescue puts "Query #{query} failed : #{$!}" end options = {'home' => 'env', 'container' => 'name.xml'} man = BDB::Env.new(options['home'], BDB::INIT_LOMP).manager con = man.open_container(options['container']) cxt = man.create_query_context cxt.set_namespace("fruits", "http://groceryItem.dbxml/fruits") cxt.set_namespace("vegetables", "http://groceryItem.dbxml/vegetables") cxt.set_namespace("desserts", "http://groceryItem.dbxml/desserts"); timestamp(man, con.name, "/vegetables:item", cxt) ruby-bdb-0.6.6/bdbxml2/examples/dbxml/names.rb000077500000000000000000000020601154714021300211360ustar00rootroot00000000000000#!/usr/bin/ruby -I../.. -I../../../src require 'bdbxml' def names(manager, name, query, context) query = "collection('#{name}')#{query}" puts "Exercising query '#{query}'" print "Return to continue : " STDIN.gets results = manager.query(query, context) results.each do |r| puts "Document name : #{r.name}" puts r end puts "#{results.size} objects returned for expression '#{query}'" puts rescue puts "Query #{query} failed : #{$!}" end options = {'home' => 'env', 'container' => 'name.xml'} man = BDB::Env.new(options['home'], BDB::INIT_LOMP).manager con = man.open_container(options['container']) cxt = man.create_query_context cxt.set_namespace("fruits", "http://groceryItem.dbxml/fruits") cxt.set_namespace("vegetables", "http://groceryItem.dbxml/vegetables") cxt.set_namespace("desserts", "http://groceryItem.dbxml/desserts"); names(man, con.name, "//*[@dbxml:name='ZuluNut.xml']", cxt) names(man, con.name, "//*[@dbxml:name='TrifleOrange.xml']", cxt) names(man, con.name, "//*[@dbxml:name='TriCountyProduce.xml']", cxt) ruby-bdb-0.6.6/bdbxml2/examples/dbxml/query.rb000077500000000000000000000014441154714021300212050ustar00rootroot00000000000000#!/usr/local/bin/ruby -I../.. -I../../../src require 'bdbxml' query = [ '/vendor', '/vendor[@type="wholesale"]', '/product/item[text()="Lemon Grass"]', '/product/inventory[number(price)<=0.11]', '/product[number(inventory/price)<=0.11 and category/text()="vegetables"]', ] options = {'home' => 'env', 'container' => 'simple.xml'} env = BDB::Env.new(options['home'], BDB::INIT_LOMP) man = env.manager con = man.open_container(options['container']) query.each do |q| fq = "collection('#{con.name}')#{q}" puts "Exercising query '#{fq}'" print "Return to continue : " STDIN.gets cxt = man.create_query_context results = man.query(fq, cxt) results.each {|r| puts r} puts "#{results.size} objects returned for expression '#{fq}'" puts end ruby-bdb-0.6.6/bdbxml2/examples/dbxml/replace_index.rb000077500000000000000000000017331154714021300226430ustar00rootroot00000000000000#!/usr/bin/ruby -I../.. -I../../../src require 'bdbxml' def replace(container, uri, name, itype) puts "Replacing index type : #{itype} to #{name}" index = container.index puts "Before index replace" count = 0 index.each do |u, n, i| puts "\tFor node #{n}, found index #{i}." count += 1 end puts "#{count} indexes found" index.replace(uri, name, itype) container.index = index puts "After index replace" count = 0 index.each do |u, n, i| puts "\tFor node #{n}, found index #{i}." count += 1 end puts "#{count} indexes found" rescue puts "Replace index failed #{$!}" end options = {'home' => 'env', 'container' => 'name.xml'} man = BDB::Env.new(options['home'], BDB::INIT_TRANSACTION).manager man.begin do |txn| con = txn.open_container(options['container']) replace(con, "", "product", "node-attribute-substring-string node-element-equality-string edge-element-presence-none") txn.commit end ruby-bdb-0.6.6/bdbxml2/examples/dbxml/retrieve_db.rb000077500000000000000000000014611154714021300223310ustar00rootroot00000000000000#!/usr/bin/ruby -I../.. -I../../../src require 'bdbxml' def value(manager, document, xpath, context) query = manager.prepare(xpath, context) result = query.execute(document, context).to_a if result.size != 1 raise "Expected 1 got #{result.size}" end result[0].to_s end options = {'home' => 'env', 'container' => 'name.xml'} env = BDB::Env.new(options['home'], BDB::INIT_TRANSACTION) man = env.manager context = man.create_query_context man.begin do |txn| con = txn.open_container(options['container']) bdb = txn.open_db(BDB::Btree, 'bdb', nil, 'a') txn.query("collection('#{options['container']}')/vendor") do |doc| res = value(txn, doc, "/vendor/salesrep/name/text()", context) puts "For key '#{res}', retrieved : " puts "\t #{bdb[res]}" end txn.commit end ruby-bdb-0.6.6/bdbxml2/examples/dbxml/update.rb000077500000000000000000000041411154714021300213170ustar00rootroot00000000000000#!/usr/bin/ruby -I../.. -I../../../src require 'bdbxml' def value(man, doc, query, context) doc_expr = man.prepare(query, context) result = doc_expr.execute(doc, context).to_a if result.size != 1 raise "Expected 1 got #{result.size}" end result[0] end def new_document(man, doc, context) res = value(man, doc, "/*/inventory/inventory/text()", context).to_s doc.to_s.sub(/#{res}/, "#{res}__NEW_VALUE") end def update(man, con, query, context) query = "collection('#{con.name}')/#{query}" puts "Updating document for '#{query}'" print "Return to continue : " STDIN.gets results = man.query(query, context) puts "\nFound #{results.size} documents matching the expression '#{query}'" results.each do |r| r = r.to_document puts "Updating document #{r.name}" puts r print "Return to continue : " STDIN.gets r.content = new_document(man, r, context) con.update(r) end puts rescue puts "Query #{query} failed : #{$!}" end def retrieve(man, con, query, context) query = "collection('#{con.name}')/#{query}" puts "Retrieving document for '#{query}'" print "Return to continue : " STDIN.gets results = man.query(query, context) puts "\nFound #{results.size} documents matching the expression '#{query}'" results.each do |r| r = r.to_document puts "Document #{r.name}" puts r print "Return to continue : " STDIN.gets end puts rescue puts "Query #{query} failed : #{$!}" end options = {'home' => 'env', 'container' => 'name.xml'} env = BDB::Env.new(options['home'], BDB::INIT_TRANSACTION) man = env.manager man.begin do |txn| con = txn.open_container(options['container']) cxt = man.create_query_context cxt.set_namespace("fruits", "http://groceryItem.dbxml/fruits") cxt.set_namespace("vegetables", "http://groceryItem.dbxml/vegetables") cxt.set_namespace("desserts", "http://groceryItem.dbxml/desserts"); update(txn, con, "/fruits:item/product[text() = 'Zapote Blanco']", cxt) retrieve(txn, con, "/fruits:item/product[text() = 'Zapote Blanco']", cxt) txn.commit end ruby-bdb-0.6.6/bdbxml2/examples/event_reader.rb000066400000000000000000000032661154714021300213760ustar00rootroot00000000000000#!/usr/bin/ruby $LOAD_PATH.unshift Dir.pwd.sub(%r{(bdb-\d\.\d\.\d/).*}, '\1bdbxml2') require 'bdbxml' File::unlink("exa.dbxml") rescue nil man = BDB::XML::Manager.new con = man.create_container("exa.dbxml") at_exit { con.close man.close } con.put("doc", "a text") doc = con.get("doc") rdr = doc.event_reader while rdr.next? case rdr.next when BDB::XML::EventReader::StartElement puts "BDB::XML::EventReader::StartElement" when BDB::XML::EventReader::EndElement puts "BDB::XML::EventReader::EndElement" when BDB::XML::EventReader::StartDocument puts "BDB::XML::EventReader::StartDocument" when BDB::XML::EventReader::EndDocument puts "BDB::XML::EventReader::EndDocument" when BDB::XML::EventReader::StartEntityReference puts "BDB::XML::EventReader::StartEntityReference" when BDB::XML::EventReader::EndEntityReference puts "BDB::XML::EventReader::EndEntityReference" when BDB::XML::EventReader::Characters puts "BDB::XML::EventReader::Characters" when BDB::XML::EventReader::CDATA puts "BDB::XML::EventReader::CDATA" when BDB::XML::EventReader::Comment puts "BDB::XML::EventReader::Comment" when BDB::XML::EventReader::Whitespace puts "BDB::XML::EventReader::Whitespace" when BDB::XML::EventReader::DTD puts "BDB::XML::EventReader::DTD" when BDB::XML::EventReader::ProcessingInstruction puts "BDB::XML::EventReader::ProcessingInstruction" end end rdr.close val = BDB::XML::Value.new(doc) rdr = val.event_reader doc1 = man.create_document doc1.name = 'doc1' doc1.content = rdr con.put(doc1) doc1 = con.get('doc1') puts doc1.content ruby-bdb-0.6.6/bdbxml2/examples/event_writer.rb000066400000000000000000000017561154714021300214520ustar00rootroot00000000000000#!/usr/bin/ruby $LOAD_PATH.unshift Dir.pwd.sub(%r{(bdb-\d\.\d\.\d/).*}, '\1bdbxml2') require 'bdbxml' File::unlink("exa.dbxml") rescue nil man = BDB::XML::Manager.new con = man.create_container("exa.dbxml", 0, BDB::XML::Container::NodeContainer) doc = man.create_document at_exit { con.close man.close } doc.name = 'doc' wrt = con.event_writer(doc, man.create_update_context) wrt.start_document wrt.start_element("root", nil, nil, 0, false) wrt.start_element("a", nil, nil, 1, false) wrt.attribute("a1", nil, nil, "val1", true) wrt.text(BDB::XML::EventReader::Characters, "a text") wrt.end_element("a") wrt.start_element("b", nil, nil, 0, false) wrt.start_element("c", nil, nil, 1, false) wrt.attribute("cattr", nil, nil, "c1", true) wrt.start_element("d", nil, nil, 0, true) wrt.end_element("c") wrt.text(BDB::XML::EventReader::Characters, "b text") wrt.text(BDB::XML::EventReader::Characters,"plus") wrt.end_element("b") wrt.end_element("root") wrt.end_document wrt.close puts con.get('doc') ruby-bdb-0.6.6/bdbxml2/examples/index.rb000066400000000000000000000022411154714021300200320ustar00rootroot00000000000000#!/usr/bin/ruby $LOAD_PATH.unshift("../../src", "..") require 'bdbxml' File::unlink("exa.dbxml") rescue nil man = BDB::XML::Manager.new con = man.create_container("exa.dbxml") at_exit { con.close man.close } index = con.index index.add(BDB::XML::Namespace["uri"], BDB::XML::Name["default"], "node-attribute-substring-string") index.add("http://moulon/", "ref2", "node-attribute-equality-string") index.add("http://moulon/", "ref0", "node-attribute-equality-string") index.add("http://moulon/", "ref1", "node-element-presence-none") index.each do |url, name, val| puts "#{url}, #{name}, #{val}" end p index.find("http://moulon/", "ref2") p index.find("", "ref2") index.add("http://moulon/", "ref0", "node-element-presence-none") index.add("http://moulon/", "ref0", "edge-attribute-equality-string") p index.find("http://moulon/", "ref0") index.delete("http://moulon/", "ref0", "node-attribute-equality-string") p index.find("http://moulon/", "ref0") index.replace("http://moulon/", "ref0", "edge-element-presence-none") p index.find("http://moulon/", "ref0") index.replace("http://moulon/", "ref0", "none-none-none-none") p index.find("http://moulon/", "ref0") ruby-bdb-0.6.6/bdbxml2/examples/indexlookup.rb000077500000000000000000000072401154714021300212730ustar00rootroot00000000000000#!/usr/bin/ruby $LOAD_PATH.unshift("../../src", "..") require 'bdbxml' include BDB File::unlink("exa.dbxml") rescue nil man = XML::Manager.new con = man.create_container("exa.dbxml", XML::INDEX_NODES) at_exit { con.close man.close } upd = man.create_update_context con.add_index("", "foo", "node-element-equality-string") con.add_index("http://www.example.com/schema", "foo", "node-element-equality-string") con.add_index("", "foo", "node-element-presence") con.add_index("http://www.example.com/schema", "foo", "node-element-presence") con.add_index("", "len", "edge-attribute-equality-decimal") con.add_index("", "len", "edge-attribute-presence") con.add_index("", "date", "edge-element-equality-date") con.put("docA", <<-EOT, upd) hello charlie brown aNd Lucy EOT con.put("docB", <<-EOT, upd) hello charlie brown aNd Lucy EOT con.put("docC", <<-EOT, upd) tall guy 30 yds 30 yds five feeet point two five feet EOT con.put("docD", <<-EOT, upd) 2005-08-02 2003-06-12 1005-12-12 1492-05-30 2000-01-01 1984-12-25 EOT puts "content" con.each do |value| puts "\n\tDocument #{value.to_document.name}" puts value end puts "\nnode-element-presence\n" xil = man.create_index_lookup(con, "", "foo", "node-element-presence") ["", "http://www.example.com/schema" ].each do |uri| xil.node_uri = uri puts "\tnode : #{xil.node.inspect}" xil.execute.each {|p| puts "\t\t#{p}"} end puts "\nnode-element-equality-string : charlie" xil = man.create_index_lookup(con, "", "foo", "node-element-equality-string") [[XML::IndexLookup::LT, "<"], [XML::IndexLookup::LTE, "<="], [XML::IndexLookup::GT, ">"], [XML::IndexLookup::GTE, ">="]].each do |comp, rep| xil.low_bound = ["charlie", comp] puts "\n low_bound : charlie #{rep} #{xil.low_bound[0]}" ["", "http://www.example.com/schema" ].each do |uri| xil.node_uri = uri puts "\tnode : #{xil.node.inspect}" xil.execute.each {|p| puts "\t\t#{p}"} puts "\tnode : #{xil.node.inspect} -- reverse" xil.execute(nil, XML::REVERSE_ORDER).each {|p| puts "\t\t#{p}"} end end puts "\nedge-attribute-equality-decimal : 40" xil = man.create_index_lookup(con, "", "len", "edge-attribute-equality-decimal") xil.parent = ["", "baz"] [[XML::IndexLookup::LT, "<"], [XML::IndexLookup::LTE, "<="], [XML::IndexLookup::GT, ">"], [XML::IndexLookup::GTE, ">="]].each do |comp, rep| xil.low_bound = [XML::Value.new(XML::Value::DECIMAL, 40), comp] puts "\n low_bound : len #{rep} #{xil.low_bound[0]}" puts "\tnode : #{xil.node.inspect}" xil.execute.each {|p| puts "\t\t#{p}"} puts "\tnode : #{xil.node.inspect} -- reverse" xil.execute(nil, XML::REVERSE_ORDER).each {|p| puts "\t\t#{p}"} end puts "\nedge-element-equality-date : date == 2003-06-12" xil = man.create_index_lookup(con, "", "date", "edge-element-equality-date", XML::Value.new(XML::Value::DATE, "2003-06-12"), XML::IndexLookup::EQ) xil.parent = ["", "dates1"] puts "\tparent = dates1" xil.execute.each {|p| puts "\t\t#{p}"} xil.parent = ["", "dates2"] puts "\tparent = dates2" xil.execute(nil, XML::REVERSE_ORDER).each {|p| puts "\t\t#{p}"} ruby-bdb-0.6.6/bdbxml2/examples/modify.rb000077500000000000000000000007421154714021300202210ustar00rootroot00000000000000#!/usr/local/bin/ruby $LOAD_PATH.unshift("..", "../../src") require 'bdbxml' include BDB::XML File.unlink("exa.dbxml") rescue nil man = Manager.new doc = man.create_document at_exit { doc.close man.close } doc.name = "test1" doc.content = '' puts "#{doc.name} = #{doc}" que = man.prepare("/root") mod = Modify.new(man) mod.append(que, Modify::Element, "new", "foo") mod.execute(doc) puts "#{doc.name} = #{doc}" ruby-bdb-0.6.6/bdbxml2/examples/transaction.rb000077500000000000000000000022611154714021300212550ustar00rootroot00000000000000#!/usr/local/bin/ruby $LOAD_PATH.unshift("..", "../../src") require 'bdbxml' require 'find' Find::find('tmp') do |f| File::unlink(f) if FileTest::file? f end env = BDB::Env.new("tmp", BDB::CREATE | BDB::INIT_TRANSACTION) bdb = env.open_db(BDB::Btree, "tutu", nil, "a") man = env.manager doc = man.create_container("toto", BDB::XML::TRANSACTIONAL) at_exit { doc.close man.close } 2.times do |i| doc.put("#{i}", "title nb #{i}") bdb[i] = "bdb#{i}" end que = man.prepare("collection('toto')/bk") qc = man.create_query_context man.begin(doc, bdb, que) do |txn, doc1, bdb1, que1| 2.times do |i| bdb1[i+2] = "bdb#{i+2}" doc1.put("#{i+2}", "title nb #{i+2}") end puts "=============== get ========================" p doc1.get("2") puts "================ each ======================" que1.execute(qc) {|x| p x } puts "================= bdb ======================" bdb1.each {|k,v| p "#{k} -- #{v}" } # implicit txn.abort end puts "=============== each ======================" que.execute(qc) {|x| p x } puts "================= bdb =====================" bdb.each {|k,v| p "#{k} -- #{v}" } ruby-bdb-0.6.6/bdbxml2/extconf.rb000066400000000000000000000044621154714021300165620ustar00rootroot00000000000000# VERIFY 'myconfig' then comment this line require 'mkmf' load './myconfig' $DLDFLAGS ||= "" $LDFLAGS ||= "" def addld(key, path, lib) libs = if lib.kind_of?(Array) "-l" + lib.join(" -l") else "-l#{lib}" end if path case Config::CONFIG["arch"] when /solaris2/ libs = " -L#{path} -R#{path} #{libs}" when /linux/ libs = " -Wl,-rpath,#{path} -L#{path} #{libs}" else libs = " -L#{path} #{libs}" end end $stderr.puts "\t#{key}\tusing ... #{libs}" $DLDFLAGS += " #{libs}" $LDFLAGS += " #{libs}" end $CFLAGS += " -I. -I../src" $stderr.puts "INCLUDE" $order.each do |key| val = $include[key] unless val.nil? res = if val.kind_of?(Array) " -I" + val.join(" -I") else " -I#{val}" end $stderr.puts "\t#{key}\tusing ... #{res}" $CFLAGS += res end end $CFLAGS += " -DBDB_NO_THREAD" if enable_config("thread") == false $stderr.puts "\nLIBRARY" $order.each do |key| val = $library[key] if val.kind_of?(Array) && val.size == 2 addld(key, *val) end end if CONFIG["LDSHARED"] == "gcc -shared" CONFIG["LDSHARED"] = "g++ -shared" end if with_config("bdb-objs") bdb_obj = Dir["../src/*.#{$OBJEXT}"] if bdb_obj.size == 0 puts <<-EOT **************************************************** Build bdb first, if you want to link bdbxml with bdb **************************************************** EOT exit end $objs = ["bdbxml.o"] + bdb_obj $CFLAGS += " -DBDB_LINK_OBJ" end have_func("rb_block_call") require './features' create_makefile('bdbxml') begin make = open("Makefile", "a") make.print <<-EOF %.html: %.rd \trd2 $< > ${<:%.rd=%.html} EOF make.print "HTML = bdbxml.html" docs = Dir['docs/*.rd'] docs.each {|x| make.print " \\\n\t#{x.sub(/\.rd$/, '.html')}" } make.print "\n\nRDOC = bdbxml.rd" docs.each {|x| make.print " \\\n\t#{x}" } make.puts make.print <<-EOF rdoc: docs/doc/index.html docs/doc/index.html: $(RDOC) \t@-(cd docs; rdoc .) ri: \t@-(rdoc -r docs/*rb) ri-site: \t@-(rdoc -R docs/*rb) rd2: html html: $(HTML) test: $(DLLIB) EOF Dir.glob('tests/*.rb') do |x| next if /(_\.rb|~)$/ =~ x next if FileTest.directory?(x) make.print "\t#{CONFIG['RUBY_INSTALL_NAME']} #{x}\n" end ensure make.close end ruby-bdb-0.6.6/bdbxml2/features.rb000066400000000000000000000265531154714021300167370ustar00rootroot00000000000000class Object remove_const('CONFTEST_C') end CONFTEST_C = 'conftest.cxx' unless "a".respond_to?(:tr_cpp) class String def tr_cpp strip.upcase.tr_s("^A-Z0-9_", "_") end end end def try_dbxml_compile(mes, func, src) new_src = " #include using namespace DbXml; int main() { #{src} return 1; } " print "checking for #{mes}... " if try_compile(new_src) $defs << "-DHAVE_DBXML_#{func}" puts "yes" true else $defs << "-DNOT_HAVE_DBXML_#{func}" puts "no" false end end def have_dbxml_const(const) const.each do |c| try_dbxml_compile(c, "CONST_#{c.tr_cpp}", < int main() { rb_iterate(RUBY_METHOD_FUNC(rb_each), (VALUE)0, RUBY_METHOD_FUNC(0), (VALUE )0); } EOT $defs << '-DHAVE_DBXML_RB_NEW_PROTO' else $defs << '-DNOT_HAVE_DBXML_RB_NEW_PROTO' end puts have_dbxml_const([ 'CATEGORY_ALL', 'CATEGORY_CONTAINER', 'CATEGORY_DICTIONARY', 'CATEGORY_INDEXER', 'CATEGORY_MANAGER', 'CATEGORY_NODESTORE', 'CATEGORY_NONE', 'CATEGORY_OPTIMIZER', 'CATEGORY_QUERY', 'DBXML_ADOPT_DBENV', 'DBXML_ALLOW_AUTO_OPEN', 'DBXML_ALLOW_EXTERNAL_ACCESS', 'DBXML_ALLOW_VALIDATION', 'DBXML_CACHE_DOCUMENTS', 'DBXML_CHKSUM_SHA1', 'DBXML_DOCUMENT_PROJECTION', 'DBXML_ENCRYPT', 'DBXML_GEN_NAME', 'DBXML_INDEX_NODES', 'DBXML_INDEX_VALUES', 'DBXML_LAZY_DOCS', 'DBXML_NO_AUTO_COMMIT', 'DBXML_NO_INDEX_NODES', 'DBXML_NO_STATISTICS', 'DBXML_REVERSE_ORDER', 'DBXML_STATISTICS', 'DBXML_TRANSACTIONAL', 'DBXML_WELL_FORMED_ONLY', 'LEVEL_ALL', 'LEVEL_DEBUG', 'LEVEL_ERROR', 'LEVEL_INFO', 'LEVEL_NONE', 'LEVEL_WARNING']) have_dbxml_const([ 'XmlContainer::NodeContainer', 'XmlContainer::WholedocContainer', 'XmlEventReader::CDATA', 'XmlEventReader::Characters', 'XmlEventReader::Comment', 'XmlEventReader::DTD', 'XmlEventReader::EndDocument', 'XmlEventReader::EndElement', 'XmlEventReader::EndEntityReference', 'XmlEventReader::ProcessingInstruction', 'XmlEventReader::StartDocument', 'XmlEventReader::StartElement', 'XmlEventReader::StartEntityReference', 'XmlEventReader::Whitespace', 'XmlIndexLookup::EQ', 'XmlIndexLookup::GT', 'XmlIndexLookup::GTE', 'XmlIndexLookup::LT', 'XmlIndexLookup::LTE', 'XmlIndexLookup::NONE']) have_dbxml_const([ 'XmlIndexSpecification::KEY_EQUALITY', 'XmlIndexSpecification::KEY_NONE', 'XmlIndexSpecification::KEY_PRESENCE', 'XmlIndexSpecification::KEY_SUBSTRING', 'XmlIndexSpecification::NODE_ATTRIBUTE', 'XmlIndexSpecification::NODE_ELEMENT', 'XmlIndexSpecification::NODE_METADATA', 'XmlIndexSpecification::NODE_NONE', 'XmlIndexSpecification::PATH_EDGE', 'XmlIndexSpecification::PATH_NODE', 'XmlIndexSpecification::PATH_NONE', 'XmlIndexSpecification::UNIQUE_OFF', 'XmlIndexSpecification::UNIQUE_ON', 'XmlModify::Attribute', 'XmlModify::Comment', 'XmlModify::Element', 'XmlModify::ProcessingInstruction', 'XmlModify::ProcessingInstruction', 'XmlModify::Text', 'XmlQueryContext::DeadValues', 'XmlQueryContext::Eager', 'XmlQueryContext::Lazy', 'XmlQueryContext::LiveValues']) have_dbxml_const([ 'XmlValue::ANY_SIMPLE_TYPE', 'XmlValue::ANY_URI', 'XmlValue::BASE_64_BINARY', 'XmlValue::BOOLEAN', 'XmlValue::DATE', 'XmlValue::DATE_TIME', 'XmlValue::DAY_TIME_DURATION', 'XmlValue::DECIMAL', 'XmlValue::DOUBLE', 'XmlValue::DURATION', 'XmlValue::FLOAT', 'XmlValue::G_DAY', 'XmlValue::G_MONTH', 'XmlValue::G_MONTH_DAY', 'XmlValue::G_YEAR', 'XmlValue::G_YEAR_MONTH', 'XmlValue::HEX_BINARY', 'XmlValue::NODE', 'XmlValue::NONE', 'XmlValue::NOTATION', 'XmlValue::QNAME', 'XmlValue::STRING', 'XmlValue::TIME', 'XmlValue::UNTYPED_ATOMIC ', 'XmlValue::YEAR_MONTH_DURATION']) # try_dbxml_compile('XmlManager::compactContainer', 'MAN_COMPACT_CONTAINER', <compactContainer(name, *upd, (u_int32_t)0); EOT try_dbxml_compile('XmlManager::truncateContainer', 'MAN_TRUNCATE_CONTAINER', <truncateContainer(name, *upd, (u_int32_t)0); EOT try_dbxml_compile('XmlManager::getFlags', 'MAN_GET_FLAGS', <getFlags(); EOT try_dbxml_compile('XmlManager::getImplicitTimezone', 'MAN_GET_IMPLICIT_TIMEZONE', <getImplicitTimezone(); EOT try_dbxml_compile('XmlManager::existsContainer', 'MAN_EXISTS_CONTAINER', <existsContainer(""); EOT try_dbxml_compile('XmlManager::reindexContainer', 'MAN_REINDEX_CONTAINER', <reindexContainer(name, *upd, (u_int32_t)0); EOT try_dbxml_compile('XmlManager::getDefaultSequenceIncrement', 'MAN_DEFAULT_SEQUENCE_INCREMENT', <getDefaultSequenceIncrement(); EOT try_dbxml_compile('XmlIndexLookup::Operation', 'XML_INDEX_LOOKUP', <openContainer((char *)"", 0); con.getIndexNodes(); EOT try_dbxml_compile('XmlContainer::getPageSize', 'CON_PAGESIZE', <openContainer((char *)"", 0); con.getPageSize(); EOT try_dbxml_compile('XmlContainer::getFlags', 'CON_FLAGS', <openContainer((char *)"", 0); con.getFlags(); EOT try_dbxml_compile('XmlContainer::getNode', 'CON_NODE', <openContainer((char *)"", 0); con.getNode("", 0); EOT try_dbxml_compile('XmlEventWriter', 'XML_EVENT_WRITER', <openContainer((char *)"", 0); con.putDocumentAsEventWriter(*doc, *upd, 0); EOT try_dbxml_compile('new XmlEventWriter', 'XML_EVENT_WRITER_ALLOC', <createUpdateContext(); upd.getApplyChangesToContainers(); EOT try_dbxml_compile('XmlQueryContext::getVariableValue', 'CXT_VARIABLE_VALUE', <createQueryContext(rt, et); XmlResults res; cxt.getVariableValue((char *)"", res); EOT try_dbxml_compile('XmlQueryContext::getDefaultCollection', 'CXT_COLLECTION', <createQueryContext(rt, et); XmlResults res; cxt.getDefaultCollection(); EOT try_dbxml_compile('XmlQueryContext::interruptQuery', 'CXT_INTERRUPT', <createQueryContext(rt, et); XmlResults res; cxt.interruptQuery(); EOT try_dbxml_compile('XmlQueryContext::getQueryTimeoutSeconds', 'CXT_TIMEOUT', <createQueryContext(rt, et); XmlResults res; cxt.getQueryTimeoutSeconds(); EOT try_dbxml_compile('XmlQueryExpression::isUpdateExpression', 'QUE_UPDATE', <createQueryContext(); XmlQueryExpression que = man->prepare((char *)"", cxt); que.isUpdateExpression(); EOT try_dbxml_compile('XmlResults::getEvaluationType', 'RES_EVAL', <)) Glossary # Original: by matz@zetabits.com (Yukihiro Matsumoto, aka matz) # English Translation: by matz himself and web-i31s@clio.ne.jp (SugHimsi) et alii. # First Release: 2000-12-25 # Last Retrieval: 2000-12-29 (Fixed some misspelling.) =end ruby-bdb-0.6.6/bdbxml2/glossary/abstract_data_type000066400000000000000000000007771154714021300222170ustar00rootroot00000000000000 Abstract Data Type encapsulation data A bunch of data structure and operation to the ((data|Data)) is called an abstract data type. The abstract data should not be operated unless passing this operation. As a result, it is not referred directly from the outside, and the change in an internal structure does not color the outside. This is called ((encapsulation|Encapsulation)). ruby-bdb-0.6.6/bdbxml2/glossary/associative_array000066400000000000000000000012251154714021300220570ustar00rootroot00000000000000 Associative Array hash Alias of ((hash|Hash)) It seems "Associative" is because the hash can take out the value of an arbitrary key, and "Array" is because you can assume it to be an array which the subscript is not number. Once upon a time, the associative array (called associative memory then) was thought to be realized with hardware, but improvement of hardware's calculation speed and discovery of an appropriate algorithm (it is called "((Hash)) table", derivation of the hash) brought us achievement only with software. ruby-bdb-0.6.6/bdbxml2/glossary/awk000066400000000000000000000003551154714021300171340ustar00rootroot00000000000000 AWK scripting language A small ((scripting language|Scripting Language)) by Alfred ((*A*))ho, Peter ((*W*))einberger, and Brian ((*K*))ernighan. ruby-bdb-0.6.6/bdbxml2/glossary/big_endian000066400000000000000000000012301154714021300204220ustar00rootroot00000000000000 Big Endian byte order data little endian The American Continent original inhabitants... are Indians. Here: ((*endian*)). The etymology is the people who eat the egg from a round edge, after Swift's "Gulliver's Travels." Naturally, the people who eat from a pointed edge are the (('Little' endian|Little Endian)). In the computer industry, it is one of the forms when CPU etc. arrange ((data|Data)). The networkers are said that they will like Big endian. See also "((byte order|Byte Order))." ruby-bdb-0.6.6/bdbxml2/glossary/block000066400000000000000000000002361154714021300174420ustar00rootroot00000000000000 Block The one to compose loop with, to build house and wall with, or to hit person with. ruby-bdb-0.6.6/bdbxml2/glossary/bug000066400000000000000000000001071154714021300171220ustar00rootroot00000000000000 Bug unknown ruby-bdb-0.6.6/bdbxml2/glossary/built-in_class000066400000000000000000000014251154714021300212610ustar00rootroot00000000000000 Built-In Class object instance ruby data hash thread ((Ruby)) interpreter built-in class which the structure of ((instance|Instance)) is different from usual ((object|Object)). To define the class which inherits these classes is not recommended. A built-in class of ((Ruby)) is as follows: * Array * Bignum * Class * ((Data)) * FalseClass * File * Fixnum * Float * ((Hash)) * IO * ((MatchingData)) * Module * NilClass * Proc * Regexp * String * Struct * ((Thread)) * TrueClass ruby-bdb-0.6.6/bdbxml2/glossary/byte_order000066400000000000000000000007351154714021300205120ustar00rootroot00000000000000 Byte Order data big endian little endian Do you arrange four byte ((data|Data)) 0x1234 with 1, 2, 3, 4? or 4, 3, 2, 1? The former way is called ((Big Endian)), and the latter is called ((Little Endian)). The controversy which is good continues from the preliterate era and till now the conclusion has not been reached yet. ruby-bdb-0.6.6/bdbxml2/glossary/class000066400000000000000000000001151154714021300174510ustar00rootroot00000000000000 Class A Nice Name ruby-bdb-0.6.6/bdbxml2/glossary/class_method000066400000000000000000000007221154714021300210150ustar00rootroot00000000000000 Class Method self method ((Method)) of class. It is defined in class Class of all classes. Though there is a method which is common in all classes and a ((singleton method|Singleton Method)) which is proper to each class. that's not much of a problem. Do not misunderstand than '((|((self))|))' in the class method is a class. ruby-bdb-0.6.6/bdbxml2/glossary/coerce000066400000000000000000000012521154714021300176070ustar00rootroot00000000000000 Coerce instance method ruby ((Method)) of converting type of numerical value. The numeric calculation method is set on, when the ((instance|Instance)) which it doesn't know is passed as an argument, which the coerce method is used to convert it. The coerce method returns a pair of given (, and converted) value and itself (a converted value, if necessary), as its arguments. The converting order of numerical types of the library of ((Ruby)) is as follows: Fixnum -> Bignum -> Rational -> Float -> Complex ruby-bdb-0.6.6/bdbxml2/glossary/constant000066400000000000000000000003041154714021300201750ustar00rootroot00000000000000 Constant variable ((Variable)) which cannot change value once it is defined. ...Contradiction in terms? ruby-bdb-0.6.6/bdbxml2/glossary/data000066400000000000000000000010411154714021300172540ustar00rootroot00000000000000 Data function object ruby Wrapper to show pointer at C level as ((Ruby)) ((object|Object)). It is made of C pointer, the mark function, and the free function. The person who tries to add the ((function|Function)) to ((Ruby)) by C should master the usage of this class, by all means. Contrary to that, it is a class that have no business with a person whose schedule has no chance to try it. ruby-bdb-0.6.6/bdbxml2/glossary/defined?000066400000000000000000000010161154714021300200420ustar00rootroot00000000000000 defined? method ruby Operator to examine whether the various expression is actually defined. It returns the string to show the type of the expression if defined, and returns nil if not defined. While defined? looks like the ((method|Method)), it is the built-in operator of ((Ruby)), and it doesn't evaluate arguments. Therefore, there'll be no output with: defined? print("abc\n") ruby-bdb-0.6.6/bdbxml2/glossary/destructive000066400000000000000000000005261154714021300207130ustar00rootroot00000000000000 Destructive receiver method ((Method)) such as String#chop and Array#concat is said "It has destructive action", since they change the state of the ((receiver|Receiver)), though the hardware is seldom put out of order. ruby-bdb-0.6.6/bdbxml2/glossary/dictionary000066400000000000000000000011411154714021300205110ustar00rootroot00000000000000 Dictionary data paradigm object-oriented hash ruby The one that can take the definition out of the item. Changed to the alias of "((hash|Hash))." In ((Smalltalk)) (which can be called the origin of ((object-oriented|Object-Oriented)) ((paradigm|Paradigm)) the ((data|Data)) structure which corresponds to the hash was called "Dictionary." So there are specks of the crowd who are familiar with that term. ruby-bdb-0.6.6/bdbxml2/glossary/document000066400000000000000000000005431154714021300201670ustar00rootroot00000000000000 document bugs matz The one that ((matz)) is really bad at. He always says "the source itself should be the document. It even describes ((bugs|Bug)) perfectly." But no one agrees. This is the programmers' use and wont. Sigh. ruby-bdb-0.6.6/bdbxml2/glossary/dynamic_binding000066400000000000000000000012751154714021300214720ustar00rootroot00000000000000 Dynamic Binding variable paradigm object-oriented object data method ruby To select an appropriate procedure (((method|Method))) on the operation according to the ((data|Data)) type of its ((object|Object)). The flexibility of the program is effected to be improved. One of the requirements for ((object-oriented|Object-Oriented)) ((paradigm|Paradigm)). Dynamic binding is inevitable in ((Ruby)) because there is no type in the ((variable|Variable)). ruby-bdb-0.6.6/bdbxml2/glossary/eiffel000066400000000000000000000011131154714021300175750ustar00rootroot00000000000000 Eiffel block object-oriented programming ruby matz An ((object-oriented programming|Object-Oriented Programming)) language. Young ((matz)) has said to drop scales off his eyes by the book "Object-oriented Software Construction," written by the author of this language. Even so, ((Ruby)) doesn't look like Eiffel at all, except the ((block|Block)) end (with '((|((end))|))') and a reserved word '((|rescue|)).' ruby-bdb-0.6.6/bdbxml2/glossary/encapsulation000066400000000000000000000012001154714021300212050ustar00rootroot00000000000000 Encapsulation instance variable method data ruby To hide the algorithm of an internal structure and processing from outside, by the immediate operation to ((data|Data)) only from a specific procedure (called the ((method|Method))) which accompanies the type of data. See also "((Abstract Data Type))." In ((Ruby)) it can be said that encapsulation will be compelled since it is impossible to refer to the ((instance variable|Instance Variable)) from non-method. ruby-bdb-0.6.6/bdbxml2/glossary/end000066400000000000000000000040271154714021300171200ustar00rootroot00000000000000 end block bug ruby eiffel perl matz Reserved word to which ((block|Block)) structure is finished. According to a certain statistics, 33% of the person, who saw ((Ruby)) first sees this, associates Pascal. (...trust it?) However, this form which does not pair with '((|begin|))' is actually the neighbor of Ada or ((Eiffel)) rather than Pascal. ((Ruby)) do not to have offered to {} which had been accustomed and familiar with C and ((Perl)). It is from the following reasons: * Evasion of ambiguous simple / complex sentence problem For instance, in C, when you try to add a sentence on if (a==b) c(); and do as follows if (a==b) c(); d(); leads a confusing ((bug|Bug)). This problem exists also in Pascal. * Evasion of dangling 'else' problem It is similar to the situation above-mentioned. If you write if (a==b) if (c==d) foo(); else bar(); it becomes annoying. To tell the truth, what you really meant is: if (a==b) { if (c==d) foo(); else bar(); } * Improvement of readability There is a person who thinks that closing the ((block|Block)) in the word named 'end' is legible to program, though it is a debatable opinion. * Problems in sentence structure of '((|begin|))' and '((|case|))' Frankly speaking, ((matz)) have tried to use the ((variable|Variable)) 'end' several time only to have had a terrible time. Then, he examined to change to the grammar with {} for a time, but every time he abandoned it for the part of grammar of '((|begin|))' and '((|case|))' with no beauty. To tell the truth, this might be the first reason. ruby-bdb-0.6.6/bdbxml2/glossary/env000066400000000000000000000012051154714021300171350ustar00rootroot00000000000000 ENV environment variable singleton method instance ruby object hash ((Object)) which operates same as ((Hash)) to access ((environment variable|Environment Variable)). Actually it is an ((instance|Instance)) of the Object class which adds a ((singleton method|Singleton Method)). When the ((environment variable|Environment Variable)) is changed with this object, it is succeeded to the offspring process of ((Ruby)). ruby-bdb-0.6.6/bdbxml2/glossary/environment_variable000066400000000000000000000007271154714021300225660ustar00rootroot00000000000000 Environment Variable Value which is delivered from parent process to offspring process. It is accessed with ((|((ENV))|)). What is delivered to the offspring process is a copy of the environment ((variable|Variable)), so it is not possible to pass informations from the offspring process to the parent by using the environment variable. The parent will not listen to the child. ruby-bdb-0.6.6/bdbxml2/glossary/exception000066400000000000000000000013031154714021300203420ustar00rootroot00000000000000 Exception thread ruby The one occurs in exceptional situation. when it occurs, unless it is caught explicitly by '((|rescue|))' paragraph of '((|begin|))', the call hierarchy is traced back and the execution of program (((Thread))) is interrupted. The ((Ruby)) program should thank exception, because it is able to ((end)) without checking an exceptional situation one by one, in almost all of the case. The information on the place where the exception is generated is stored in ((|$@|)), and the information on the exception itself is stored in ((|$!|)). ruby-bdb-0.6.6/bdbxml2/glossary/faq000066400000000000000000000003361154714021300171200ustar00rootroot00000000000000 FAQ ruby ...And the compiled answers of them. ((Ruby)) FAQ is still developing now. Questions and answers are always welcome. ruby-bdb-0.6.6/bdbxml2/glossary/function000066400000000000000000000016771154714021300202070ustar00rootroot00000000000000 Function self module function receiver instance variable method ruby Strictly speaking, ((Ruby)) has no functions. But the appearance of a method call with ((receiver|Receiver)) left out is like a function, and furthermore, there is a ((method|Method)) which we can describe it as a virtual function, ((|((self))|)), ((instance variable|Instance Variable)), where no ((receiver|Receiver)) informations are referred. Such methods are sometimes, in a torelant situation, called functions. Mostly such function(al method)s' visibility is set to private, so that they could not be called in the form which ((receiver|Receiver)) is not omitted. The representative of that methods is ((module function|Module Function)). ruby-bdb-0.6.6/bdbxml2/glossary/global_variable000066400000000000000000000003241154714021300214530ustar00rootroot00000000000000 Global Variable variable ((Variable)) which can be referred to anywhere in the program. ((*Danger!*)) Overuse deadlock. ruby-bdb-0.6.6/bdbxml2/glossary/goto000066400000000000000000000007511154714021300173220ustar00rootroot00000000000000 goto exception ruby non-local exit One of which ((Ruby)) doesn't have. Why ((|goto|))'s absent is not for the policy "it should not be anywhere," but for the fact "it's troublesome in implementation." In place of ((|goto|)), ((|catch|))/((|throw|)) or the ((exception|Exception)) is used\ in ((Ruby)). See also "((Non-Local Exit))." ruby-bdb-0.6.6/bdbxml2/glossary/hash000066400000000000000000000007511154714021300172750ustar00rootroot00000000000000 Hash associative array dictionary ruby Data structure in ((Ruby)) which expresses the mapping from key to value. It is also called "((Associative Array))" or "((Dictionary))." The derivation of hash is the algorithm which is called "Hash table" in the achievement of the structure. The word 'hash' means "cut in pieces", of "hashed beef." ruby-bdb-0.6.6/bdbxml2/glossary/immediate_value000066400000000000000000000011601154714021300214770ustar00rootroot00000000000000 Immediate Value object reference variable ruby The one in ((variable|Variable)) that not ((reference|Reference)) but actual value is stored. Only '((|Fixnum|))' and ((|nil|))/((|true|))/((|false|)) are immediate values in present ((Ruby)). However, there's no law against another ((Ruby)) which ((|Fixnum|)) is not immediate value, and also you can regard the all values on the model as a ((reference|Reference)) to the ((object|Object)). ruby-bdb-0.6.6/bdbxml2/glossary/inheritance000066400000000000000000000014711154714021300206430ustar00rootroot00000000000000 Inheritance function mix-in Do minimum in itself, and fully rely on what succeeded from the ancestor or the relative to deal the rest matter. In the real world, It should be an unpleasant fellow. Turned to establish a new class which adds the ((function|Function)) to a certain class. Inheritance is effective to express the relation of is-a. For instance, "Student" class which describes the character of the general student can be succeeded to "Department of Engineering student (who is afflicted with the experiment)" class. When there is no is-a relation and the situation only shares the character and the function, it is assumed preferable to use ((Mix-in)). ruby-bdb-0.6.6/bdbxml2/glossary/initialize000066400000000000000000000013211154714021300205050ustar00rootroot00000000000000 Initialize block method object Put the ((object|Object)) (or "something") into "ready-to-use-it" state. The '((|initialize|))' ((method|Method)) should be redefined to initialize the ((instance|Instance)). The default definition of the method '((|new|))' of the class is to execute Initialize to the newly generated instance. The argument to ((|new|)) is tossed to initialize as it is. Moreover, when ((|new|)) is called with the ((block|Block)), the block is given to initialize as it is. This surely means Class#new is not to have to be redefined. ruby-bdb-0.6.6/bdbxml2/glossary/instance000066400000000000000000000007541154714021300201610ustar00rootroot00000000000000 Instance paradigm object-oriented object ((Object)) There seems to be a meaning to emphasize belonging to the class where the object exists. It is heard that there are a lot of people who have failed in ((object-oriented|Object-Oriented)) ((paradigm|Paradigm)) by confusing whether the one s/he touches is an object or an instance. ruby-bdb-0.6.6/bdbxml2/glossary/instance_variable000066400000000000000000000007201154714021300220170ustar00rootroot00000000000000 Instance Variable method instance object variable ruby Intrinsic ((variable|Variable)) to ((object|Object)). The ((instance|Instance)) variable of ((Ruby)) is the one that applies @ just before the identifier. It can be referred only from inside of the ((method|Method)). ruby-bdb-0.6.6/bdbxml2/glossary/iterator000066400000000000000000000017451154714021300202070ustar00rootroot00000000000000 Iterator block method Rehearser The group of a certain code which can be passed to the ((method|Method)) is called '((block|Block)).' Iterator is the method which the given block...this is surely the case. In general, the block is executed more than one time, so the method is called 'iterator' ("iterate" = repeat it); but there is a custom to call the case executing only once or not repeating, also iterator, insofar as the block is given to the method. Keep in mind, just the method have the 'repetition' as many as 0 or 1 time, do not call it liar, because it must be the 'repetition.' In the iterator, you can execute the block by '((|yield|)).' Ah, of course Nothing happens to the metho when the block is given of not evaluating the block internally. I wish you not to disappoint though the error does not occur either. ruby-bdb-0.6.6/bdbxml2/glossary/japanese_(language)000066400000000000000000000005101154714021300221150ustar00rootroot00000000000000 Japanese (language) documentation matz ruby Native language of ((matz)), the author of ((Ruby)). The cause of the poor ((documentation|document)) of ((Ruby)) (according to his excuse). ruby-bdb-0.6.6/bdbxml2/glossary/little_endian000066400000000000000000000006451154714021300211670ustar00rootroot00000000000000 Little Endian byte order data At first there're ten children and decreases one by one. In the computer industry, it is one of the forms when CPU etc. arrange ((data|Data)). A certain CPU maker with very big share is said that they will like Little endian. See also "((byte order|Byte Order))." ruby-bdb-0.6.6/bdbxml2/glossary/local_variable000066400000000000000000000013651154714021300213130ustar00rootroot00000000000000 Local Variable block ruby variable method ((Variable)) which can be referred only within a certain range. The range is called 'Scope'. The scope of ((Ruby)) is among: * The entire program * Class and module definition * ((Method)) definition * ((Block)) and only ((block|Block)) can access the local variable in the outside scope. An effective range of the local variable is from the place where the first substitution in scope appeared to an end of the scope. The effective range is fixed statically, and is unrelated whether actually executed. ruby-bdb-0.6.6/bdbxml2/glossary/main000066400000000000000000000010431154714021300172710ustar00rootroot00000000000000 main self singleton method instance object '((|((self))|))' at top level. Since it can't be without self, it is a mere ((instance|Instance)) of an ((Object)) class, only for being there. Some ((singleton methods|Singleton Method)) are defined to operate the Object class. Defined ((singleton method|Singleton Method)): * private * public * include ruby-bdb-0.6.6/bdbxml2/glossary/matchingdata000066400000000000000000000006351154714021300207770ustar00rootroot00000000000000 MatchingData object variable ((Object)) which shows state concerning match of regular expression. Value of ((variable|Variable)) ((|$~|)). When the value of this variable is changed, the value of variable group (((|$1|)),((|$2|))...,etc) concerning the regular expression changes, too. ruby-bdb-0.6.6/bdbxml2/glossary/matz000066400000000000000000000004211154714021300173170ustar00rootroot00000000000000 matz ruby ((Ruby))'s author His real name is 'Yukihiro Matsumoto.' If you say '((*You-Key-Hero Matz-motor*))' real quick, it sounds like his name. ('tz' as in 'waltz') ruby-bdb-0.6.6/bdbxml2/glossary/method000066400000000000000000000011211154714021300176220ustar00rootroot00000000000000 Method self built-in class receiver object ruby Operation to ((object|Object)). You can refer to the object ((receiver|Receiver)) to be operated with ((self)). In ((Ruby)), if you exclude the object of a ((built-in class|Built-In Class)), since the structure of the object is dynamically determined, the character of a certain object is determined by the method defined in the object. ruby-bdb-0.6.6/bdbxml2/glossary/mix-in000066400000000000000000000012621154714021300175510ustar00rootroot00000000000000 Mix-in function inheritance ruby matz To make a new taste mixing various one with the ice cream. Changed into mix the module with the class, and add the ((function|Function)). See also "((Inheritance))." Multiple ((inheritance|Inheritance)) is not adopted in ((Ruby)). Instead, the inheritance for the is-a relation, and Mix-in for sharing the ((function|Function)) is prepared. The purpose of this is the belief of ((matz)) that the relations should be in chaos when multiple inheritance is abused. ruby-bdb-0.6.6/bdbxml2/glossary/module_function000066400000000000000000000011531154714021300215410ustar00rootroot00000000000000 Module Function singleton method function method In the ((methods|Method)) which is used like ((function|Function)). the one defined both as a method of the module and a ((singleton method|Singleton Method)) is called module function. For instance, most methods of the ((|Math|)) module are the module functions. These methods is convenient because it can be used both in the form(for example):: Math.sqrt(2) and include Math sqrt(2) ruby-bdb-0.6.6/bdbxml2/glossary/non-local_exit000066400000000000000000000020171154714021300212620ustar00rootroot00000000000000 Non-Local Exit object bug exception method ruby Non-local exit (or global exit) is not an escape within the ranges of the ((methods|Method)) such as ((|break|)), ((|next|)), ((|redo|)), ((|retry|)), and ((|return|)), but the type which interrupts going back the hierarchy of the method call as long as it's not caught. In ((Ruby)) there are two way: by ((exception|Exception)), or ((|catch|))/((|throw|)). Almost all exceptions can be caught with '((|rescue|))' (including ((|SystemExit|)) generated by exit), but the exception not significant to catching (example: Fail in memory allocation/interpreter's ((bug|Bug)) does not become the ((object|Object)) to catch. ((|catch|))/((|throw|)) is the one which, when '((|throw|))' is done, jumps at a dash to catch with the same tag as the tag specified. ruby-bdb-0.6.6/bdbxml2/glossary/object000066400000000000000000000012771154714021300176240ustar00rootroot00000000000000 Object awk paradigm object-oriented encapsulation abstract data type A thing. The matter. Love, perhaps, is not an object, but love letter is an object. Whether something is an object or not strongly depends on YOUR philosophy. Might the cause that ((object-oriented|Object-Oriented)) ((paradigm|Paradigm)) is difficult. Someone in the computer industry calls a specific space in computer memory as 'object.' ((Awk|AWK))ward guys... See also "((Encapsulation))," and "((Abstract Data Type))." ruby-bdb-0.6.6/bdbxml2/glossary/object-oriented000066400000000000000000000017321154714021300214270ustar00rootroot00000000000000 Object-Oriented paradigm object japanese inheritance encapsulation polymorphism dynamic binding ((In Japanese|Japanese (language))), an adjective "Object-Oriented" has transcolored to an abstract noun, which means "the ((object|Object))-based ((paradigm|Paradigm))." Any kind of view looks OK at first as long as the object is the central concept, but in general, it seems that the ((paradigm|Paradigm)) needs * ((Inheritance)), * ((Encapsulation)), * and ((Polymorphism)) (or ((Dynamic Binding))). Someone deals it as a wild card or a kind of magic, but our life has a lot more. Twenty-odd years since the dawn, through all our fortunes, there comes to be a first stage of pragmatic use...perhaps...agreed? ruby-bdb-0.6.6/bdbxml2/glossary/object-oriented_analysis000066400000000000000000000002571154714021300233330ustar00rootroot00000000000000 Object-Oriented Analysis object System analysis based on ((object|Object)). ((*OOA*)). ruby-bdb-0.6.6/bdbxml2/glossary/object-oriented_design000066400000000000000000000002531154714021300227550ustar00rootroot00000000000000 Object-Oriented Design object System design based on ((object|Object)). ((*OOD*)). ruby-bdb-0.6.6/bdbxml2/glossary/object-oriented_programming000066400000000000000000000002561154714021300240310ustar00rootroot00000000000000 Object-Oriented Programming object Programming based on ((object|Object)). ((*OOP*)). ruby-bdb-0.6.6/bdbxml2/glossary/override000066400000000000000000000006031154714021300201650ustar00rootroot00000000000000 Override method super redefinition ((Redefinition)). Define a ((method|Method)) same name as the one defined on the super class or included method. In overridden method, '((|((super))|))' can invoke the superior method with same name. ruby-bdb-0.6.6/bdbxml2/glossary/paradigm000066400000000000000000000002351154714021300201330ustar00rootroot00000000000000 Paradigm An affected expression of a 'view.' You tame could use the plain word instead. ruby-bdb-0.6.6/bdbxml2/glossary/perl000066400000000000000000000001551154714021300173120ustar00rootroot00000000000000 Perl Hmm.. Sounds familiar. What was that? ruby-bdb-0.6.6/bdbxml2/glossary/polymorphism000066400000000000000000000010471154714021300211130ustar00rootroot00000000000000 Polymorphism receiver method object ruby To define actual operation as to an ((object|Object)). ((Ruby)) carries it out to choose the ((method|Method) according to the object of the ((receiver|Receiver)). : Example: obj = "abc" print obj.length, "\n" # => 3 obj = [1,2,3,4] print obj.length, "\n" # => 4 ruby-bdb-0.6.6/bdbxml2/glossary/python000066400000000000000000000006631154714021300176750ustar00rootroot00000000000000 Python object-oriented programming ruby matz An ((object-oriented programming|Object-Oriented Programming)) language. ((Ruby))'s rival. "An elapsed serpent." If ((matz)) was content with Python, ((Ruby)) wouldn't be born now. Anxious most is length of the name. (Up to 6 characters!) ruby-bdb-0.6.6/bdbxml2/glossary/receiver000066400000000000000000000010041154714021300201460ustar00rootroot00000000000000 Receiver self variable instance variable method Operational subject of the ((method|Method)). It is on the left of '((|.|))' or '((|::|))' of method call expression. In a method, it can be referred as '((|((self))|)).' The ((instance variable|Instance Variable)) of the receiver is accessible in the form '((|@|))((variable|Variable))_name.' ruby-bdb-0.6.6/bdbxml2/glossary/redefinition000066400000000000000000000002051154714021300210230ustar00rootroot00000000000000 Redefinition override ((Override)). Rewrite. ruby-bdb-0.6.6/bdbxml2/glossary/reference000066400000000000000000000001341154714021300203030ustar00rootroot00000000000000 Reference See also foobar. ruby-bdb-0.6.6/bdbxml2/glossary/ruby000066400000000000000000000007351154714021300173350ustar00rootroot00000000000000 Ruby scripting language object-oriented perl The name of the ((object-oriented|Object-Oriented)) ((scripting language|Scripting Language)) and its interpreter. The name 'ruby' is not an acronym. It's named after the red precious stone, which is the birthsone of July. Notice pearl(((Perl))) is the birthstone of June. ruby-bdb-0.6.6/bdbxml2/glossary/sather000066400000000000000000000006141154714021300176360ustar00rootroot00000000000000 Sather matz object-oriented programming eiffel ruby An ((object-oriented programming|Object-Oriented Programming)) language. ((Matz|matz)) likes Sather rather than ((Eiffel)). But Sather doesn't look like ((Ruby)) at all, either. ruby-bdb-0.6.6/bdbxml2/glossary/script000066400000000000000000000003101154714021300176450ustar00rootroot00000000000000 Script Scenario Turned into a relatively short program where the interpreter works on. Of course there's a super-masterpiece. ruby-bdb-0.6.6/bdbxml2/glossary/scripting_language000066400000000000000000000004011154714021300222070ustar00rootroot00000000000000 Scripting Language script Interpreter which handles batch operations after the ((script|Script)). Man is also a scripting language on the point which reads script. ruby-bdb-0.6.6/bdbxml2/glossary/self000066400000000000000000000010001154714021300172670ustar00rootroot00000000000000 self method receiver smalltalk Expression which refers to ((receiver|Receiver)). Why it's called '((|self|))'? By one account, the ((receiver|Receiver)) is the subject of the sentence where ((method|Method)) is the verb, so from the method's standpoint it's itself, though it is strongly suspected that it's the mimic of ((Smalltalk)) without deep account. ruby-bdb-0.6.6/bdbxml2/glossary/singleton_class000066400000000000000000000002501154714021300215330ustar00rootroot00000000000000 Singleton Class object Virtual class only for the particular ((object|Object)). ruby-bdb-0.6.6/bdbxml2/glossary/singleton_method000066400000000000000000000010001154714021300217000ustar00rootroot00000000000000 Singleton Method override object method ((Method)) which is defined only for the particular ((object|Object)). Singleton method can be succeeded to other method(s) in the following case: * Cloned. * Made subclass(es). When the singleton method ((overrides|Override)) the original method, the original method can be invoked to appear by '((|((super))|))'. ruby-bdb-0.6.6/bdbxml2/glossary/smalltalk000066400000000000000000000006071154714021300203360ustar00rootroot00000000000000 Smalltalk object-oriented paradigm object-oriented programming An ((object-oriented programming|Object-Oriented Programming)) language, which laid the groundwork of the ((paradigm|Paradigm)) to this day, '((object-oriented|Object-Oriented))' style. ruby-bdb-0.6.6/bdbxml2/glossary/sort000066400000000000000000000005001154714021300173310ustar00rootroot00000000000000 Sort ruby To arrange in order ((Ruby)) can sort anything, not only array, however complex, if only * they're countable (((|Enumerable|)) is included), * and the order is (i.e. ((|<=>|)) is) defined in each element. ruby-bdb-0.6.6/bdbxml2/glossary/super000066400000000000000000000013271154714021300175100ustar00rootroot00000000000000 super variable overridde method Technique to call upper level ((method|Method)) from ((overridden|Override)) method. When argument is omitted, super'ed slave can be called by the same argument as that of the master's method. : Question: If you change the value of ((variable|Variable)) given as an argument, which 'super' gets, the original value, or the changed? def foo(a) print a end def self.foo(a) a=25 super end foo(5) # 5 or 25? : Answer the original one(((%5%))) ruby-bdb-0.6.6/bdbxml2/glossary/thread000066400000000000000000000003471154714021300176220ustar00rootroot00000000000000 Thread ruby ((*Thread of control*)), in original; a chain of control processes. In ((Ruby)), more than one thread can exist in a program. ruby-bdb-0.6.6/bdbxml2/glossary/undef000066400000000000000000000010451154714021300174500ustar00rootroot00000000000000 undef inheritance method mix-in To set the ((method|Method)) undefined. '((|undef|))' means that the particular method can be obviated, while ((inheritance|Inheritance)) or ((Mix-in)) just adds class on the method. However, you'll pay for the lack of prudence when you '((|undef|))' the method which is called from inside of the method, which is crucial to the implementation of the class. ruby-bdb-0.6.6/bdbxml2/glossary/variable000066400000000000000000000010321154714021300201300ustar00rootroot00000000000000 Variable local variable global variable instance variable object constant A tag attached to an ((object|Object)). ((Ruby)) has ((global|Global Variable)), ((local|Local Variable)), class, and ((instance|Instance Variable)) variables. ((Constant)) has the same implication of tag, though it's not variable, since its value cannot be changed. ruby-bdb-0.6.6/bdbxml2/myconfig000066400000000000000000000011631154714021300163200ustar00rootroot00000000000000# directories for cpp $base = "#{ENV['HOME']}/local/dbxml" $include = { 'db' => "#{$base}/include", 'dbxml' => "#{$base}/include", 'xercesc' => "#{$base}/include/xercesc", 'xqilla' => "#{$base}/include/xqilla" } # [directory, library] for ld # it's important to have xercesc compiled with -rnone # (i.e. *without* threads) $library = { 'db' => ["#{$base}/lib/", ["db-4.6", "db_cxx-4.6"]], 'dbxml' => ["#{$base}/lib", "dbxml-2.4"], 'xqilla' => ["#{$base}/lib", "xqilla"], 'xercesc' => ["#{$base}/lib", "xerces-c"], } # order for ld (don't change it) $order = ['dbxml', 'db', 'xqilla', 'xercesc'] ruby-bdb-0.6.6/bdbxml2/myconfig-2.2000066400000000000000000000012541154714021300166200ustar00rootroot00000000000000# directories for cpp $base = "#{ENV['HOME']}/local/dbxml" $include = { 'db' => "#{$base}/include", 'dbxml' => "#{$base}/include", 'xercesc' => "#{$base}/include/xercesc", 'xquery' => "#{$base}/include/xquery" } # [directory, library] for ld # it's important to have xercesc compiled with -rnone # (i.e. *without* threads) $library = { 'db' => ["#{$base}/lib/", ["db-4.3", "db_cxx-4.3"]], 'dbxml' => ["#{$base}/lib", "dbxml-2.2"], 'pathan' => ["#{$base}/lib", "pathan"], 'xercesc' => ["#{$base}/lib", "xerces-c"], 'xquery' => ["#{$base}/lib", "xquery-1.2"], } # order for ld (don't change it) $order = ['dbxml', 'db', 'pathan', 'xercesc', 'xquery'] ruby-bdb-0.6.6/bdbxml2/myconfig-2.3000066400000000000000000000012441154714021300166200ustar00rootroot00000000000000# Thanks to "Paul Dlug" # # directories for cpp $base = "#{ENV['HOME']}/local/dbxml" $include = { 'db' => "#{$base}/include", 'dbxml' => "#{$base}/include", 'xercesc' => "#{$base}/include/xercesc", 'xqilla' => "#{$base}/include/xqilla" } # [directory, library] for ld # it's important to have xercesc compiled with -rnone # (i.e. *without* threads) $library = { 'db' => ["#{$base}/lib/", ["db-4.5", "db_cxx-4.5"]], 'dbxml' => ["#{$base}/lib", "dbxml-2.3"], 'xqilla' => ["#{$base}/lib", "xqilla"], 'xercesc' => ["#{$base}/lib", "xerces-c"], } # order for ld (don't change it) $order = ['dbxml', 'db', 'xquilla', 'xercesc'] ruby-bdb-0.6.6/bdbxml2/myconfig-2.4000066400000000000000000000011631154714021300166210ustar00rootroot00000000000000# directories for cpp $base = "#{ENV['HOME']}/local/dbxml" $include = { 'db' => "#{$base}/include", 'dbxml' => "#{$base}/include", 'xercesc' => "#{$base}/include/xercesc", 'xqilla' => "#{$base}/include/xqilla" } # [directory, library] for ld # it's important to have xercesc compiled with -rnone # (i.e. *without* threads) $library = { 'db' => ["#{$base}/lib/", ["db-4.6", "db_cxx-4.6"]], 'dbxml' => ["#{$base}/lib", "dbxml-2.4"], 'xqilla' => ["#{$base}/lib", "xqilla"], 'xercesc' => ["#{$base}/lib", "xerces-c"], } # order for ld (don't change it) $order = ['dbxml', 'db', 'xqilla', 'xercesc'] ruby-bdb-0.6.6/bdbxml2/tests/000077500000000000000000000000001154714021300157235ustar00rootroot00000000000000ruby-bdb-0.6.6/bdbxml2/tests/data.e000066400000000000000000000023421154714021300170030ustar00rootroot00000000000000# Content # BDB::XML::Modify.new("/root",BDB::XML::Modify::InsertBefore,BDB::XML::Modify::Element,"new","") BDB::XML::Modify.new("/root",BDB::XML::Modify::InsertAfter,BDB::XML::Modify::Element,"new","") BDB::XML::Modify.new("/root",BDB::XML::Modify::Remove,BDB::XML::Modify::None,"","") BDB::XML::Modify.new("/root",BDB::XML::Modify::Append,BDB::XML::Modify::Attribute,"","val") BDB::XML::Modify.new("/root",BDB::XML::Modify::Append,BDB::XML::Modify::Attribute,"name","") BDB::XML::Modify.new("/root",BDB::XML::Modify::Append,BDB::XML::Modify::Element,"","val") # Content a contentb content 1 b content 2 # BDB::XML::Modify.new("/root/a/@att1",BDB::XML::Modify::Append,BDB::XML::Modify::Attribute,"name","val") BDB::XML::Modify.new("/root/comment()",BDB::XML::Modify::Append,BDB::XML::Modify::Attribute,"name","val") BDB::XML::Modify.new("/root/a/@att1",BDB::XML::Modify::Append,BDB::XML::Modify::Element,"name","val") BDB::XML::Modify.new("/root/comment()",BDB::XML::Modify::Append,BDB::XML::Modify::Element,"name","val") ruby-bdb-0.6.6/bdbxml2/tests/data.t000066400000000000000000000132671154714021300170320ustar00rootroot00000000000000# Content : an empty root element # # # BDB::XML::Modify.new("/root",BDB::XML::Modify::Append,BDB::XML::Modify::Element,"new","new content") # new content # # BDB::XML::Modify.new("/root",BDB::XML::Modify::Append,BDB::XML::Modify::Attribute,"new","foo") # # # BDB::XML::Modify.new("/root",BDB::XML::Modify::Append,BDB::XML::Modify::PI,"newPI","PIcontent") # # # BDB::XML::Modify.new("/root",BDB::XML::Modify::Append,BDB::XML::Modify::Comment,"","comment content") # # # BDB::XML::Modify.new("/root",BDB::XML::Modify::Append,BDB::XML::Modify::Text,"","text content") # text content # # Content : a little structure. # a content b content 1 b content 2 # # BDB::XML::Modify.new("/root/b/@att1",BDB::XML::Modify::Remove,BDB::XML::Modify::None) # a content b content 1b content 2 # # BDB::XML::Modify.new("/root/b[text()='b content 2']",BDB::XML::Modify::Remove,BDB::XML::Modify::None) # a content b content 1 # # BDB::XML::Modify.new("/root/comment()",BDB::XML::Modify::Remove,BDB::XML::Modify::None) # a content b content 1 b content 2 # # BDB::XML::Modify.new("/root/a/text()",BDB::XML::Modify::Remove,BDB::XML::Modify::None) # b content 1 b content 2 # # BDB::XML::Modify.new("/root",BDB::XML::Modify::Append,BDB::XML::Modify::Element,"new") # a content b content 1 b content 2 # # BDB::XML::Modify.new("/root",BDB::XML::Modify::Append,BDB::XML::Modify::Element,"new","",0) # a content b content 1 b content 2 # # BDB::XML::Modify.new("/root",BDB::XML::Modify::Append,BDB::XML::Modify::Element,"new","",2) # a content b content 1 b content 2 # # BDB::XML::Modify.new("/root/a",BDB::XML::Modify::InsertBefore,BDB::XML::Modify::Element,"new") # a content b content 1 b content 2 # # BDB::XML::Modify.new("/root/a",BDB::XML::Modify::InsertAfter,BDB::XML::Modify::Element,"new") # a content b content 1 b content 2 # # BDB::XML::Modify.new("/root/a",BDB::XML::Modify::Rename,BDB::XML::Modify::None,"x") # a content b content 1 b content 2 # # BDB::XML::Modify.new("/root/a/@att1",BDB::XML::Modify::Rename,BDB::XML::Modify::None,"att2") # a content b content 1 b content 2 # # Content test update # a content 1a content 2 b content 1 # # BDB::XML::Modify.new("/root/comment()",BDB::XML::Modify::Update,BDB::XML::Modify::None,"","new comment") # a content 1a content 2 b content 1 # # BDB::XML::Modify.new("/root/a",BDB::XML::Modify::Update,BDB::XML::Modify::None,"","new a text") # new a text b content 1 # # BDB::XML::Modify.new("/root/a",BDB::XML::Modify::Update,BDB::XML::Modify::None) # b content 1 # # BDB::XML::Modify.new("/root",BDB::XML::Modify::Update,BDB::XML::Modify::None,"","new root text") a content 1a content 2 b content 1 new root text # # BDB::XML::Modify.new("/root/b",BDB::XML::Modify::Update,BDB::XML::Modify::None,"","new b text") # a content 1a content 2 new b text # ruby-bdb-0.6.6/bdbxml2/tests/runit_.rb000066400000000000000000000012441154714021300175510ustar00rootroot00000000000000begin require 'test/unit' rescue LoadError require 'runit/testcase' require 'runit/cui/testrunner' module RUNIT module Assert def assert_raises(error, message = nil) begin yield rescue error assert(true, message) rescue assert_fail("must fail with #{error} : #{string}") else assert_fail("*must* fail : #{string}") end end end end end if RUBY_VERSION > "1.7" class Array alias indices select end class Hash alias indexes select end module BDB class Common alias indexes select end class Recnum alias indices select end end end ruby-bdb-0.6.6/bdbxml2/tests/xml.rb000077500000000000000000000143461154714021300170630ustar00rootroot00000000000000#!/usr/bin/ruby $LOAD_PATH.unshift *%w{../src . tests} $dir = Dir.pwd def clean Dir.foreach('tmp') do |x| if FileTest.file?("tmp/#{x}") File.unlink("tmp/#{x}") end end end at_exit do Dir.chdir($dir) clean() end require 'bdbxml' require 'runit_' $glo, $bdb, $env, $man = nil, nil, nil, nil $time = Time.now.to_s $reference = {"matz" => [], "object" => [], "ruby" => []} clean puts "\nVERSION of BDB is #{BDB::VERSION}\n" puts "\nVERSION of BDB::XML is #{BDB::XML::VERSION}\n" Inh = defined?(RUNIT) ? RUNIT : Test::Unit class TestXML < Inh::TestCase def assert_quote(a, b) a = a.to_s b = b.to_s a.gsub!(/"/, "'") b.gsub!(/"/, "'") assert_equal(a, b) end def test_00_env @flag ||= BDB::INIT_LOMP assert_kind_of(BDB::Env, $env = BDB::Env.new("tmp", BDB::CREATE | @flag)) $man.close if $man assert_kind_of(BDB::XML::Manager, $man = $env.manager) if (@flag & BDB::INIT_TXN) != 0 assert_kind_of(BDB::XML::Container, $glo = $man.create_container("glossary", BDB::XML::TRANSACTIONAL)) else assert_kind_of(BDB::XML::Container, $glo = $man.create_container("glossary")) end assert_equal("glossary", $glo.name) $base = "." end def int_01_doc(man, glo) $id, $names = [], [] @mask ||= "[a-z]" Dir["#{$base}/glossary/#{@mask}*"].each do |file| assert_kind_of(BDB::XML::Document, a = man.create_document) content = IO.readlines(file, nil)[0] $reference.each do |k, v| if content.index("reference>#{k}") v << file end end assert_quote(content, a.content = content) assert_equal(file, a.name = file) assert($time, a['time'] = $time) glo[file] = a $id << file $names << file end end def test_01_doc int_01_doc($man, $glo) end def test_02_each $id.each do |file| assert_kind_of(BDB::XML::Document, doc = $glo[file]) assert_equal(file, doc.name) content = IO.readlines(doc.name, nil)[0] assert_quote(content, doc.content) assert_quote(content, doc.to_s) =begin assert_equal($time, doc['time']) assert_equal($time, doc.get(nil, 'time')) =end end end def test_03_search names = [] $man.query("collection('glossary')/*") do |doc| names << doc.to_document.name end assert_equal($id.sort, names.sort) que = $man.prepare("collection('glossary')/*") assert_kind_of(BDB::XML::Query, que) names = [] que.execute do |doc| names << doc.to_document.name end assert_equal($id.sort, names.sort) assert_equal("collection('glossary')/*", que.to_s) end def int_04_query(man) $reference.each do |k, v| query = man.query("collection('glossary')/entry[reference[contains(text(), '#{k}')]]") file = query.collect {|doc| doc.to_document.name} assert_equal(v.sort, file.sort) end end def test_04_query int_04_query($man) end def test_05_dump assert_equal(nil, $man.close) assert_equal(nil, $env.close) assert_kind_of(BDB::Env, $env = BDB::Env.new("tmp", BDB::INIT_LOMP)) assert_kind_of(BDB::XML::Manager, $man = $env.manager) assert_equal($man, $man.dump("glossary", "tmp/dumpee")) # assert_equal($man, $man.load("glossary", "tmp/dumpee")) assert_equal(nil, $env.close) end def test_07_reinit @flag = BDB::INIT_TRANSACTION @mask = "[a-m]" $reference = {"matz" => [], "object" => [], "ruby" => []} clean test_00_env $man.begin($glo) do |txn, glo| int_01_doc(txn, glo) int_04_query(txn) txn.commit end end def test_08_transaction old_ref = {} $reference.each{|k,v| old_ref[k] = v.dup} $man.begin($glo) do |txn, glo| @mask = "[n-z]" int_01_doc(txn, glo) int_04_query(txn) end $reference = old_ref $man.begin {|txn| int_04_query(txn) } $man.begin($glo) do |txn, glo| @mask = "[n-z]" int_01_doc(txn, glo) int_04_query(txn) txn.commit end $man.begin {|txn| int_04_query(txn) } end def test_09_single $man.close $env.close clean begin Dir.chdir('tmp') $base = ".." $reference.each {|k,v| v.clear} assert_kind_of(BDB::XML::Manager, $man = BDB::XML::Manager.new) assert_kind_of(BDB::XML::Container, $glo = $man.create_container("glossary")) test_01_doc test_02_each test_03_search test_04_query ensure $man.close Dir.chdir("..") end end def expr_modify(man, content, expression, result) doc = man.create_document doc.content = content eval expression assert_equal(result, doc.to_s, expression) end def test_10_modify clean assert_kind_of(BDB::XML::Manager, man = BDB::XML::Manager.new) data = File.new('tests/data.t') begin expression, content, result = nil, nil, nil while line = data.gets next if /\A#\s*\z/ =~ line || /\A\s*\z/ =~ line if /\A#\s*Content/i =~ line while line = data.gets break if /\A#\s*\z/ !~ line end content = line while line = data.gets break if /\A#\s*\z/ =~ line content << line end content.gsub!(/\n/, '') end if /\A#\s*que = / =~ line expression = line.gsub(/\A#\s*/, '') while line = data.gets break if /\A#\s*/ !~ line expression << line.sub(/\A#\s*/, '') end expression<< "mod.execute(doc)" result = line while line = data.gets break if /\A#\s*\z/ =~ line result << line end result.gsub!(/\n/, '') end if result expr_modify(man, content, expression, result) result = nil end end ensure data.close man.close end end end if defined?(RUNIT) RUNIT::CUI::TestRunner.run(TestXML.suite) end ruby-bdb-0.6.6/docs/000077500000000000000000000000001154714021300141575ustar00rootroot00000000000000ruby-bdb-0.6.6/docs/arraylike.rd000066400000000000000000000124721154714021300164770ustar00rootroot00000000000000=begin == Acces Methods These are the methods for ((|BDB::Recnum|)) # module BDB #^ Don't mix these methods with methods of ((|BDB::Cursor|)) #^ ## ## All instance methods has the same syntax than the methods of Array # class Recnum < Common # class << self === Class Methods --- open(name = nil, subname = nil, flags = 0, mode = 0, options = {}) --- create(name = nil, subname = nil, flags = 0, mode = 0, options = {}) --- new(name = nil, subname = nil, flags = 0, mode = 0, options = {}) open the database BDB::Recnum.open(name, subname, flags, mode) is equivalent to BDB::Recno.open(name, subname, flags, mode, "set_flags" => BDB::RENUMBER, "set_array_base" => 0) --- remove(name, subname = nil) --- db_remove(name, subname = nil) --- unlink(name, subname = nil) Removes the database (or subdatabase) represented by the name and subname combination. If no subdatabase is specified, the physical file represented by name is removed, incidentally removing all subdatabases that it contained. --- upgrade(name) --- db_upgrade(name) Upgrade the database # end === Methods ((*All this methods has the same syntax than for the class ((|Array|))*)) --- self[nth] retrieves the ((|nth|)) item from an array. Index starts from zero. If index is the negative, counts backward from the end of the array. The index of the last element is -1. Returns ((|nil|)), if the ((|nth|)) element is not exist in the array. --- self[start..end] returns an array containing the objects from ((|start|)) to ((|end|)), including both ends. if end is larger than the length of the array, it will be rounded to the length. If ((|start|)) is out of an array range , returns ((|nil|)). And if ((|start|)) is larger than end with in array range, returns empty array ([]). --- self[start, length] returns an array containing ((|length|)) items from ((|start|)). Returns ((|nil|)) if ((|length|)) is negative. --- self[nth] = val changes the ((|nth|)) element of the array into ((|val|)). If ((|nth|)) is larger than array length, the array shall be extended automatically. Extended region shall be initialized by ((|nil|)). --- self[start..end] = val replace the items from ((|start|)) to ((|end|)) with ((|val|)). If ((|val|)) is not an array, the type of ((|val|)) will be converted into the Array using ((|to_a|)) method. --- self[start, length] = val replace the ((|length|)) items from ((|start|)) with ((|val|)). If ((|val|)) is not an array, the type of ((|val|)) will be converted into the Array using ((|to_a|)). --- self + other concatenation --- self * times repetition --- self - other substraction --- self & other returns a new array which contains elements belong to both elements. --- self | other join --- self << obj append a new item with value ((|obj|)). Return ((|self|)) --- self <=> other comparison : return -1, 0 or 1 --- clear delete all elements --- collect {|item| ..} Returns a new array by invoking block once for every element, passing each element as a parameter to block. The result of block is used as the given element --- collect! {|item| ..} invokes block once for each element of db, replacing the element with the value returned by block. --- concat(other) append ((|other|)) to the end --- delete(val) delete the item which matches to ((|val|)) --- delete_at(pos) delete the item at ((|pos|)) --- delete_if {|x| ...} delete the item if the block return ((|true|)) --- reject!{|x|...} delete the item if the block return ((|true|)) --- each {|x| ...} iterate over each item --- each_index {|i| ...} iterate over each index --- empty? return ((|true|)) if the db file is empty --- fill(val) set the entire db with ((|val|)) --- fill(val, start[, length]) fill the db with ((|val|)) from ((|start|)) --- fill(val, start..end) set the db with ((|val|)) from ((|start|)) to ((|end|)) --- include?(val) returns true if the given ((|val|)) is present --- index(val) returns the index of the item which equals to ((|val|)). If no item found, returns ((|nil|)) --- indexes(index_1,..., index_n) returns an array consisting of elements at the given indices --- indices(index_1,..., index_n) returns an array consisting of elements at the given indices --- join([sep]) returns a string created by converting each element to a string --- length --- size return the number of elements of the db file --- nitems return the number of non-nil elements of the db file --- pop pops and returns the last value --- push(obj...) appends obj --- replace(other) replaces the contents of the db file with the contents of ((|other|)) --- reverse returns the array of the items in reverse order --- reverse! replaces the items in reverse order. --- reverse_each {|x| ...} iterate over each item in reverse order --- rindex(val) returns the index of the last item which verify ((|item == val|)) --- shift remove and return the first element --- to_a --- to_ary return an ((|Array|)) with all elements --- unshift(obj) insert ((|obj|)) to the front of the db file # end # end =end ruby-bdb-0.6.6/docs/bdb.rb000066400000000000000000000062521154714021300152400ustar00rootroot00000000000000# Berkeley DB is an embedded database system that supports keyed access # to data. # # ............................................................... # # With bdb >= 0.5.5 nil is stored as an empty string (when marshal is # not used). # # Open the database with # # "store_nil_as_null" => true # # if you want the old behavior (nil stored as `\000') # # ............................................................... # # Developers may choose to store data in any of several different # storage structures to satisfy the requirements of a particular # application. In database terminology, these storage structures and the # code that operates on them are called access methods. # # * B+tree: Stores keys in sorted order, using a default function that does # lexicographical ordering of keys. # # * Hashing: Stores records in a hash table for fast searches based # on strict equality, using a default that hashes on the key as a bit # string. Extended Linear Hashing modifies the hash function used by the # table as new records are inserted, in order to keep buckets underfull in # the steady state. # # * Fixed and Variable-Length Records: Stores fixed- or # variable-length records in sequential order. Record numbers may be # immutable, requiring that new records be added only at the end # of the database, or mutable, permitting new records to be inserted # between existing records. # # Berkeley DB environment is an encapsulation of one or more databases, # log files and shared information about the database environment such # as shared memory buffer cache pages. # # The transaction subsystem makes operations atomic, consistent, # isolated, and durable in the face of system and application # failures. The subsystem requires that the data be properly logged and # locked in order to attain these properties. Berkeley DB contains all # the components necessary to transaction-protect the Berkeley DB access # methods and other forms of data may be protected if they are logged # and locked appropriately. # # A database cursor is a sequential pointer to the database entries. It # allows traversal of the database and access to duplicate keyed # entries. Cursors are used for operating on collections of records, # for iterating over a database, and for saving handles to individual # records, so that they can be modified after they have been read. # # The lock subsystem provides interprocess and intraprocess concurrency # control mechanisms. While the locking system is used extensively by # the Berkeley DB access methods and transaction system, it may also be # used as a stand-alone subsystem to provide concurrency control to any # set of designated resources. # # The logging subsystem is the logging facility used by Berkeley DB. It # is largely Berkeley DB specific, although it is potentially useful # outside of the Berkeley DB package for applications wanting # write-ahead logging support. Applications wanting to use the log for # purposes other than logging file modifications based on a set of open # file descriptors will almost certainly need to make source code # modifications to the Berkeley DB code base. module BDB end ruby-bdb-0.6.6/docs/common.rb000066400000000000000000000412261154714021300160010ustar00rootroot00000000000000# Implement common methods for access to data # class BDB::Common class << self #open the database # #* name # The argument name is used as the name of a single physical # file on disk that will be used to back the database. # #* subname # The subname argument allows applications to have # subdatabases, i.e., multiple databases inside of a single physical # file. This is useful when the logical databases are both # numerous and reasonably small, in order to avoid creating a large # number of underlying files. It is an error to attempt to open a # subdatabase in a database file that was not initially # created using a subdatabase name. # #* flags # The flags must be the string "r", "r+", "w", "w+", "a", "a+" or # and integer value. # # The flags value must be set to 0 or by bitwise inclusively # OR'ing together one or more of the following values # # * BDB::CREATE # Create any underlying files, as necessary. If the files # do not already exist and the DB_CREATE flag is not # specified, the call will fail. # # * BD::EXCL # Return an error if the database already exists. Underlying # filesystem primitives are used to implement this # flag. For this reason it is only applicable to the # physical database file and cannot be used to test if a # subdatabase already exists. # # * BDB::NOMMAP # Do not map this database into process memory. # # * BDB::RDONLY # Open the database for reading only. Any attempt to # modify items in the database will fail regardless of the # actual permissions of any underlying files. # # * BDB::TRUNCATE # Physically truncate the underlying database file, # discarding all previous subdatabases or databases. # Underlying filesystem primitives are used to implement # this flag. For this reason it is only applicable to the # physical database file and cannot be used to discard # subdatabases. # # The DB_TRUNCATE flag cannot be transaction protected, # and it is an error to specify it in a transaction # protected environment. # #* options # Hash, Possible options are (see the documentation of Berkeley DB # for more informations) # # * store_nil_as_null: if `true' will store `nil' as `\000', otherwise as an empty string (default `false') # * set_array_base: base index for BDB::Recno, BDB::Queue or BDB::Btree (with BDB::RECNUM). Must be 0 or 1 # * set_bt_compare : specify a Btree comparison function # * set_bt_minkey : set the minimum number of keys per Btree page # * set_bt_prefix : specify a Btree prefix comparison function # * set_cachesize : set the database cache size # * set_dup_compare : specify a duplicate comparison function # * set_store_key : specify a Proc called before a key is stored # * set_fetch_key : specify a Proc called after a key is read # * set_store_value : specify a Proc called before a value is stored # * set_fetch_value : specify a Proc called after a value is read # * set_flags : general database configuration # * set_h_ffactor : set the Hash table density # * set_h_hash : specify a hashing function # * set_h_nelem : set the Hash table size # * set_lorder : set the database byte order # * set_pagesize : set the underlying database page size # * set_re_delim : set the variable-length record delimiter # * set_re_len : set the fixed-length record length # * set_re_pad : set the fixed-length record pad byte # * set_re_source : set the backing Recno text file # * set_append_recno : modify the stored data for BDB::APPEND # * set_encrypt : set the password used # * set_feedback : set the function to monitor some operations # * env : open the database in the environnement given as the value # * txn : open the database in the transaction given as the value # # set_append_recno will be called with (key, value) and # it must return nil or the modified value # # set_encrypt take an Array as arguments with the values # [password, flags], where flags can be 0 or BDB::ENCRYPT_AES # # Proc given to set_bt_compare, set_bt_prefix, # set_dup_compare, set_h_hash, set_store_key # set_fetch_key, set_store_value, set_fetch_value # set_feedback and set_append_recno # can be also specified as a method (replace the prefix set_ # with bdb_) # # For example # # module BDB # class Btreesort < Btree # def bdb_bt_compare(a, b) # b.downcase <=> a.downcase # end # end # end # def open(name = nil, subname = nil, flags = 0, mode = 0, options = {}) end #same than open def create(name = nil, subname = nil, flags = 0, mode = 0, options = {}) end #same than open def new(name = nil, subname = nil, flags = 0, mode = 0, options = {}) end #Removes the database (or subdatabase) represented by the #name and subname combination. # #If no subdatabase is specified, the physical file represented by name #is removed, incidentally removing all subdatabases that it contained. # def remove(name, subname = nil) end #same than remove def db_remove(name, subname = nil) end #same than remove def unlink(name, subname = nil) end #Upgrade the database # def upgrade(name) end #same than upgrade def db_upgrade(name) end end #Returns the value corresponding the key # def [](key) end #associate a secondary index db # #flag can have the value BDB::RDONLY # #The block must return the new key, or Qfalse in this case the #secondary index will not contain any reference to key/value # def associate(db, flag = 0) yield db, key, value end #return the current priority value # def cache_priority end #set the priority value : can be BDB::PRIORITY_VERY_LOW, #BDB::PRIORITY_LOW, BDB::PRIORITY_DEFAULT, #BDB::PRIORITY_HIGH or BDB::PRIORITY_VERY_HIGH # def cache_priority=value end #create a new sequence (see also open_sequence) # #equivalent to #open_sequence(key, BDB::CREATE|BDB::EXCL, init, options) # #return (or yield) an object BDB::Sequence def create_sequence(key, init = nil, options = {}) yield sequence end #create or open a sequence (see BDB::Sequence) # #key : key for the sequence # #flags : flags can have BDB::CREATE, BDB::EXCL, BDB::AUTO_COMMIT, #BDB::THREAD # #init : initial value for the sequence # #options : hash with the possible keys "set_cachesize", #"set_flags" and "set_range" # #return (or yield) an object BDB::Sequence def open_sequence(key, flags = 0, init = nil, options = {}) yield sequence end # #monitor the progress of some operations # def feedback=(proc) end #Returns the value correspondind the key # #flags can have the values BDB::GET_BOTH, #BDB::SET_RECNO or BDB::RMW # #In presence of duplicates it will return the first data item, use ##duplicates if you want all duplicates (see also #each_dup) # def get(key, flags = 0) end #same than get def db_get(key, flags = 0) end #same than get def fetch(key, flags = 0) end #Returns the primary key and the value corresponding to key #in the secondary index # #only with >= 3.3.11 # def pget(key, flags = 0) end #Stores the value associating with key # #If nil is given as the value, the association from the key will be #removed. # def []=(key, value) end #Stores the value associating with key # #If nil is given as the value, the association from the key #will be removed. It return the object deleted or nil if the #specified key don't exist. # #flags can have the value DBD::NOOVERWRITE, in this case #it will return nil if the specified key exist, otherwise true # def put(key, value, flags = 0) end #same than put def db_put(key, value, flags = 0) end #same than put def store(key, value, flags = 0) end #Append the value associating with key # def append(key, value) end #same than append def db_append(key, value) end #Return if the underlying database is in host order # def byteswapped? end #same than byteswapped? def get_byteswapped end #Clear partial set. # def clear_partial end #same than clear_partial def partial_clear end #Closes the file. # def close(flags = 0) end #same than close def db_close(flags = 0) end #Only for Btree and Recno (DB VERSION >= 4.4) # #* start starting point for compaction in a Btree or Recno database. # Compaction will start at the smallest key greater than or equal to the # specified key. # #* stop the stopping point for compaction in a Btree or Recno database. # Compaction will stop at the page with the smallest key greater # than the specified key # #* options hash with the possible keys # # * flags with the value 0, BDB::FREELIST_ONLY, or # BDB::FREE_SPACE # # * compact_fillpercentthe goal for filling pages, specified as a # percentage between 1 and 100. # # * compact_timeout the lock timeout set for implicit transactions, # in microseconds. # def compact(start = nil, stop = nil, options = nil) end #Return the count of duplicate for key # def count(key) end #same than count def dup_count(key) end #Open a new cursor. # def cursor(flags = 0) end #same than cursor def db_cursor(flags = 0) end #Open a new cursor with the flag BDB::WRITECURSOR # def cursor_write() end #same than cursor_write def db_cursor_write(flags = 0) end #Return the subname # def database() end #same than database def subname() end #Removes the association from the key. # #It return the object deleted or nil if the specified #key don't exist. # def delete(key) end #same than delete def db_del(key) end #Deletes associations if the evaluation of the block returns true. # #set # def delete_if(set = nil) yield key, value end #same than delete_if def reject!(set = nil) yield key, value end #Return an array of all duplicate associations for key # #if assoc is false return only the values. # def duplicates(key , assoc = true) end #Iterates over associations. # #set bulk # def each(set = nil, bulk = 0, "flags" => 0) yield key, value end #same than each def each_pair(set = nil, bulk = 0) yield key, value end #iterate over associations, where the key begin with #prefix def each_by_prefix(prefix = nil) yield key, value end #Iterates over each duplicate associations for key # #bulk # def each_dup(key, bulk = 0) yield key, value end #Iterates over each duplicate values for key # #bulk # def each_dup_value(key, bulk = 0) yield value end #Iterates over keys. # #set bulk # def each_key(set = nil, bulk = 0) yield key end #Iterates over secondary indexes and give secondary key, primary key #and value # def each_primary(set = nil) yield skey, pkey, pvalue end #Iterates over values. # #set bulk # def each_value(set = nil, bulk = 0) yield value end #Returns true if the database is empty. # def empty?() end #Return the name of the file # def filename() end #Returns true if the association from the key exists. # def has_key?(key) end #same than has_key? def key?(key) end #same than has_key? def include?(key) end #same than has_key? def member?(key) end #Returns true if the association from key is value # def has_both?(key, value) end #same than has_both? def both?(key, value) end #Returns true if the association to the value exists. # def has_value?(value) end #same than has_value? def value?(value) end #Returns the first key associated with value # def index(value) end #Returns the keys associated with value1, value2, ... # def indexes(value1, value2, ) end #Perform a join. cursor is an array of BDB::Cursor # def join(cursor , flag = 0) yield key, value end #Returns the array of the keys in the database # def keys end #Returns the number of association in the database. # def length end #same than length def size end # #The log_register function registers a file name. # def log_register(name) end # #The log_unregister function unregisters a file name. # def log_unregister() end #Create an hash without the associations if the evaluation of the #block returns true. # def reject yield key, value end #Iterates over associations in reverse order # #set # def reverse_each(set = nil) yield key, value end #same than reverse_each def reverse_each_pair(set = nil) yield key, value end #iterate over associations in reverse order, where the key begin with #prefix def reverse_each_by_prefix(prefix = nil) yield key, value end #Iterates over keys in reverse order # #set # def reverse_each_key(set = nil) yield key end #Iterates over secondary indexes in reverse order and give secondary #key, primary key and value # def reverse_each_primary(set = nil) yield skey, pkey, pvalue end #Iterates over values in reverse order. # #set # def reverse_each_value(set = nil) yield value end #Set the partial value len and offset # def set_partial(len, offset) end #Return database statistics. # def stat end #Return an array of all associations [key, value] # def to_a end #Return an hash of all associations {key => value} # def to_hash end #Empty a database # def truncate end #same than truncate def clear end #Returns the array of the values in the database. # def values end #Verify the integrity of the DB file, and optionnally output the #key/data to file (file must respond to #to_io) # def verify(file = nil, flags = 0) end end ruby-bdb-0.6.6/docs/comxxx.rb000066400000000000000000000254221154714021300160370ustar00rootroot00000000000000# Implementation of a sorted, balanced tree structure # # Inherit from BDB::Common # class BDB::Btree < BDB::Common # Return an Hash with the fields (description for 4.0.14) # * bt_magic : Magic number that identifies the file as a Btree database. # * bt_version : The version of the Btree database. # * bt_nkeys : the number of unique keys in the database. # * bt_ndata : the number of key/data pairs in the database. # * bt_pagesize : Underlying database page size, in bytes. # * bt_minkey : The minimum keys per page. # * bt_re_len : The length of fixed-length records. # * bt_re_pad : The padding byte value for fixed-length records. # * bt_levels : Number of levels in the database. # * bt_int_pg : Number of database internal pages. # * bt_leaf_pg : Number of database leaf pages. # * bt_dup_pg : Number of database duplicate pages. # * bt_over_pg : Number of database overflow pages. # * bt_free : Number of pages on the free list. # * bt_int_pgfree : Number of bytes free in database internal pages. # * bt_leaf_pgfree : Number of bytes free in database leaf pages. # * bt_dup_pgfree : Number of bytes free in database duplicate pages. # * bt_over_pgfree : Number of bytes free in database overflow pages. def stat(flags = 0) end end # Implementation of Extended Linear Hashing # # Inherit from BDB::Common # class BDB::Hash < BDB::Common # Return an Hash with the fields (description for 4.0.14) # * hash_magic : Magic number that identifies the file as a Hash file. # * hash_version : The version of the Hash database. # * hash_nkeys : The number of unique keys in the database. # * hash_ndata : The number of key/data pairs in the database. # * hash_pagesize : The underlying Hash database page (and bucket) size, in bytes. # * hash_nelem : The estimated size of the hash table specified at database-creation time. # * hash_ffactor : The desired fill factor (number of items per bucket) specified at database-creation time. # * hash_buckets : The number of hash buckets. # * hash_free : The number of pages on the free list. # * hash_bfree :The number of bytes free on bucket pages. # * hash_bigpages : The number of big key/data pages. # * hash_big_bfree : The number of bytes free on big item pages. # * hash_overflows : The number of overflow pages # * hash_ovfl_free : The number of bytes free on overflow pages. # * hash_dup : The number of duplicate pages. # * hash_dup_free : The number of bytes free on duplicate pages. def stat(flags = 0) end end # Stores both fixed and variable-length records with logical record # numbers as keys # # Inherit from BDB::Common # class BDB::Recno < BDB::Common #Removes and returns an association from the database. # def shift end # Return an Hash with the fields (description for 4.0.14) # * bt_magic : Magic number that identifies the file as a Btree database. # * bt_version : The version of the Btree database. # * bt_nkeys : The exact number of records in the database. # * bt_ndata : The exact number of records in the database. # * bt_pagesize : Underlying database page size, in bytes. # * bt_minkey : The minimum keys per page. # * bt_re_len : The length of fixed-length records. # * bt_re_pad : The padding byte value for fixed-length records. # * bt_levels : Number of levels in the database. # * bt_int_pg : Number of database internal pages. # * bt_leaf_pg : Number of database leaf pages. # * bt_dup_pg : Number of database duplicate pages. # * bt_over_pg : Number of database overflow pages. # * bt_free : Number of pages on the free list. # * bt_int_pgfree : Number of bytes free in database internal pages. # * bt_leaf_pgfree : Number of bytes free in database leaf pages. # * bt_dup_pgfree : Number of bytes free in database duplicate pages. # * bt_over_pgfree : Number of bytes free in database overflow pages. def stat(flags = 0) end end # Stores fixed-length records with logical record numbers as keys. # It is designed for fast inserts at the tail and has a special cursor # consume operation that deletes and returns a record from the head of # the queue # # Inherit from BDB::Common # class BDB::Queue < BDB::Common #Push the values # def push values end #Removes and returns an association from the database. # def shift end # Return an Hash with the fields (description for 4.0.14) # * qs_magic : Magic number that identifies the file as a Queue file. # * qs_version : The version of the Queue file type. # * qs_nkeys : The number of records in the database. # * qs_ndata : The number of records in the database. # * qs_pagesize : Underlying database page size, in bytes. # * qs_extentsize : Underlying database extent size, in pages. # * qs_pages : Number of pages in the database. # * qs_re_len : The length of the records. # * qs_re_pad : The padding byte value for the records. # * qs_pgfree : Number of bytes free in database pages. # * qs_first_recno : First undeleted record in the database. # * qs_cur_recno : Last allocated record number in the database. def stat(flags = 0) end end # Don't mix these methods with methods of BDB::Cursor # # All instance methods has the same syntax than the methods of Array # #BDB::Recnum.open(name, subname, flags, mode) # #is equivalent to # #BDB::Recno.open(name, subname, flags, mode, #"set_flags" => BDB::RENUMBER, "set_array_base" => 0) # # Inherit from BDB::Common class BDB::Recnum < BDB::Common #Element reference - with the following syntax # #self[nth] # #retrieves the nth item from an array. Index starts from zero. #If index is the negative, counts backward from the end of the array. #The index of the last element is -1. Returns nil, if the nth #element is not exist in the array. # #self[start..end] # #returns an array containing the objects from start to end, #including both ends. if end is larger than the length of the array, #it will be rounded to the length. If start is out of an array #range , returns nil. #And if start is larger than end with in array range, returns #empty array ([]). # #self[start, length] # #returns an array containing length items from start. #Returns nil if length is negative. # def [](args) end #Element assignement -- with the following syntax # #self[nth] = val # #changes the nth element of the array into val. #If nth is larger than array length, the array shall be extended #automatically. Extended region shall be initialized by nil. # #self[start..end] = val # #replace the items from start to end with val. #If val is not an array, the type of val will be #converted into the Array using to_a method. # #self[start, length] = val # #replace the length items from start with val. #If val is not an array, the type of val will be #converted into the Array using to_a. # def []=(args, val) end #concatenation # def +(other) end #repetition # def *(times) end #substraction # def -(other) end #returns a new array which contains elements belong to both elements. # def &(other) end #join # def |(other) end #append a new item with value obj. Return self # def <<(obj) end #comparison : return -1, 0 or 1 # def <=>(other) end #delete all elements # def clear end #Returns a new array by invoking block once for every element, #passing each element as a parameter to block. The result of block #is used as the given element # def collect yield item end #invokes block once for each element of db, replacing the element #with the value returned by block. # def collect! yield item end #append other to the end # def concat(other) end #delete the item which matches to val # def delete(val) end #delete the item at pos # def delete_at(pos) end #delete the item if the block return true # def delete_if yield x end #delete the item if the block return true # def reject! yield x end #iterate over each item # def each yield x end #iterate over each index # def each_index yield i end #return true if the db file is empty # def empty? end #set the entire db with val # def fill(val) end #fill the db with val from start # def fill(val, start[, length]) end #set the db with val from start to end # def fill(val, start..end) end #returns true if the given val is present # def include?(val) end #returns the index of the item which equals to val. #If no item found, returns nil # def index(val) end #returns an array consisting of elements at the given indices # def indexes(index_1,..., index_n) end #returns an array consisting of elements at the given indices # def indices(index_1,..., index_n) end #returns a string created by converting each element to a string # def join([sep]) end #return the number of elements of the db file # def length end #same than length def size end #return the number of non-nil elements of the db file # def nitems end #pops and returns the last value # def pop end #appends obj # def push(obj, ...) end #replaces the contents of the db file with the contents of other # def replace(other) end #returns the array of the items in reverse order # def reverse end #replaces the items in reverse order. # def reverse! end #iterate over each item in reverse order # def reverse_each yield x end #returns the index of the last item which verify item == val # def rindex(val) end #remove and return the first element # def shift end #return an Array with all elements # def to_a end #same than to_a def to_ary end #insert obj to the front of the db file # def unshift(obj) end end ruby-bdb-0.6.6/docs/cursor.rb000066400000000000000000000075731154714021300160350ustar00rootroot00000000000000# A database cursor is a sequential pointer to the database entries. It # allows traversal of the database and access to duplicate keyed # entries. Cursors are used for operating on collections of records, # for iterating over a database, and for saving handles to individual # records, so that they can be modified after they have been read. # # A cursor is created with the methods BDB::Common#cursor and # BDB::Common#cursor_write # class BDB::Cursor #Discards the cursor. # def close() end #same than close def c_close() end #Return the count of duplicate # def count() end #same than count def c_count() end #Same than get(BDB::CURRENT) # def current() end #same than current def c_current() end #Deletes the key/data pair currently referenced by the cursor. # def del() end #same than del def delete() end #same than del def c_del() end #Creates new cursor that uses the same transaction and locker ID as #the original cursor. This is useful when an application is using #locking and requires two or more cursors in the same thread of #control. # #flags can have the value BDB::DB_POSITION, in this case the #newly created cursor is initialized to reference the same position in #the database as the original cursor and hold the same locks. # def dup(flags = 0) end #same than dup def clone(flags = 0) end #same than dup def c_dup(flags = 0) end #same than dup def c_clone(flags = 0) end #Same than get(BDB::FIRST) # def first() end #same than first def c_first() end #Retrieve key/data pair from the database # #See the description of c_get in the Berkeley distribution #for the different values of the flags parameter. # #key must be given if the flags parameter is #BDB::SET | BDB::SET_RANGE | BDB::SET_RECNO # #key and value must be specified for BDB::GET_BOTH # def get(flags, key = nil, value = nil) end #same than get def c_get(flags, key = nil, value = nil) end #Same than get(BDB::LAST) # def last() end #same than last def c_last() end #Same than get(BDB::NEXT) # def next() end #same than next def c_next() end #Retrieve key/primary key/data pair from the database # def pget(flags, key = nil, value = nil) end #same than pget def c_pget(flags, key = nil, value = nil) end #Same than get(BDB::PREV) # def prev() end #same than prev def c_prev() end #Stores data value into the database. # #See the description of c_put in the Berkeley distribution #for the different values of the flags parameter. # def put(flags, value) end #same than put def c_put(flags, value) end #Stores key/data pairs into the database (only for Btree and Hash #access methods) # #flags must have the value BDB::KEYFIRST or #BDB::KEYLAST # def put(flags, key, value) end #same than put def c_put(flags, key, value) end #Same than get with the flags BDB::SET or BDB::SET_RANGE #or BDB::SET_RECNO # def set(key) end #same than set def c_set(key) end #same than set def set_range(key) end #same than set def c_set_range(key) end #same than set def set_recno(key) end #same than set def c_set_recno(key) end end ruby-bdb-0.6.6/docs/cursor.rd000066400000000000000000000061071154714021300160270ustar00rootroot00000000000000=begin == Cursor operation A database cursor is a sequential pointer to the database entries. It allows traversal of the database and access to duplicate keyed entries. Cursors are used for operating on collections of records, for iterating over a database, and for saving handles to individual records, so that they can be modified after they have been read. # module BDB ## A database cursor is a sequential pointer to the database entries. It ## allows traversal of the database and access to duplicate keyed ## entries. Cursors are used for operating on collections of records, ## for iterating over a database, and for saving handles to individual ## records, so that they can be modified after they have been read. # class Cursor See also iterators in (()) === Methods --- close() --- c_close() Discards the cursor. --- count() --- c_count() Return the count of duplicate --- current() --- c_current() Same than (({get(BDB::CURRENT)})) --- del() --- delete() --- c_del() Deletes the key/data pair currently referenced by the cursor. --- dup(flags = 0) --- clone(flags = 0) --- c_dup(flags = 0) --- c_clone(flags = 0) Creates new cursor that uses the same transaction and locker ID as the original cursor. This is useful when an application is using locking and requires two or more cursors in the same thread of control. ((|flags|)) can have the value ((|BDB::DB_POSITION|)), in this case the newly created cursor is initialized to reference the same position in the database as the original cursor and hold the same locks. --- first() --- c_first() Same than (({get(BDB::FIRST)})) --- get(flags, key = nil, value = nil) --- c_get(flags, key = nil, value = nil) Retrieve key/data pair from the database See the description of (({c_get})) in the Berkeley distribution for the different values of the ((|flags|)) parameter. ((|key|)) must be given if the ((|flags|)) parameter is ((|BDB::SET|)) | ((|BDB::SET_RANGE|)) | ((|BDB::SET_RECNO|)) ((|key|)) and ((|value|)) must be specified for ((|BDB::GET_BOTH|)) --- last() --- c_last() Same than (({get(BDB::LAST)})) --- next() --- c_next() Same than (({get(BDB::NEXT)})) --- pget(flags, key = nil, value = nil) --- c_pget(flags, key = nil, value = nil) Retrieve key/primary key/data pair from the database --- prev() --- c_prev() Same than (({get(BDB::PREV)})) --- put(flags, value) --- c_put(flags, value) Stores data value into the database. See the description of (({c_put})) in the Berkeley distribution for the different values of the ((|flags|)) parameter. --- put(flags, key, value) --- c_put(flags, key, value) Stores key/data pairs into the database (only for Btree and Hash access methods) ((|flags|)) must have the value ((|BDB::KEYFIRST|)) or ((|BDB::KEYLAST|)) --- set(key) --- c_set(key) --- set_range(key) --- c_set_range(key) --- set_recno(key) --- c_set_recno(key) Same than (({get})) with the flags ((|BDB::SET|)) or ((|BDB::SET_RANGE|)) or ((|BDB::SET_RECNO|)) # end # end =end ruby-bdb-0.6.6/docs/env.rb000066400000000000000000000454331154714021300153050ustar00rootroot00000000000000# Berkeley DB environment is an encapsulation of one or more databases, # log files and shared information about the database environment such # as shared memory buffer cache pages. # # The simplest way to administer a Berkeley DB application environment # is to create a single home directory that stores the files for the # applications that will share the environment. The environment home # directory must be created before any Berkeley DB applications are run. # Berkeley DB itself never creates the environment home directory. The # environment can then be identified by the name of that directory. class BDB::Env class << self #open the Berkeley DB environment # #* home # If this argument is non-NULL, its value may be used as the # database home, and files named relative to its path. # #* mode # mode for creation (see chmod(2)) # #* flags # must be set to 0 or by OR'ing with # # * BDB::INIT_CDB Initialize locking. # * BDB::INIT_LOCK Initialize the locking subsystem. # * BDB::INIT_LOG Initialize the logging subsystem. # * BDB::INIT_MPOOL Initialize the shared memory buffer pool subsystem. # * BDB::INIT_TXN Initialize the transaction subsystem. # * BDB::INIT_TRANSACTION # Equivalent to DB_INIT_LOCK|DB_INIT_MPOOL|DB_INIT_TXN|DB_INIT_LOG # * BDB::RECOVER # Run normal recovery on this environment before opening it for normal # use. If this flag is set, the DB_CREATE flag must also be set since # the regions will be removed and recreated. # # * BDB::RECOVER_FATAL # Run catastrophic recovery on this environment before opening # it for normal use. If this flag is set, the DB_CREATE flag # must also be set since the regions will be removed and recreated. # # * BDB::USE_ENVIRON # The Berkeley DB process' environment may be permitted to # specify information to be used when naming files # # * BDB::USE_ENVIRON_ROOT # The Berkeley DB process' environment may be permitted to # specify information to be used when naming files; # if the DB_USE_ENVIRON_ROOT flag is set, environment # information will be used for file naming only for users with # appropriate permissions # # * BDB::CREATE # Cause Berkeley DB subsystems to create any underlying # files, as necessary. # # * BDB::LOCKDOWN # Lock shared Berkeley DB environment files and memory mapped # databases into memory. # # * BDB::NOMMAP # Always copy read-only database files in this environment # into the local cache instead of potentially mapping # them into process memory # # * BDB::PRIVATE # Specify that the environment will only be accessed by a # single process # # * BDB::SYSTEM_MEM # Allocate memory from system shared memory instead of from # memory backed by the filesystem. # # * BDB::TXN_NOSYNC # Do not synchronously flush the log on transaction commit or # prepare. This means that transactions exhibit the # ACI (atomicity, consistency and isolation) properties, but not # D (durability), i.e., database integrity will # be maintained but it is possible that some number of the # most recently committed transactions may be undone # during recovery instead of being redone. # # * BDB::CDB_ALLDB # For Berkeley DB Concurrent Data Store applications, perform # locking on an environment-wide basis rather than per-database. # #* options # Hash, Possible options are (see the documentation of Berkeley DB # for more informations) # # * set_app_dispatch : configure application recovery interface (DB >= 4.1) # * set_cachesize : set the database cache size # * set_data_dir : set the environment data directory (DB >= 3) # * set_encrypt : set the environment cryptographic key (DB >= 4.1) # * set_feedback : set feedback callback (DB >= 3) # * set_flags : environment configuration (DB >= 3.2) # * set_lg_bsize : set log buffer size (DB >= 3) # * set_lg_dir : set the environment logging directory (DB >= 3) # * set_lg_max : set log file size # * set_lg_regionmax : set logging region size (DB >= 3) # * set_lk_conflicts : set lock conflicts matrix (DB >= 3) # * set_lk_detect : set automatic deadlock detection # * set_lk_max_lockers : set maximum number of lockers # * set_lk_max_locks : set maximum number of locks # * set_lk_max_objects : set maximum number of lock objects # * set_rep_transport : configure replication transport (DB >= 4) # * set_rep_limit : limit data sent in response to a single message (DB >= 4.1) # * set_rep_nsites : configure replication group site count (DB >= 4.5) # * set_rep_priority : configure replication site priority (DB >= 4.5) # * set_rep_config : configure the replication subsystem (DB >= 4.5) # * set_rep_timeout : configure replication timeouts (DB >= 4.5) # * set_rpc_server : establish an RPC server connection (DB >= 3.1) # * set_tas_spins : set the number of test-and-set spins (DB >= 3) # * set_tmp_dir : set the environment temporary file directory (DB >= 3) # * set_timeout : set lock and transaction timeout (DB >= 4) # * set_tx_max : set maximum number of transactions (DB >= 3) # * set_tx_timestamp : set recovery timestamp (DB >= 3.1) # * set_verbose : set verbose messages # * set_verb_chkpoint :display checkpoint location information when searching the log for checkpoints. (DB >= 3) # * set_verb_deadlock : display additional information when doing deadlock detection. (DB >= 3) # * set_verb_recovery : display additional information when performing recovery. (DB >= 3) # * set_verb_replication : display additional information when processing replication messages. (DB >= 4) # * set_verb_waitsfor : display the waits-for table when doing deadlock detection. (DB >= 3) # # Proc given to set_feedback, set_app_dispatch and # set_rep_transport can be also specified as a method # (replace the prefix set_ with bdb_) # # For bdb_rep_transport the constant ENVID must be defined # # The constant BDB::ENCRYPT can be used to replace set_encrypt # def open(home, flags = 0, mode = 0, options = {}) end #same than open def create(home, flags = 0, mode = 0, options = {}) end #same than open def new(home, flags = 0, mode = 0, options = {}) end #remove the environnement # def remove() end #same than remove def unlink() end end #close the environnement # def close() end #only with BDB::VERSION_MAJOR == 4 && BDB::VERSION_MINOR >= 1 # #remove the database specified by file and database. If no #database is nil, the underlying file represented by #file is removed, incidentally removing all databases #that it contained. # #The flags value must be set to 0 or BDB::AUTO_COMMIT # def dbremove(file, database = nil, flags = 0) end #only with BDB::VERSION_MAJOR == 4 && BDB::VERSION_MINOR >= 1 # #rename the database specified by file and database to #newname. If database is nil, the underlying file #represented by file is renamed, incidentally renaming all databases #that it contained. # #The flags value must be set to 0 or BDB::AUTO_COMMIT # def dbrename(file, database, newname, flags = 0) end #monitor the progress of some operations # def feedback=(proc) end #return the name of the directory # def home() end #Acquire a locker ID # def lock() end #same than lock def lock_id() end #The lock_detect function runs one iteration of the deadlock #detector. The deadlock detector traverses the lock table, and for each #deadlock it finds, marks one of the participating transactions for #abort. # #type can have one the value BDB::LOCK_OLDEST, #BDB::LOCK_RANDOM or BDB::LOCK_YOUNGUEST # #flags can have the value BDB::LOCK_CONFLICT, in this case #the deadlock detector is run only if a lock conflict has occurred #since the last time that the deadlock detector was run. # #return the number of transactions aborted by the lock_detect function #if BDB::VERSION_MAJOR >= 3 or zero # def lock_detect(type, flags = 0) end #Return lock subsystem statistics # # def lock_stat() end #The log_archive function return an array of log or database file names. # #flags value must be set to 0 or the value BDB::ARCH_DATA, #BDB::ARCH_ABS, BDB::ARCH_LOG # def log_archive(flags = 0) end # #same as log_put(string, BDB::CHECKPOINT) # def log_checkpoint(string) end # #same as log_put(string, BDB::CURLSN) # def log_curlsn(string) end # #Implement an iterator inside of the log # def log_each yield string, lsn end # #same as log_put(string, BDB::FLUSH) # #Without argument, garantee that all records are written to the disk # def log_flush(string = nil) end # #The log_get return an array [String, BDB::Lsn] according to #the flag value. # #flag can has the value BDB::CHECKPOINT, BDB::FIRST, #BDB::LAST, BDB::NEXT, BDB::PREV, BDB::CURRENT # def log_get(flag) end # #The log_put function appends records to the log. It return #an object BDB::Lsn # #flag can have the value BDB::CHECKPOINT, BDB::CURLSN, #BDB::FLUSH # def log_put(string, flag = 0) end # #Implement an iterator inside of the log # def log_reverse_each yield string, lsn end # #return log statistics # def log_stat end #open the database in the current environment. type must be one of #the constant BDB::BTREE, BDB::HASH, BDB::RECNO, #BDB::QUEUE. See open for other #arguments # def open_db(type, name = nil, subname = nil, flags = 0, mode = 0) end #only with BDB::VERSION_MAJOR == 3 && BDB::VERSION_MINOR >= 3 # #iterate over all prepared transactions. The transaction txn #must be made a call to #abort, #commit, #discard # #id is the global transaction ID for the transaction # def recover yield txn, id end #only with BDB::VERSION_MAJOR == 3 && BDB::VERSION_MINOR >= 2 # #flags can have the value BDB::CDB_ALLDB, BDB::NOMMAP #BDB::TXN_NOSYNC # #if onoff is false, the specified flags are cleared # # def set_flags(flags, onoff = true) end #begin a transaction (the transaction manager must be enabled). flags #can have the value DBD::TXN_COMMIT, in this case the transaction #will be commited at end. # def begin(flags = 0) end #same than begin def txn_begin(flags = 0) end #The txn_checkpoint function flushes the underlying memory pool, #writes a checkpoint record to the log and then flushes the log. # #If either kbyte or min is non-zero, the checkpoint is only done #if more than min minutes have passed since the last checkpoint, or if #more than kbyte kilobytes of log data have been written since the last #checkpoint. # def checkpoint(kbyte, min = 0) end #same than checkpoint def txn_checkpoint(kbyte, min = 0) end #Return transaction subsystem statistics # # def stat() end #same than stat def txn_stat() end #Only for DB >= 4 # #Holds an election for the master of a replication group, returning the #new master's ID # #Raise BDB::RepUnavail if the timeout expires # def elect(sites, priority, timeout) end #same than elect def rep_elect(sites, priority, timeout) end #Only for DB >= 4 # #Processes an incoming replication message sent by a member of the #replication group to the local database environment # def process_message(control, rec, envid) end #same than process_message def rep_process_message(control, rec, envid) end #Only for DB >= 4 # #cdata is an identifier #flags must be one of BDB::REP_CLIENT, BDB::REP_MASTER #or BDB::REP_LOGSONLY # def start(cdata, flags) end #same than start def rep_start(cdata, flags) end #Only for DB >= 4.4 # #Reset database file LSN # #The Env#lsn_reset method allows database files to be moved from one transactional #database environment to another. # #fileThe name of the physical file in which the LSNs are to be cleared. #flags must be set to 0 or BDB::ENCRYPT # def lsn_reset(file, flags = 0) end #Only for DB >= 4.4 # #Reset database file ID # #The Env#fileid_reset method allows database files to be copied, and then the copy #used in the same database environment as the original. # #fileThe name of the physical file in which new file IDs are to be created. #flags must be set to 0 or BDB::ENCRYPT # def fileid_reset(file, flags = 0) end #Only for DB >= 4.4 # #There are interfaces in the Berkeley DB library which either directly output informational #messages or statistical information : Env#msgcall is used to set callback which will #called by BDB # #The value given must be nil to unconfigure the callback, or and object #which respond to #call : it will called with a String as argument # def msgcall=(call_proc) end #Only for DB >= 4.4 # #Declare a proc object which returns a unique identifier pair for the current #thread of control. # #The proc must return a pair # *pid: process ID of the current thread # *tid: thread ID of the current thread # def thread_id=(call_proc) end #Only for DB >= 4.4 # #Declare a proc that formats a process ID and thread ID identifier pair for display. # #The proc will be called with 2 arguments and must return a String # def thread_id_string=(call_proc) end #Only for DB >= 4.4 # #Declare a proc that returns if a thread of control (either a true thread or #a process) is still running. # #The proc will be called with 2 arguments (pid, tid) # def is_alive=(call_proc) end #Only for DB >= 4.4 # #The method checks for threads of control (either a true #thread or a process) that have exited while manipulating Berkeley DB library #data structures # #flag is actually unused and must be set to 0 # def failcheck(flag = 0) end #Only for DB >= 4.5 # #Adds a new replication site to the replication manager's list of known sites. # #Return the environment ID assigned to the remote site def repmgr_add_remote(host, port, flag = 0) end #Only for DB >= 4.5 # #Specifies how master and client sites will handle acknowledgment of replication #messages which are necessary for "permanent" records. # #policy must be set to one of the following values #BDB::REPMGR_ACKS_ALL, BDB::REPMGR_ACKS_ALL_PEERS, #BDB::REPMGR_ACKS_NONE, BDB::REPMGR_ACKS_ONE, #BDB::REPMGR_ACKS_ONE_PEER, BDB::REPMGR_ACKS_QUORUM def repmgr_ack_policy=(policy) end #Only for DB >= 4.5 # #Returns the replication manager's client acknowledgment policy. def repmgr_ack_policy end #Only for DB >= 4.5 # #Returns an array with the status of the sites currently known by the #replication manager. def repmgr_site_list end #Only for DB >= 4.5 # #Specifies the host identification string and port number for the local system. def repmgr_set_local_site(host, port, flag = 0) end #Only for DB >= 4.5 # #Starts the replication manager. def repmgr_start(count, flag) end #Only for DB >= 4.5 # #Configures the Berkeley DB replication subsystem. # #which can have the value BDB::REP_CONF_BULK, #BDB::REP_CONF_DELAYCLIENT, BDB::REP_CONF_NOAUTOINIT, #BDB::REP_CONF_NOWAIT # #onoff can have the value true or false def rep_config[]=(which, onoff) end #Only for DB >= 4.5 # #Returns true if the specified which parameter is currently set or not. def rep_config?[](which) end #Only for DB >= 4.5 # #Specifies the total number of sites in a replication group. def rep_nsites=(sites) end #Only for DB >= 4.5 # #Returns the total number of sites in a replication group. def rep_nsites end #Only for DB >= 4.5 # #Specifies the priority in the replication group elections. def rep_priority=(priority) end #Only for DB >= 4.5 # #Returns the database environment priority. def rep_priority end #Only for DB >= 4.5 # #Specifies the timeout in the replication group elections. # #which can have the value BDB::REP_ACK_TIMEOUT, #BDB::REP_ELECTION_TIMEOUT, BDB::REP_ELECTION_RETRY, #BDB::REP_CONNECTION_RETRY def rep_timeout[]=(which, timeout) end #Only for DB >= 4.5 # #Returns the database environment timeout for which def rep_timeout[](which) end end ruby-bdb-0.6.6/docs/env.rd000066400000000000000000000425661154714021300153130ustar00rootroot00000000000000=begin == BDB::Env Berkeley DB environment is an encapsulation of one or more databases, log files and shared information about the database environment such as shared memory buffer cache pages. The simplest way to administer a Berkeley DB application environment is to create a single home directory that stores the files for the applications that will share the environment. The environment home directory must be created before any Berkeley DB applications are run. Berkeley DB itself never creates the environment home directory. The environment can then be identified by the name of that directory. * (()) * (()) # module BDB ## Berkeley DB environment is an encapsulation of one or more databases, ## log files and shared information about the database environment such ## as shared memory buffer cache pages. ## ## The simplest way to administer a Berkeley DB application environment ## is to create a single home directory that stores the files for the ## applications that will share the environment. The environment home ## directory must be created before any Berkeley DB applications are run. ## Berkeley DB itself never creates the environment home directory. The ## environment can then be identified by the name of that directory. # class Env # class << self === Class Methods --- open(home, flags = 0, mode = 0, options = {}) --- create(home, flags = 0, mode = 0, options = {}) --- new(home, flags = 0, mode = 0, options = {}) open the Berkeley DB environment : ((|home|)) If this argument is non-NULL, its value may be used as the database home, and files named relative to its path. : ((|mode|)) mode for creation (see chmod(2)) : ((|flags|)) must be set to 0 or by OR'ing with : ((|BDB::INIT_CDB|)) Initialize locking. : ((|BDB::INIT_LOCK|)) Initialize the locking subsystem. : ((|BDB::INIT_LOG|)) Initialize the logging subsystem. : ((|BDB::INIT_MPOOL|)) Initialize the shared memory buffer pool subsystem. : ((|BDB::INIT_TXN|)) Initialize the transaction subsystem. : ((|BDB::INIT_TRANSACTION|)) Equivalent to ((|DB_INIT_LOCK | DB_INIT_MPOOL | DB_INIT_TXN | DB_INIT_LOG|)) : ((|BDB::RECOVER|)) Run normal recovery on this environment before opening it for normal use. If this flag is set, the DB_CREATE flag must also be set since the regions will be removed and recreated. : ((|BDB::RECOVER_FATAL|)) Run catastrophic recovery on this environment before opening it for normal use. If this flag is set, the DB_CREATE flag must also be set since the regions will be removed and recreated. : ((|BDB::USE_ENVIRON|)) The Berkeley DB process' environment may be permitted to specify information to be used when naming files : ((|BDB::USE_ENVIRON_ROOT|)) The Berkeley DB process' environment may be permitted to specify information to be used when naming files; if the DB_USE_ENVIRON_ROOT flag is set, environment information will be used for file naming only for users with appropriate permissions : ((|BDB::CREATE|)) Cause Berkeley DB subsystems to create any underlying files, as necessary. : ((|BDB::LOCKDOWN|)) Lock shared Berkeley DB environment files and memory mapped databases into memory. : ((|BDB::NOMMAP|)) Always copy read-only database files in this environment into the local cache instead of potentially mapping them into process memory : ((|BDB::PRIVATE|)) Specify that the environment will only be accessed by a single process : ((|BDB::SYSTEM_MEM|)) Allocate memory from system shared memory instead of from memory backed by the filesystem. : ((|BDB::TXN_NOSYNC|)) Do not synchronously flush the log on transaction commit or prepare. This means that transactions exhibit the ACI (atomicity, consistency and isolation) properties, but not D (durability), i.e., database integrity will be maintained but it is possible that some number of the most recently committed transactions may be undone during recovery instead of being redone. : ((|BDB::CDB_ALLDB|)) For Berkeley DB Concurrent Data Store applications, perform locking on an environment-wide basis rather than per-database. : ((|options|)) Hash, Possible options are (see the documentation of Berkeley DB for more informations) : ((|set_app_dispatch|)) : configure application recovery interface (DB >= 4.1) : ((|set_cachesize|)) : set the database cache size : ((|set_data_dir|)) : set the environment data directory (DB >= 3) : ((|set_encrypt|)) : set the environment cryptographic key (DB >= 4.1) : ((|set_feedback|)) : set feedback callback (DB >= 3) : ((|set_flags|)) : environment configuration (DB >= 3.2) : ((|set_lg_bsize|)) : set log buffer size (DB >= 3) : ((|set_lg_dir|)) : set the environment logging directory (DB >= 3) : ((|set_lg_max|)) : set log file size : ((|set_lg_regionmax|)) : set logging region size (DB >= 3) : ((|set_lk_conflicts|)) : set lock conflicts matrix (DB >= 3) : ((|set_lk_detect|)) : set automatic deadlock detection : ((|set_lk_max_lockers|)) : set maximum number of lockers : ((|set_lk_max_locks|)) : set maximum number of locks : ((|set_lk_max_objects|)) : set maximum number of lock objects : ((|set_rep_transport|)) : configure replication transport (DB >= 4) : ((|set_rep_limit|)) : limit data sent in response to a single message (DB >= 4.1) : ((|set_rep_nsites|)) : configure replication group site count (DB >= 4.5) : ((|set_rep_priority|)) : configure replication site priority (DB >= 4.5) : ((|set_rep_config|)) : configure the replication subsystem (DB >= 4.5) : ((|set_rep_timeout|)) : configure replication timeouts (DB >= 4.5) : ((|set_rpc_server|)) : establish an RPC server connection (DB >= 3.1) : ((|set_tas_spins|)) : set the number of test-and-set spins (DB >= 3) : ((|set_tmp_dir|)) : set the environment temporary file directory (DB >= 3) : ((|set_timeout|)) : set lock and transaction timeout (DB >= 4) : ((|set_tx_max|)) : set maximum number of transactions (DB >= 3) : ((|set_tx_timestamp|)) : set recovery timestamp (DB >= 3.1) : ((|set_verbose|)) : set verbose messages : ((|set_verb_chkpoint|)) :display checkpoint location information when searching the log for checkpoints. (DB >= 3) : ((|set_verb_deadlock|)) : display additional information when doing deadlock detection. (DB >= 3) : ((|set_verb_recovery|)) : display additional information when performing recovery. (DB >= 3) : ((|set_verb_replication|)) : display additional information when processing replication messages. (DB >= 4) : ((|set_verb_waitsfor|)) : display the waits-for table when doing deadlock detection. (DB >= 3) Proc given to ((|set_feedback|)), ((|set_app_dispatch|)) and ((|set_rep_transport|)) can be also specified as a method (replace the prefix ((|set_|)) with ((|bdb_|))) For ((|bdb_rep_transport|)) the constant ((|ENVID|)) must be defined The constant ((|BDB_ENCRYPT|)) can be used to replace ((|set_encrypt|)) --- remove() --- unlink() remove the environnement # end === Methods --- close() close the environnement --- dbremove(file, database = nil, flags = 0) only with BDB::VERSION_MAJOR == 4 && BDB::VERSION_MINOR >= 1 remove the database specified by ((|file|)) and ((|database|)). If no ((|database|)) is ((|nil|)), the underlying file represented by ((|file|)) is removed, incidentally removing all databases that it contained. The ((|flags|)) value must be set to 0 or ((|BDB::AUTO_COMMIT|)) --- dbrename(file, database, newname, flags = 0) only with BDB::VERSION_MAJOR == 4 && BDB::VERSION_MINOR >= 1 rename the database specified by ((|file|)) and ((|database|)) to ((|newname|)). If ((|database|)) is ((|nil|)), the underlying file represented by ((|file|)) is renamed, incidentally renaming all databases that it contained. The ((|flags|)) value must be set to 0 or ((|BDB::AUTO_COMMIT|)) --- feedback=(proc) monitor the progress of some operations --- home() return the name of the directory --- lock() --- lock_id() Acquire a locker ID --- lock_detect(type, flags = 0) The lock_detect function runs one iteration of the deadlock detector. The deadlock detector traverses the lock table, and for each deadlock it finds, marks one of the participating transactions for abort. ((|type|)) can have one the value ((|BDB::LOCK_OLDEST|)), ((|BDB::LOCK_RANDOM|)) or ((|BDB::LOCK_YOUNGUEST|)) ((|flags|)) can have the value ((|BDB::LOCK_CONFLICT|)), in this case the deadlock detector is run only if a lock conflict has occurred since the last time that the deadlock detector was run. return the number of transactions aborted by the lock_detect function if ((|BDB::VERSION_MAJOR >= 3|)) or ((|zero|)) --- lock_stat() Return lock subsystem statistics --- log_archive(flags = 0) The log_archive function return an array of log or database file names. ((|flags|)) value must be set to 0 or the value ((|BDB::ARCH_DATA|)), ((|BDB::ARCH_ABS|)), ((|BDB::ARCH_LOG|)) --- log_checkpoint(string) same as ((|log_put(string, BDB::CHECKPOINT)|)) --- log_curlsn(string) same as ((|log_put(string, BDB::CURLSN)|)) --- log_each { |string, lsn| ... } Implement an iterator inside of the log --- log_flush(string = nil) same as ((|log_put(string, BDB::FLUSH)|)) Without argument, garantee that all records are written to the disk --- log_get(flag) The ((|log_get|)) return an array ((|[String, BDB::Lsn]|)) according to the ((|flag|)) value. ((|flag|)) can has the value ((|BDB::CHECKPOINT|)), ((|BDB::FIRST|)), ((|BDB::LAST|)), ((|BDB::NEXT|)), ((|BDB::PREV|)), ((|BDB::CURRENT|)) --- log_put(string, flag = 0) The ((|log_put|)) function appends records to the log. It return an object ((|BDB::Lsn|)) ((|flag|)) can have the value ((|BDB::CHECKPOINT|)), ((|BDB::CURLSN|)), ((|BDB::FLUSH|)) --- log_reverse_each { |string, lsn| ... } Implement an iterator inside of the log --- log_stat return log statistics --- open_db(type, name = nil, subname = nil, flags = 0, mode = 0) open the database in the current environment. type must be one of the constant ((|BDB::BTREE|)), ((|BDB::HASH|)), ((|BDB::RECNO|)), ((|BDB::QUEUE|)). See (()) for other arguments --- recover { |txn, id| ... } only with BDB::VERSION_MAJOR == 3 && BDB::VERSION_MINOR >= 3 iterate over all prepared transactions. The transaction ((|txn|)) must be made a call to #abort, #commit, #discard ((|id|)) is the global transaction ID for the transaction --- set_flags(flags, onoff = true) only with BDB::VERSION_MAJOR == 3 && BDB::VERSION_MINOR >= 2 ((|flags|)) can have the value ((|BDB::CDB_ALLDB|)), ((|BDB::NOMMAP|)) ((|BDB::TXN_NOSYNC|)) if ((|onoff|)) is false, the specified flags are cleared --- begin(flags = 0) --- txn_begin(flags = 0) --- begin(flags = 0, db, ...) { |txn, db, ...| ...} begin a transaction (the transaction manager must be enabled). flags can have the value ((|DBD::TXN_COMMIT|)), in this case the transaction will be commited at end. --- checkpoint(kbyte, min = 0) --- txn_checkpoint(kbyte, min = 0) The txn_checkpoint function flushes the underlying memory pool, writes a checkpoint record to the log and then flushes the log. If either kbyte or min is non-zero, the checkpoint is only done if more than min minutes have passed since the last checkpoint, or if more than kbyte kilobytes of log data have been written since the last checkpoint. --- stat() --- txn_stat() Return transaction subsystem statistics --- repmgr_add_remote(host, port, flag = 0) Only for DB >= 4.5 Adds a new replication site to the replication manager's list of known sites. Return the environment ID assigned to the remote site --- repmgr_ack_policy=(policy) --- repmgr_set_ack_policy(policy) Only for DB >= 4.5 Specifies how master and client sites will handle acknowledgment of replication messages which are necessary for "permanent" records. ((|policy|)) must be set to one of the following values ((|BDB::REPMGR_ACKS_ALL|)), ((|BDB::REPMGR_ACKS_ALL_PEERS|)), ((|BDB::REPMGR_ACKS_NONE|)), ((|BDB::REPMGR_ACKS_ONE|)), ((|BDB::REPMGR_ACKS_ONE_PEER|)), ((|BDB::REPMGR_ACKS_QUORUM|)) --- repmgr_ack_policy --- repmgr_get_ack_policy Only for DB >= 4.5 Returns the replication manager's client acknowledgment policy. --- repmgr_site_list Only for DB >= 4.5 Returns an array with the status of the sites currently known by the replication manager. --- repmgr_set_local_site(host, port, flag = 0) Only for DB >= 4.5 Specifies the host identification string and port number for the local system. --- repmgr_start(count, flag) Only for DB >= 4.5 Starts the replication manager. --- rep_config[]=(which, onoff) Only for DB >= 4.5 Configures the Berkeley DB replication subsystem. ((|which|)) can have the value ((|BDB::REP_CONF_BULK|)), ((|BDB::REP_CONF_DELAYCLIENT|)), ((|BDB::REP_CONF_NOAUTOINIT|)), ((|BDB::REP_CONF_NOWAIT|)) ((|onoff|)) can have the value ((|true|)) or ((|false|)) --- rep_config?[](which) Only for DB >= 4.5 Returns ((|true|)) if the specified ((|which|)) parameter is currently set or not. --- rep_nsites=(sites) Only for DB >= 4.5 Specifies the total number of sites in a replication group. --- rep_nsites Only for DB >= 4.5 Returns the total number of sites in a replication group. --- rep_priority=(priority) Only for DB >= 4.5 Specifies the priority in the replication group elections. --- rep_priority Only for DB >= 4.5 Returns the database environment priority. --- rep_timeout[]=(which, timeout) Only for DB >= 4.5 Specifies the timeout in the replication group elections. ((|which|)) can have the value ((|BDB::REP_ACK_TIMEOUT|)), ((|BDB::REP_ELECTION_TIMEOUT|)), ((|BDB::REP_ELECTION_RETRY|)), ((|BDB::REP_CONNECTION_RETRY|)) --- rep_timeout[](which) Only for DB >= 4.5 Returns the database environment timeout for ((|which|)) --- elect(sites, priority, timeout) --- rep_elect(sites, priority, timeout) Only for DB >= 4 Holds an election for the master of a replication group, returning the new master's ID Raise ((|BDB::RepUnavail|)) if the ((|timeout|)) expires --- process_message(control, rec, envid) --- rep_process_message(control, rec, envid) Only for DB >= 4 Processes an incoming replication message sent by a member of the replication group to the local database environment --- start(cdata, flags) --- rep_start(cdata, flags) Only for DB >= 4 ((|cdata|)) is an identifier ((|flags|)) must be one of ((|BDB::REP_CLIENT|)), ((|BDB::REP_MASTER|)) or ((|BDB::REP_LOGSONLY|)) --- lsn_reset(file, flags = 0) Only for DB >= 4.4 Reset database file LSN The Env#lsn_reset method allows database files to be moved from one transactional database environment to another. ((|file|))The name of the physical file in which the LSNs are to be cleared. ((|flags|)) must be set to 0 or ((|BDB::ENCRYPT|)) --- fileid_reset(file, flags = 0) Only for DB >= 4.4 Reset database file ID The Env#fileid_reset method allows database files to be copied, and then the copy used in the same database environment as the original. ((|file|))The name of the physical file in which new file IDs are to be created. ((|flags|)) must be set to 0 or ((|BDB::ENCRYPT|)) --- msgcall=(call_proc) Only for DB >= 4.4 There are interfaces in the Berkeley DB library which either directly output informational messages or statistical information : Env#msgcall is used to set callback which will called by BDB The value given must be ((|nil|)) to unconfigure the callback, or and object which respond to ((|#call|)) : it will called with a String as argument --- thread_id=(call_proc) Only for DB >= 4.4 Declare a proc object which returns a unique identifier pair for the current thread of control. The proc must return a pair *((|pid|)): process ID of the current thread *((|tid|)): thread ID of the current thread --- thread_id_string=(call_proc) Only for DB >= 4.4 Declare a proc that formats a process ID and thread ID identifier pair for display. The proc will be called with 2 arguments and must return a String --- is_alive=(call_proc) Only for DB >= 4.4 Declare a proc that returns if a thread of control (either a true thread or a process) is still running. The proc will be called with 2 arguments (pid, tid) --- failcheck(flag = 0) Only for DB >= 4.4 The method checks for threads of control (either a true thread or a process) that have exited while manipulating Berkeley DB library data structures ((|flag|)) is actually unused and must be set to 0 # end # end =end ruby-bdb-0.6.6/docs/exception.rb000066400000000000000000000005551154714021300165070ustar00rootroot00000000000000# general exception class BDB::LockError < Exception end # Lock not held by locker # # inherit from BDB::LockError class BDB::LockHeld < BDB::LockError end # Lock not granted # # inherit from BDB::LockError class BDB::LockGranted < BDB::LockError end # Locker killed to resolve a deadlock # # inherit from BDB::LockError class BDB::LockDead < BDB::LockError end ruby-bdb-0.6.6/docs/hashlike.rd000066400000000000000000000442631154714021300163070ustar00rootroot00000000000000=begin == Acces Methods These are the common methods for ((|BDB::Btree|)), ((|BDB::Hash|)), ((|BDB::Recno|)) and ((|BDB::Queue|)) * (()) * (()) * (()) ## Berkeley DB is an embedded database system that supports keyed access ## to data. # module BDB ## Implementation of a sorted, balanced tree structure # class Btree < Common ## Return an Hash with the fields (description for 4.0.14) ## * bt_magic : Magic number that identifies the file as a Btree database. ## * bt_version : The version of the Btree database. ## * bt_nkeys : the number of unique keys in the database. ## * bt_ndata : the number of key/data pairs in the database. ## * bt_pagesize : Underlying database page size, in bytes. ## * bt_minkey : The minimum keys per page. ## * bt_re_len : The length of fixed-length records. ## * bt_re_pad : The padding byte value for fixed-length records. ## * bt_levels : Number of levels in the database. ## * bt_int_pg : Number of database internal pages. ## * bt_leaf_pg : Number of database leaf pages. ## * bt_dup_pg : Number of database duplicate pages. ## * bt_over_pg : Number of database overflow pages. ## * bt_free : Number of pages on the free list. ## * bt_int_pgfree : Number of bytes free in database internal pages. ## * bt_leaf_pgfree : Number of bytes free in database leaf pages. ## * bt_dup_pgfree : Number of bytes free in database duplicate pages. ## * bt_over_pgfree : Number of bytes free in database overflow pages. # def stat(flags = 0) # end # end ## Implementation of Extended Linear Hashing # class Hash < Common ## Return an Hash with the fields (description for 4.0.14) ## * hash_magic : Magic number that identifies the file as a Hash file. ## * hash_version : The version of the Hash database. ## * hash_nkeys : The number of unique keys in the database. ## * hash_ndata : The number of key/data pairs in the database. ## * hash_pagesize : The underlying Hash database page (and bucket) size, in bytes. ## * hash_nelem : The estimated size of the hash table specified at database-creation time. ## * hash_ffactor : The desired fill factor (number of items per bucket) specified at database-creation time. ## * hash_buckets : The number of hash buckets. ## * hash_free : The number of pages on the free list. ## * hash_bfree :The number of bytes free on bucket pages. ## * hash_bigpages : The number of big key/data pages. ## * hash_big_bfree : The number of bytes free on big item pages. ## * hash_overflows : The number of overflow pages ## * hash_ovfl_free : The number of bytes free on overflow pages. ## * hash_dup : The number of duplicate pages. ## * hash_dup_free : The number of bytes free on duplicate pages. # def stat(flags = 0) # end # end ## Stores both fixed and variable-length records with logical record ## numbers as keys # class Recno < Common ## Return an Hash with the fields (description for 4.0.14) ## * bt_magic : Magic number that identifies the file as a Btree database. ## * bt_version : The version of the Btree database. ## * bt_nkeys : The exact number of records in the database. ## * bt_ndata : The exact number of records in the database. ## * bt_pagesize : Underlying database page size, in bytes. ## * bt_minkey : The minimum keys per page. ## * bt_re_len : The length of fixed-length records. ## * bt_re_pad : The padding byte value for fixed-length records. ## * bt_levels : Number of levels in the database. ## * bt_int_pg : Number of database internal pages. ## * bt_leaf_pg : Number of database leaf pages. ## * bt_dup_pg : Number of database duplicate pages. ## * bt_over_pg : Number of database overflow pages. ## * bt_free : Number of pages on the free list. ## * bt_int_pgfree : Number of bytes free in database internal pages. ## * bt_leaf_pgfree : Number of bytes free in database leaf pages. ## * bt_dup_pgfree : Number of bytes free in database duplicate pages. ## * bt_over_pgfree : Number of bytes free in database overflow pages. # def stat(flags = 0) # end # end ## Stores fixed-length records with logical record numbers as keys. ## It is designed for fast inserts at the tail and has a special cursor ## consume operation that deletes and returns a record from the head of ## the queue # class Queue < Common ## Return an Hash with the fields (description for 4.0.14) ## * qs_magic : Magic number that identifies the file as a Queue file. ## * qs_version : The version of the Queue file type. ## * qs_nkeys : The number of records in the database. ## * qs_ndata : The number of records in the database. ## * qs_pagesize : Underlying database page size, in bytes. ## * qs_extentsize : Underlying database extent size, in pages. ## * qs_pages : Number of pages in the database. ## * qs_re_len : The length of the records. ## * qs_re_pad : The padding byte value for the records. ## * qs_pgfree : Number of bytes free in database pages. ## * qs_first_recno : First undeleted record in the database. ## * qs_cur_recno : Last allocated record number in the database. # def stat(flags = 0) # end # end ## Implement common methods for access to data # class Common # class << self === Class Methods --- open(name = nil, subname = nil, flags = 0, mode = 0, options = {}) --- create(name = nil, subname = nil, flags = 0, mode = 0, options = {}) --- new(name = nil, subname = nil, flags = 0, mode = 0, options = {}) open the database : ((|name|)) The argument name is used as the name of a single physical file on disk that will be used to back the database. : ((|subname|)) The subname argument allows applications to have subdatabases, i.e., multiple databases inside of a single physical file. This is useful when the logical databases are both numerous and reasonably small, in order to avoid creating a large number of underlying files. It is an error to attempt to open a subdatabase in a database file that was not initially created using a subdatabase name. : ((|flags|)) The flags must be the string "r", "r+", "w", "w+", "a", "a+" or and integer value. The flags value must be set to 0 or by bitwise inclusively OR'ing together one or more of the following values : ((|BDB::CREATE|)) Create any underlying files, as necessary. If the files do not already exist and the DB_CREATE flag is not specified, the call will fail. : ((|BD::EXCL|)) Return an error if the database already exists. Underlying filesystem primitives are used to implement this flag. For this reason it is only applicable to the physical database file and cannot be used to test if a subdatabase already exists. : ((|BDB::NOMMAP|)) Do not map this database into process memory. : ((|BDB::RDONLY|)) Open the database for reading only. Any attempt to modify items in the database will fail regardless of the actual permissions of any underlying files. : ((|BDB::TRUNCATE|)) Physically truncate the underlying database file, discarding all previous subdatabases or databases. Underlying filesystem primitives are used to implement this flag. For this reason it is only applicable to the physical database file and cannot be used to discard subdatabases. The DB_TRUNCATE flag cannot be transaction protected, and it is an error to specify it in a transaction protected environment. : ((|options|)) Hash, Possible options are (see the documentation of Berkeley DB for more informations) : ((|store_nil_as_null|)): if `true' will store `nil' as `\000', otherwise as an empty string (default `false') : ((|set_array_base|)): base index for BDB::Recno, BDB::Queue or BDB::Btree (with BDB::RECNUM). Must be 0 or 1 : ((|set_bt_compare|)) : specify a Btree comparison function : ((|set_bt_minkey|)) : set the minimum number of keys per Btree page : ((|set_bt_prefix|)) : specify a Btree prefix comparison function : ((|set_cachesize|)) : set the database cache size : ((|set_dup_compare|)) : specify a duplicate comparison function : ((|set_store_key|)) : specify a Proc called before a key is stored : ((|set_fetch_key|)) : specify a Proc called after a key is read : ((|set_store_value|)) : specify a Proc called before a value is stored : ((|set_fetch_value|)) : specify a Proc called after a value is read : ((|set_flags|)) : general database configuration : ((|set_h_ffactor|)) : set the Hash table density : ((|set_h_hash|)) : specify a hashing function : ((|set_h_nelem|)) : set the Hash table size : ((|set_lorder|)) : set the database byte order : ((|set_pagesize|)) : set the underlying database page size : ((|set_re_delim|)) : set the variable-length record delimiter : ((|set_re_len|)) : set the fixed-length record length : ((|set_re_pad|)) : set the fixed-length record pad byte : ((|set_re_source|)) : set the backing Recno text file : ((|set_append_recno|)) : modify the stored data for ((|BDB::APPEND|)) : ((|set_encrypt|)) : set the password used : ((|set_feedback|)) : set the function to monitor some operations : ((|env|)) : open the database in the environnement given as the value : ((|txn|)) : open the database in the transaction given as the value ((|set_append_recno|)) will be called with (key, value) and it must return ((|nil|)) or the modified value ((|set_encrypt|)) take an Array as arguments with the values [password, flags], where flags can be 0 or ((|BDB::ENCRYPT_AES|)) Proc given to ((|set_bt_compare|)), ((|set_bt_prefix|)), ((|set_dup_compare|)), ((|set_h_hash|)), ((|set_store_key|)) ((|set_fetch_key|)), ((|set_store_value|)), ((|set_fetch_value|)) ((|set_feedback|)) and ((|set_append_recno|)) can be also specified as a method (replace the prefix ((|set_|)) with ((|bdb_|))) For example module BDB class Btreesort < Btree def bdb_bt_compare(a, b) b.downcase <=> a.downcase end end end --- remove(name, subname = nil) --- db_remove(name, subname = nil) --- unlink(name, subname = nil) Removes the database (or subdatabase) represented by the name and subname combination. If no subdatabase is specified, the physical file represented by name is removed, incidentally removing all subdatabases that it contained. --- upgrade(name) --- db_upgrade(name) Upgrade the database # end === Methods --- self[key] Returns the value corresponding the ((|key|)) --- associate(db, flag = 0) { |db, key, value| } associate a secondary index db ((|flag|)) can have the value ((|BDB::RDONLY|)) The block must return the new key, or ((|Qfalse|)) in this case the secondary index will not contain any reference to key/value --- cache_priority return the current priority value --- cache_priority=value set the priority value : can be ((|BDB::PRIORITY_VERY_LOW|)), ((|BDB::PRIORITY_LOW|)), ((|BDB::PRIORITY_DEFAULT|)), ((|BDB::PRIORITY_HIGH|)) or ((|BDB::PRIORITY_VERY_HIGH|)) --- feedback=(proc) monitor the progress of some operations --- get(key, flags = 0) --- db_get(key, flags = 0) --- fetch(key, flags = 0) Returns the value correspondind the ((|key|)) ((|flags|)) can have the values ((|BDB::GET_BOTH|)), ((|BDB::SET_RECNO|)) or ((|BDB::RMW|)) In presence of duplicates it will return the first data item, use #duplicates if you want all duplicates (see also #each_dup) --- pget(key, flags = 0) Returns the primary key and the value corresponding to ((|key|)) in the secondary index only with >= 3.3.11 --- self[key] = value Stores the ((|value|)) associating with ((|key|)) If ((|nil|)) is given as the value, the association from the key will be removed. --- put(key, value, flags = 0) --- db_put(key, value, flags = 0) --- store(key, value, flags = 0) Stores the ((|value|)) associating with ((|key|)) If ((|nil|)) is given as the value, the association from the ((|key|)) will be removed. It return the object deleted or ((|nil|)) if the specified key don't exist. ((|flags|)) can have the value ((|DBD::NOOVERWRITE|)), in this case it will return ((|nil|)) if the specified key exist, otherwise ((|true|)) --- append(key, value) --- db_append(key, value) Append the ((|value|)) associating with ((|key|)) --- byteswapped? --- get_byteswapped Return if the underlying database is in host order --- clear_partial --- partial_clear Clear partial set. --- close(flags = 0) --- db_close(flags = 0) Closes the file. --- count(key) --- dup_count(key) Return the count of duplicate for ((|key|)) --- cursor(flags = 0) --- db_cursor(flags = 0) Open a new cursor. --- database() --- subname() Return the subname --- delete(key) --- db_del(key) Removes the association from the key. It return the object deleted or ((|nil|)) if the specified key don't exist. --- delete_if(set = nil) { |key, value| ... } --- reject!(set = nil) { |key, value| ... } Deletes associations if the evaluation of the block returns true. (()) --- duplicates(key , assoc = true) Return an array of all duplicate associations for ((|key|)) if ((|assoc|)) is ((|false|)) return only the values. --- each(set = nil, bulk = 0, "flags" => 0) { |key, value| ... } --- each_pair(set = nil, bulk = 0) { |key, value| ... } Iterates over associations. (()) (()) --- each_by_prefix(prefix) {|key, value| ... } Iterate over associations, where the key begin with ((|prefix|)) --- each_dup(key, bulk = 0) { |key, value| ... } Iterates over each duplicate associations for ((|key|)) (()) --- each_dup_value(key, bulk = 0) { |value| ... } Iterates over each duplicate values for ((|key|)) (()) --- each_key(set = nil, bulk = 0) { |key| ... } Iterates over keys. (()) (()) --- each_primary(set = nil) { |skey, pkey, pvalue| ... } Iterates over secondary indexes and give secondary key, primary key and value --- each_value(set = nil, bulk = 0) { |value| ... } Iterates over values. (()) (()) --- empty?() Returns true if the database is empty. --- filename() Return the name of the file --- has_key?(key) --- key?(key) --- include?(key) --- member?(key) Returns true if the association from the ((|key|)) exists. --- has_both?(key, value) --- both?(key, value) Returns true if the association from ((|key|)) is ((|value|)) --- has_value?(value) --- value?(value) Returns true if the association to the ((|value|)) exists. --- index(value) Returns the first ((|key|)) associated with ((|value|)) --- indexes(value1, value2, ) Returns the ((|keys|)) associated with ((|value1, value2, ...|)) --- join(cursor , flag = 0) { |key, value| ... } Perform a join. ((|cursor|)) is an array of ((|BDB::Cursor|)) --- keys Returns the array of the keys in the database --- length --- size Returns the number of association in the database. --- log_register(name) The ((|log_register|)) function registers a file ((|name|)). --- log_unregister() The ((|log_unregister|)) function unregisters a file name. --- reject { |key, value| ... } Create an hash without the associations if the evaluation of the block returns true. --- reverse_each(set = nil) { |key, value| ... } --- reverse_each_pair(set = nil) { |key, value| ... } Iterates over associations in reverse order (()) --- reverse_each_by_prefix(prefix) {|key, value| ... } Iterate over associations in reverse order, where the key begin with ((|prefix|)) --- reverse_each_key(set = nil) { |key| ... } Iterates over keys in reverse order (()) --- reverse_each_primary(set = nil) { |skey, pkey, pvalue| ... } Iterates over secondary indexes in reverse order and give secondary key, primary key and value --- reverse_each_value(set = nil) { |value| ... } Iterates over values in reverse order. (()) --- set_partial(len, offset) Set the partial value ((|len|)) and ((|offset|)) --- stat Return database statistics. --- to_a Return an array of all associations [key, value] --- to_hash Return an hash of all associations {key => value} --- truncate --- clear Empty a database --- values Returns the array of the values in the database. --- verify(file = nil, flags = 0) Verify the integrity of the DB file, and optionnally output the key/data to ((|file|)) (file must respond to #to_io) --- compact(start = nil, stop = nil, options = nil) Only for Btree and Recno (DB VERSION >= 4.4) * ((|start|)) starting point for compaction in a Btree or Recno database. Compaction will start at the smallest key greater than or equal to the specified key. * ((|stop|)) the stopping point for compaction in a Btree or Recno database. Compaction will stop at the page with the smallest key greater than the specified key * ((|options|)) hash with the possible keys * ((|flags|)) with the value 0, ((|BDB::FREELIST_ONLY|)), or ((|BDB::FREE_SPACE|)) * ((|compact_fillpercent|))the goal for filling pages, specified as a percentage between 1 and 100. * ((|compact_timeout|)) the lock timeout set for implicit transactions, in microseconds. # end # class Recno < Common ## class Queue < Common === Methods specific to BDB::Recno and BDB::Queue --- pop Returns the last couple [key, val] (only for BDB::Recno) --- push values Push the values --- shift Removes and returns an association from the database. # end === Remark ==== set If the parameter ((|set|)) is given, an initial call will be made with the option ((|BDB::SET_RANGE|)) to move the cursor to the specified key before iterating. ==== bulk Only with >= 3.3.11 : if the parameter ((|bulk|)) is given, an application buffer of size ((|bulk * 1024|)) will be used (see "Retrieving records in bulk" in the documentation of BerkeleyDB) =end ruby-bdb-0.6.6/docs/lock.rb000066400000000000000000000043301154714021300154340ustar00rootroot00000000000000# a BDB::Lockid object is created by the method lock, lock_id class BDB::Lockid #The lock_get function acquires a lock from the lock table, it return #an object BDB::Lock # #string specifies the object to be locked or released. # #mode is an index into the environment's lock conflict array # #flags value must be set to 0 or the value BDBD::LOCK_NOWAIT #in this case if a lock cannot be granted because the requested #lock conflicts with an existing lock, raise an error BDB::LockGranted # def get(string, mode , flags = 0) end #same than get def lock_get(string, mode [, flags]) end #The lock_vec function atomically obtains and releases one or more #locks from the lock table. The lock_vec function is intended to #support acquisition or trading of multiple locks under one lock table #semaphore, as is needed for lock coupling or in multigranularity #locking for lock escalation. # #* array # ARRAY of HASH with the following keys # # * "op" # the operation to be performed, which must be set to one # of the following values BDB::LOCK_GET, BDB::LOCK_PUT, # BDB::LOCK_PUT_ALL or BDB::LOCK_PUT_OBJ # # * "obj" # the object (String) to be locked or released # # * "mode" # is an index into the environment's lock conflict array # # * "lock" # an object BDB::Lock # #* flags # value must be set to 0 or the value BDBD::LOCK_NOWAIT # in this case if a lock cannot be granted because the requested # lock conflicts with an existing lock, raise an error # BDB::LockGrantedreturn immediately # def vec(array , flags = 0) end #same than vec def lock_vec(array [, flags]) end end class BDB::Lock #The lock_put function releases lock from the lock table. # def put() end #same than put def lock_put() end #same than put def release() end #same than put def delete() end end ruby-bdb-0.6.6/docs/lock.rd000066400000000000000000000064431154714021300154450ustar00rootroot00000000000000=begin == Lock system # module BDB # The lock subsystem provides interprocess and intraprocess concurrency control mechanisms. While the locking system is used extensively by the Berkeley DB access methods and transaction system, it may also be used as a stand-alone subsystem to provide concurrency control to any set of designated resources. # # class Lockid # end # The lock subsystem is created, initialized, and opened by calls to (({BDB::Env#open})) with the ((|DBD::INIT_LOCK|)) or ((|DBB::INIT_CDB|)) flags specified. The following options can be given when the environnement is created : ((|"set_lk_conflicts"|)) Set lock conflicts matrix : ((|"set_lk_detect"|)) Set automatic deadlock detection : ((|"set_lk_max"|)) Set maximum number of locks === BDB::LockError # Exception generated by lock call # # class LockError < Exception # end === BDB::LockHeld #^ Lock not held by locker #^ # class LockHeld < LockError # end === BDB::LockGranted #^ Lock not granted #^ # class LockGranted < LockError # end === BDB::LockDead #^ Locker killed to resolve a deadlock #^ # class LockDead < LockError # end ## a BDB::Lockid object is created by the method lock, lock_id # class Lockid === BDB::Lockid A lock ID can be obtained with (()) See also (()) and (()) ==== Methods --- get(string, mode , flags = 0) --- lock_get(string, mode [, flags]) The lock_get function acquires a lock from the lock table, it return an object ((|BDB::Lock|)) ((|string|)) specifies the object to be locked or released. ((|mode|)) is an index into the environment's lock conflict array ((|flags|)) value must be set to 0 or the value ((|BDBD::LOCK_NOWAIT|)) in this case if a lock cannot be granted because the requested lock conflicts with an existing lock, raise an error ((|BDB::LockGranted|)) --- vec(array , flags = 0) --- lock_vec(array [, flags]) The ((|lock_vec|)) function atomically obtains and releases one or more locks from the lock table. The ((|lock_vec|)) function is intended to support acquisition or trading of multiple locks under one lock table semaphore, as is needed for lock coupling or in multigranularity locking for lock escalation. : ((|array|)) ARRAY of HASH with the following keys : ((|"op"|)) the operation to be performed, which must be set to one of the following values ((|BDB::LOCK_GET|)), ((|BDB::LOCK_PUT|)), ((|BDB::LOCK_PUT_ALL|)) or ((|BDB::LOCK_PUT_OBJ|)) : ((|"obj"|)) the object (String) to be locked or released : ((|"mode"|)) is an index into the environment's lock conflict array : ((|"lock"|)) an object ((|BDB::Lock|)) : ((|flags|)) value must be set to 0 or the value ((|BDBD::LOCK_NOWAIT|)) in this case if a lock cannot be granted because the requested lock conflicts with an existing lock, raise an error ((|BDB::LockGranted|))return immediately # end # class Lock === BDB::Lock ==== Methods --- put() --- lock_put() --- release() --- delete() The ((|lock_put|)) function releases lock from the lock table. # end # end =end ruby-bdb-0.6.6/docs/log.rb000066400000000000000000000014771154714021300152760ustar00rootroot00000000000000# a BDB::Lsn object is created by the method log_checkpoint, log_curlsn, # log_flush, log_put class BDB::Lsn include Comparable # #compare 2 BDB::Lsn # def <=>(other) end # #The log_file function maps BDB::Lsn structures to file #names # def log_file(name) end #same than log_file def file(name) end # #The log_flush function guarantees that all log records whose #DBB:Lsn are less than or equal to the current lsn have been written #to disk. # def log_flush end #same than log_flush def flush end # #return the String associated with this BDB::Lsn # def log_get end #same than log_get def get end end ruby-bdb-0.6.6/docs/log.rd000066400000000000000000000057251154714021300153000ustar00rootroot00000000000000=begin == Logging subsystem # module BDB # This subsystem is used when recovery from application or system failure is necessary. The log is stored in one or more files in the environment directory. Each file is named using the format log.NNNNNNNNNN, where NNNNNNNNNN is the sequence number of the file within the log. If the log region is being created and log files are already present, the log files are reviewed and subsequent log writes are appended to the end of the log, rather than overwriting current log entries. The lock subsystem is created, initialized, and opened by calls to (({BDB::Env#open})) with the ((|BDB::INIT_LOG|)) flag specified. The following options can be given when the environnement is created : ((|"set_lg_bsize"|)) Set log buffer size : ((|"set_lg_dir"|)) Set the environment logging directory : ((|"set_lg_max"|)) Set log file size # # class Env === BDB::Env ==== Methods --- log_archive(flags = 0) The log_archive function return an array of log or database file names. ((|flags|)) value must be set to 0 or the value ((|BDB::ARCH_DATA|)) ((|BDB::ARCH_DATA|)), ((|BDB::ARCH_LOG|)) --- log_checkpoint(string) same as ((|log_put(string, BDB::CHECKPOINT)|)) --- log_curlsn(string) same as ((|log_put(string, BDB::CURLSN)|)) --- log_each { |string, lsn| ... } Implement an iterator inside of the log --- log_flush([string]) same as ((|log_put(string, BDB::FLUSH)|)) Without argument, garantee that all records are written to the disk --- log_get(flag) The ((|log_get|)) return an array ((|[String, BDB::Lsn]|)) according to the ((|flag|)) value. ((|flag|)) can has the value ((|BDB::CHECKPOINT|)), ((|BDB::FIRST|)), ((|BDB::LAST|)), ((|BDB::NEXT|)), ((|BDB::PREV|)), ((|BDB::CURRENT|)) --- log_put(string, flag = 0) The ((|log_put|)) function appends records to the log. It return an object ((|BDB::Lsn|)) ((|flag|)) can have the value ((|BDB::CHECKPOINT|)), ((|BDB::CURLSN|)), ((|BDB::FLUSH|)) --- log_reverse_each { |string, lsn| ... } Implement an iterator inside of the log --- log_stat return log statistics # end # class Common === BDB::Common ==== Methods --- log_register(name) The ((|log_register|)) function registers a file ((|name|)). --- log_unregister() The ((|log_unregister|)) function unregisters a file name. # end ## a BDB::Lsn object is created by the method log_checkpoint, log_curlsn, ## log_flush, log_put # class Lsn # include Comparable === BDB::Lsn include Comparable --- <=> compare 2 ((|BDB::Lsn|)) --- log_file(name) --- file(name) The ((|log_file|)) function maps ((|BDB::Lsn|)) structures to file ((|name|))s --- log_flush --- flush The ((|log_flush|)) function guarantees that all log records whose ((|DBB:Lsn|)) are less than or equal to the current lsn have been written to disk. --- log_get --- get return the ((|String|)) associated with this ((|BDB::Lsn|)) # end # end =end ruby-bdb-0.6.6/docs/sequence.rb000066400000000000000000000017411154714021300163170ustar00rootroot00000000000000# A sequence is created with the method BDB::Common#create_sequence # or BDB::Common#open_sequence # class BDB::Sequence #return the current cache size def cachesize end #close the sequence def close end #return the bdb file associated with the sequence def db end #return the current flags def flags end #return the next available element in the sequence and changes #the sequence value by delta # #flags can have the value BDB::AUTO_COMMIT, BDB::TXN_NOSYNC def get(delta = 1, flags = 0) end #return the key associated with the sequence def key end #return the range of values in the sequence def range end #remove the sequence # #flags can have the value BDB::AUTO_COMMIT, BDB::TXN_NOSYNC def remove(flags = 0) end #return statistics about the sequence # #flags can have the value BDB::STAT_CLEAR def stat(flags = 0) end end ruby-bdb-0.6.6/docs/sequence.rd000066400000000000000000000033251154714021300163210ustar00rootroot00000000000000=begin == BDB::Sequence # module BDB #^ A sequence is created with BDB::Common::create_sequence or BDB::Common::open_sequence (only with db >= 4.3) #^ === class BDB::Common --- create_sequence(key, init = nil, options = {}) {|sequence| } create a new sequence (see also ((|open_sequence|))) equivalent to ((|open_sequence(key, BDB::CREATE|BDB::EXCL, init, options)|)) return (or yield) an object BDB::Sequence --- open_sequence(key, flags = 0, init = nil, options = {}) {|sequence| } create or open a sequence (see BDB::Sequence) ((|key|)) : key for the sequence ((|flags|)) : flags can have BDB::CREATE, BDB::EXCL, BDB::AUTO_COMMIT, BDB::THREAD ((|init|)) : initial value for the sequence ((|options|)) : hash with the possible keys "set_cachesize", "set_flags" and "set_range" return (or yield) an object BDB::Sequence #^ # class Sequence === Methods --- cachesize return the current cache size --- close close the sequence --- db return the bdb file associated with the sequence --- flags return the current flags --- get(delta = 1, flags = 0) return the next available element in the sequence and changes the sequence value by ((|delta|)) ((|flags|)) can have the value BDB::AUTO_COMMIT, BDB::TXN_NOSYNC --- key return the key associated with the sequence --- range return the range of values in the sequence --- remove(flags = 0) remove the sequence ((|flags|)) can have the value BDB::AUTO_COMMIT, BDB::TXN_NOSYNC --- stat(flags = 0) return statistics about the sequence ((|flags|)) can have the value BDB::STAT_CLEAR # end # end =end ruby-bdb-0.6.6/docs/transaction.rb000066400000000000000000000137711154714021300170420ustar00rootroot00000000000000# # The transaction subsystem makes operations atomic, consistent, # isolated, and durable in the face of system and application # failures. The subsystem requires that the data be properly logged and # locked in order to attain these properties. Berkeley DB contains all # the components necessary to transaction-protect the Berkeley DB access # methods and other forms of data may be protected if they are logged # and locked appropriately. # # # The transaction subsystem is created, initialized, and opened by calls # to BDB::Env#open with the BDB::INIT_TXN # flag (or BDB::INIT_TRANSACTION) specified. # Note that enabling transactions automatically enables # logging, but does not enable locking, as a single thread of control # that needed atomicity and recoverability would not require it. # # The transaction is created with BDB::Env#begin # or with begin class BDB::Txn #Abort the transaction. This is will terminate the transaction. # def abort() end #same than abort def txn_abort() end #Associate a database with the transaction, return a new database #handle which is transaction protected. # def assoc(db, ...) end #same than assoc def associate(db, ...) end #same than assoc def txn_assoc(db, ...) end #begin a transaction (the transaction manager must be enabled). flags #can have the value DBD::TXN_COMMIT, in this case the transaction #will be commited at end. # #Return a new transaction object, and the associated database handle #if specified. # #If #begin is called as an iterator, #commit and #abort #will terminate the iterator. # #env.begin(db) do |txn, b| #... #end # #is the same than # #env.begin do |txn| #b = txn.assoc(db) #... #end # #An optional hash can be given with the possible keys "flags", #"set_timeout", "set_txn_timeout", "set_lock_timeout" # # def begin(flags = 0, db, ...) yield txn, db, ... end #same than begin def txn_begin(flags = 0, db, ...) end #Commit the transaction. This will finish the transaction. #The flags can have the value # #BDB::TXN_SYNC Synchronously flush the log. This means the #transaction will exhibit all of the ACID (atomicity, consistency #and isolation and durability) properties. This is the default value. # #BDB::TXN_NOSYNC Do not synchronously flush the log. This #means the transaction will exhibit the ACI (atomicity, consistency #and isolation) properties, but not D (durability), i.e., database #integrity will be maintained but it is possible that this #transaction may be undone during recovery instead of being redone. # #This behavior may be set for an entire Berkeley DB environment as #part of the open interface. # def commit(flags = 0) end #same than commit def close(flags = 0) end #same than commit def txn_commit(flags = 0) end #same than commit def txn_close(flags = 0) end #only with BDB::VERSION_MAJOR == 3 && BDB::VERSION_MINOR >= 3 # #Discard a prepared but not resolved transaction handle, must be called #only within BDB::Env#recover # def discard end #same than discard def txn_discard end #only with BDB::VERSION_MAJOR == 4 && BDB::VERSION_MINOR >= 1 # #remove the database specified by file and database. If no #database is nil, the underlying file represented by #file is removed, incidentally removing all databases #that it contained. # #The flags value must be set to 0 or BDB::AUTO_COMMIT # def dbremove(file, database = nil, flags = 0) end #only with BDB::VERSION_MAJOR == 4 && BDB::VERSION_MINOR >= 1 # #rename the database specified by file and database to #newname. If database is nil, the underlying file #represented by file is renamed, incidentally renaming all databases #that it contained. # #The flags value must be set to 0 or BDB::AUTO_COMMIT # def dbrename(file, database, newname, flags = 0) end #The txn_id function returns the unique transaction id associated #with the specified transaction. Locking calls made on behalf of #this transaction should use the value returned from txn_id as the #locker parameter to the lock_get or lock_vec calls. # def id() end #same than id def txn_id() end #Only with DB >= 4.1 # #open the database in the current transaction. type must be one of #the constant BDB::BTREE, BDB::HASH, BDB::RECNO, #BDB::QUEUE. See open for other #arguments # def open_db(type, name = nil, subname = nil, flags = 0, mode = 0) end #The txn_prepare function initiates the beginning of a two-phase commit. # #In a distributed transaction environment, Berkeley DB can be used #as a local transaction manager. In this case, the distributed #transaction manager must send prepare messages to each local #manager. The local manager must then issue a txn_prepare and await its #successful return before responding to the distributed transaction #manager. Only after the distributed transaction manager receives #successful responses from all of its prepare messages should it issue #any commit messages. # def prepare() end #same than prepare def txn_prepare() end #same than prepare def txn_prepare(id) # version 3.3.11 end #Only with DB >= 4.4 # #Return the string associated with a transaction # def name end #Only with DB >= 4.4 # #Set the string associated with a transaction # def name=(string) end end ruby-bdb-0.6.6/docs/transaction.rd000066400000000000000000000133041154714021300170340ustar00rootroot00000000000000=begin == BDB::Txn # module BDB #^ The transaction subsystem makes operations atomic, consistent, isolated, and durable in the face of system and application failures. The subsystem requires that the data be properly logged and locked in order to attain these properties. Berkeley DB contains all the components necessary to transaction-protect the Berkeley DB access methods and other forms of data may be protected if they are logged and locked appropriately. The transaction subsystem is created, initialized, and opened by calls to (()) with the ((|BDB::INIT_TXN|)) flag (or ((|BDB::INIT_TRANSACTION|))) specified. Note that enabling transactions automatically enables logging, but does not enable locking, as a single thread of control that needed atomicity and recoverability would not require it. #^ The following option can be given when the environnement is created : ((|"set_tx_max"|)) Set maximum number of transactions and with DB >= 4.0 : ((|"set_timeout"|)) : ((|"set_txn_timeout"|)) : ((|"set_lock_timeout"|)) #^ The transaction is created with (()) or with (()) #^ See also (()) and (()) # class Txn === Methods --- abort() --- txn_abort() Abort the transaction. This is will terminate the transaction. --- assoc(db, ...) --- associate(db, ...) --- txn_assoc(db, ...) Associate a database with the transaction, return a new database handle which is transaction protected. --- begin(flags = 0, db, ...) { |txn, db, ...| ...} --- begin(flags = 0, db, ...) --- txn_begin(flags = 0, db, ...) begin a transaction (the transaction manager must be enabled). flags can have the value ((|DBD::TXN_COMMIT|)), in this case the transaction will be commited at end. Return a new transaction object, and the associated database handle if specified. If ((|#begin|)) is called as an iterator, ((|#commit|)) and ((|#abort|)) will terminate the iterator. env.begin(db) do |txn, b| ... end is the same than env.begin do |txn| b = txn.assoc(db) ... end An optional hash can be given with the possible keys ((|"flags"|)), ((|"set_timeout"|)), ((|"set_txn_timeout"|)), ((|"set_lock_timeout"|)) --- commit(flags = 0) --- close(flags = 0) --- txn_commit(flags = 0) --- txn_close(flags = 0) Commit the transaction. This will finish the transaction. The ((|flags|)) can have the value ((|BDB::TXN_SYNC|)) Synchronously flush the log. This means the transaction will exhibit all of the ACID (atomicity, consistency and isolation and durability) properties. This is the default value. ((|BDB::TXN_NOSYNC|)) Do not synchronously flush the log. This means the transaction will exhibit the ACI (atomicity, consistency and isolation) properties, but not D (durability), i.e., database integrity will be maintained but it is possible that this transaction may be undone during recovery instead of being redone. This behavior may be set for an entire Berkeley DB environment as part of the open interface. --- discard --- txn_discard only with BDB::VERSION_MAJOR == 3 && BDB::VERSION_MINOR >= 3 Discard a prepared but not resolved transaction handle, must be called only within BDB::Env#recover --- dbremove(file, database = nil, flags = 0) only with BDB::VERSION_MAJOR == 4 && BDB::VERSION_MINOR >= 1 remove the database specified by ((|file|)) and ((|database|)). If no ((|database|)) is ((|nil|)), the underlying file represented by ((|file|)) is removed, incidentally removing all databases that it contained. The ((|flags|)) value must be set to 0 or ((|BDB::AUTO_COMMIT|)) --- dbrename(file, database, newname, flags = 0) only with BDB::VERSION_MAJOR == 4 && BDB::VERSION_MINOR >= 1 rename the database specified by ((|file|)) and ((|database|)) to ((|newname|)). If ((|database|)) is ((|nil|)), the underlying file represented by ((|file|)) is renamed, incidentally renaming all databases that it contained. The ((|flags|)) value must be set to 0 or ((|BDB::AUTO_COMMIT|)) --- id() --- txn_id() The txn_id function returns the unique transaction id associated with the specified transaction. Locking calls made on behalf of this transaction should use the value returned from txn_id as the locker parameter to the lock_get or lock_vec calls. --- open_db(type, name = nil, subname = nil, flags = 0, mode = 0) Only with DB >= 4.1 open the database in the current transaction. type must be one of the constant ((|BDB::BTREE|)), ((|BDB::HASH|)), ((|BDB::RECNO|)), ((|BDB::QUEUE|)). See (()) for other arguments --- prepare() --- txn_prepare() --- prepare(id) # version 3.3.11 --- txn_prepare(id) # version 3.3.11 The txn_prepare function initiates the beginning of a two-phase commit. In a distributed transaction environment, Berkeley DB can be used as a local transaction manager. In this case, the distributed transaction manager must send prepare messages to each local manager. The local manager must then issue a txn_prepare and await its successful return before responding to the distributed transaction manager. Only after the distributed transaction manager receives successful responses from all of its prepare messages should it issue any commit messages. --- name # version 4.4 Return the string associated with a transaction --- name=(string) # version 4.4 Set the string associated with a transaction # end # end =end ruby-bdb-0.6.6/examples/000077500000000000000000000000001154714021300150455ustar00rootroot00000000000000ruby-bdb-0.6.6/examples/basic.rb000077500000000000000000000006641154714021300164640ustar00rootroot00000000000000#!/usr/bin/ruby require './clean.rb' BDB::Env.cleanup "tmp", true db = BDB::Btree.open "tmp/basic", nil, BDB::CREATE | BDB::TRUNCATE, 0644, "set_pagesize" => 1024, "set_cachesize" => [0, 32 * 1024, 0] File.foreach("wordlist") do |line| line.chomp! db[line] = line.reverse end db.stat.each do |k, v| print "#{k}\t#{v}\n" end db.each do |k, v| if k != v.reverse print "ERROR : #{k} -- #{v}\n" end end db.close ruby-bdb-0.6.6/examples/cats.rb000077500000000000000000000026651154714021300163400ustar00rootroot00000000000000#!/usr/bin/ruby require './clean.rb' if BDB::VERSION_MAJOR == 2 || (BDB::VERSION_MAJOR == 3 && BDB::VERSION_MINOR < 3) raise "associate exist only with DB >= 3.3" end BDB::Env.cleanup("tmp", true) cat = Struct.new("Cat", :name, :age, :life) bdb = BDB::Btree.open "tmp/aa", nil, "w", "marshal" => true aux = BDB::Btree.open "tmp/bb", nil, "w", "set_flags" => BDB::DUPSORT, "marshal" => true bdb.associate(aux) { |aux1, key, value| value.life } 36.times do |i| bdb["a" + i.to_s] = cat.new "cat" + i.to_s, 1 + rand(24), 1 + rand(7) end p "======================= each ==================================" aux.each do |k, v| puts "key : #{k} -- value #{v.inspect}" end p "======================== duplicates ===========================" 7.times do |i| p aux.duplicates(1 + i) end p "======================== each_dup_value =======================" aux.each_dup_value(7) do |v| puts "value #{v.inspect}" end p "========================= each_primary ========================" aux.each_primary do |sk, pk, pv| puts "pk : #{pk} pv : #{pv.inspect} sk : #{sk}" end p "===================== reverse_each_primary ====================" aux.reverse_each_primary do |sk, pk, pv| puts "pk : #{pk} pv : #{pv.inspect} sk : #{sk}" end p "======================= cursor.pget ===========================" cursor = aux.cursor while pkv = cursor.pget(BDB::NEXT) sk, pk, pv = pkv puts "pk : #{pk.inspect} pv : #{pv.inspect} sk : #{sk}" end ruby-bdb-0.6.6/examples/clean.rb000066400000000000000000000004051154714021300164530ustar00rootroot00000000000000require '../src/bdb' class << BDB::Env def cleanup(dir, all = false) remove(dir) rescue nil Dir.foreach(dir) do |file| if FileTest.file?("#{dir}/#{file}") File.unlink("#{dir}/#{file}") if all || /^log/ =~ file end end end end ruby-bdb-0.6.6/examples/cursor.rb000077500000000000000000000014241154714021300167130ustar00rootroot00000000000000#!/usr/bin/ruby require './clean.rb' BDB::Env.cleanup("tmp", true) db = BDB::Btree.open "tmp/cursor", nil, BDB::CREATE | BDB::TRUNCATE, 0644, "set_pagesize" => 1024, "set_flags" => BDB::RECNUM indice = 0 File.foreach("wordlist") do |line| line.chomp! line = format("%05d", indice) + line db[indice] = line.reverse indice += 1 end print "======== db.stat\n" db.stat.each do |k, v| print "#{k}\t#{v}\n" end print "===============\n" total = db.stat["bt_nrecs"] cursor = db.cursor 10.times do indice = rand(total) k, v = cursor.set_recno(indice + 1) print "Recno : #{indice}\t: #{k} -- #{v}\n" k, v = cursor.next print " NEXT\t: #{k} -- #{v}\n" k, v = cursor.prev print " PREV\t: #{k} -- #{v}\n" end cursor.close db.close ruby-bdb-0.6.6/examples/func.rb000077500000000000000000000012451154714021300163320ustar00rootroot00000000000000#!/usr/bin/ruby require './clean.rb' BDB::Env.cleanup("tmp", true) module BDB class Btreesort < Btree def bdb_bt_compare(a, b) b.downcase <=> a.downcase end end end a = { "gamma" => 4, "Alpha" => 1, "delta" => 3, "Beta" => 2, "delta" => 3} env = BDB::Env.open "tmp", BDB::CREATE | BDB::INIT_MPOOL db = BDB::Btreesort.open "alpha", nil, "w", "env" => env a.each do |x, y| db[x] = y end db.each do |x, y| puts "SORT : #{x} -- #{y}" end db.close db = BDB::Hash.open "alpha", nil, "w", "env" => env, "set_h_hash" => lambda { |x| x.hash } a.each do |x, y| puts "#{x} -- #{y}" db[x] = y end db.each do |x, y| puts "HASH : #{x} -- #{y}" end ruby-bdb-0.6.6/examples/join.rb000077500000000000000000000027211154714021300163360ustar00rootroot00000000000000#!/usr/bin/ruby require './clean.rb' if BDB::VERSION_MAJOR == 2 && BDB::VERSION_MINOR < 6 raise "join exist only with db >= 2.6" end BDB::Env.cleanup("tmp", true) module BDB class Btree def cursor_set(a) c = cursor c.set(a) c end end end primary = { "apple" => "Convenience Store", "peach" => "Shopway", "pear" => "Farmer's Market", "raspberry" => "Shopway", "strawberry" => "Farmer's Market", "blueberry" => "Farmer's Market" } sec1 = { "red" => ["apple", "raspberry", "strawberry"], "yellow" => ["peach", "pear"], "blue" => ["bluberry"] } sec2 = { "expensive" => ["blueberry", "peach", "pear", "strawberry"], "inexpensive" => ["apple", "pear", "raspberry"] } env = BDB::Env.open "tmp", BDB::INIT_MPOOL | BDB::CREATE | BDB::INIT_LOCK p = BDB::Btree.open "primary", nil, BDB::CREATE, "env" => env primary.each do |k, v| p[k] = v end s1 = env.open_db BDB::Btree, "sec1", nil, BDB::CREATE, "set_flags" => BDB::DUP | BDB::DUPSORT sec1.each do |k, v| v.each do |v1| s1[k] = v1 end end s2 = BDB::Btree.open "sec2", nil, BDB::CREATE, "env" => env, "set_flags" => BDB::DUP | BDB::DUPSORT sec2.each do |k, v| v.each do |v2| s2[k] = v2 end end print "red AND inexpensive\n" p.join([s1.cursor_set("red"), s2.cursor_set("inexpensive")]) do |k, v| print "\t#{k} -- #{v}\n" end print "expensive\n" p.join([s2.cursor_set("expensive")]) do |k, v| print "\t#{k} -- #{v}\n" end s1.close s2.close ruby-bdb-0.6.6/examples/lock.rb000077500000000000000000000014761154714021300163350ustar00rootroot00000000000000#!/usr/bin/ruby require './clean.rb' Dir.mkdir 'zippy' unless File.directory? 'zippy' BDB::Env.cleanup("zippy", true) lockenv = BDB::Env.new('zippy', BDB::INIT_LOCK | BDB::CREATE) lockid0, lockid1 = lockenv.lock, lockenv.lock zappy, zippy = "zappy", "zippy" lock = lockid0.get(zappy, BDB::LOCK_WRITE) begin lock = lockid1.get(zappy, BDB::LOCK_WRITE, BDB::LOCK_NOWAIT) rescue BDB::LockGranted puts "OK must failed" rescue puts "not OK must give BDB::LockGranted not #$!" else puts "not OK must failed" end lock.put lock = lockid0.vec [{"op" => BDB::LOCK_GET, "obj" => zappy, "mode" => BDB::LOCK_WRITE}] lock = lockid0.vec [{"op" => BDB::LOCK_PUT, "lock" => lock[0]}, {"op" => BDB::LOCK_GET, "obj" => zippy, "mode" => BDB::LOCK_WRITE}] lock[1].put lockenv.lock_stat.each do |k, v| puts "#{k}\t#{v}" end ruby-bdb-0.6.6/examples/log.rb000077500000000000000000000024561154714021300161650ustar00rootroot00000000000000#!/usr/bin/ruby require './clean.rb' BDB::Env.cleanup("tmp", true) env = BDB::Env.open "tmp", BDB::CREATE | BDB::INIT_LOG, "thread" => false lsn = [] 100.times do |i| lsn.push(env.log_put("test toto #{i}")) end env.log_flush i = 0 env.log_each do |l,| if l != "test toto #{i}" puts "Error #{i} -- #{l}" end i += 1 end i = 99 env.log_reverse_each do |l,| if l != "test toto #{i}" puts "Error #{l}" end i -= 1 end 1000.times do nb = rand(lsn.size) if lsn[nb].log_get != "test toto #{nb}" puts "Error #{nb}" end end env.close BDB::Env.cleanup "tmp" max_log = 45000 env = BDB::Env.open "tmp", BDB::CREATE | BDB::INIT_LOG, "thread" => false, "set_lg_bsize" => 10000, "set_lg_max" => max_log init = "a" * 200 lsn = [] rec = [] 500.times do |i| j = env.log_put "init %d" % i if (i % 25) == 0 rec.push "init %d" % i lsn.push j end end env.log_flush log_file = Dir.glob("tmp/log*") l = nil lsn.each_with_index do |ls, i| if l if ls <= l puts "Error compare" end end if ls.log_get != rec[i] puts "Error retrieve" end l = ls end lsn.each do |ls| if !log_file.include? ls.log_file puts "Error #{ls.log_file}" end end env.log_stat.each do |k, v| puts "%s\t%s" % [k, v] end env.close BDB::Env.cleanup "tmp" ruby-bdb-0.6.6/examples/queue.rb000077500000000000000000000004261154714021300165230ustar00rootroot00000000000000#!/usr/bin/ruby require '../src/bdb' db = BDB::Queue.open "set_re_len" => 42 File.foreach("queue.rb") do |line| db.push line.chomp end db.each do |x, y| p "#{x} -- #{y}" end p db.shift print "====> STAT\n" db.stat.each do |k, v| print "stat #{k} : #{v}\n" end db.close ruby-bdb-0.6.6/examples/recno.rb000077500000000000000000000010431154714021300165010ustar00rootroot00000000000000#!/usr/bin/ruby require './clean.rb' BDB::Env.cleanup("tmp", true) out = open("tmp/recno.rb", "w") File.foreach("recno.rb") do |line| out.print line end out.close db = BDB::Recno.open nil, nil, "set_re_source" => "tmp/recno.rb", "set_flags" => BDB::RENUMBER | BDB::SNAPSHOT print "====> BEFORE\n" db.each do |k, v| print "line #{k} : #{v}\n" db[k] = nil if /^db/ =~ v end print "====> AFTER\n" db.each do |k, v| print "line #{k} : #{v}\n" end print "====> STAT\n" db.stat.each do |k, v| print "stat #{k} : #{v}\n" end db.close ruby-bdb-0.6.6/examples/record.rb000077500000000000000000000017251154714021300166600ustar00rootroot00000000000000#!/usr/bin/ruby -I../src require './clean.rb' BDB::Env.cleanup("tmp", true) module BDB class Bcomp < Btree extend Marshal def bdb_bt_compare(a, b) a <=> b end end end record1Class = Struct.new('Record1', :f1, :f2 ,:f3) record2Class = Struct.new('Record2', :f3, :f2 ,:f1) File.delete('tmp/hash1.bdb') if File.exists?('tmp/hash1.bdb') hash1 = BDB::Bcomp.create('tmp/hash1.bdb', nil, "w", 0644, 'set_pagesize' => 1024) f1 = 'aaaa' f2 = 'lmno' f3 = 'rrrr' 100.times do |i| rec1 = record1Class.new rec1.f1 = f1 = f1.succ rec1.f2 = f2 = f2.succ rec1.f3 = f3 = f3.succ hash1[rec1.f1] = rec1 end File.delete('tmp/hash2.bdb') if File.exists?('tmp/hash2.bdb') hash2 = BDB::Bcomp.create('tmp/hash2.bdb', nil, "w", 0644, 'set_pagesize' => 1024) hash1.each do |k,rec1| rec2 = record2Class.new rec2.f1 = rec1.f1 rec2.f2 = rec1.f2 rec2.f3 = rec1.f3 hash2[rec2.f1] = rec2 puts "Record2 #{hash2[rec2.f1].inspect}" end ruby-bdb-0.6.6/examples/replication/000077500000000000000000000000001154714021300173565ustar00rootroot00000000000000ruby-bdb-0.6.6/examples/replication/base/000077500000000000000000000000001154714021300202705ustar00rootroot00000000000000ruby-bdb-0.6.6/examples/replication/base/b.rb000077500000000000000000000063621154714021300210500ustar00rootroot00000000000000#!/usr/bin/ruby require './op.rb' require './mc.rb' require './ma.rb' require './cl.rb' Dir.mkdir($home) if !File.exist? $home $db = "test" $master = $master ? BDB::MC::ENVID : BDB::EID_INVALID $env = BDB::MC.new($home, $totalsites, $priority, $timeout) Thread.abort_on_exception = true def display_message(mess) puts "===> #{mess}" end def elections(tiout = 2, max = 5) display_message("Beginning an election") count = 0 begin $master = $env.rep_elect *$env.param rescue if count >= max display_message("Forcing the election") $master = BDB::MC::ENVID else display_message("retrying ...") count += 1 sleep tiout retry end end if $master == BDB::MC::ENVID display_message("Won the election") else display_message("The new master is #{$env.mach_name($master)}") end end def hm_loop(sock, host, addr) eid = $env.add_mach(sock, host, addr) display_message("new client #$me -- #{host}:#{addr}") Thread.new do election = nil while true record, control = $env.comm(eid) if ! record break if $master == BDB::MC::ENVID || $master != eid $master = BDB::EID_INVALID elections(1, 2) if $master == BDB::MC::ENVID do_master end break end res, cdata, envid = $env.rep_process_message(control, record, eid) case res when BDB::REP_NEWSITE display_message("REP_NEWSITE #{cdata}") if cdata != $me begin connect_site(cdata.split(/:/)) rescue break end end when BDB::REP_HOLDELECTION display_message("REP_HOLDELECTION") if $master != BDB::MC::ENVID if election election.join election = nil end election = Thread.new do elections if $master == BDB::MC::ENVID $env.rep_start nil, BDB::REP_MASTER end election = nil end end when BDB::REP_NEWMASTER display_message("REP_NEWMASTER #{envid}") $master = envid do_master() if envid == BDB::MC::ENVID when 0 when BDB::REP_DUPMASTER display_message("REP_DUPMASTER") $env.rep_start $me, BDB::REP_CLIENT elections if $master == BDB::MC::ENVID do_master() else do_client() end when BDB::REP_ISPERM display_message("REP_ISPERM") when BDB::REP_NOTPERM display_message("REP_NOTPERM") when BDB::REP_IGNORE display_message("REP_IGNORE") else display_message("error #{res} #{cdata} #{envid}") end end $env.remove_mach(eid) election.join if election end end def connect_site(site) return if $me == site.join(":") s = TCPSocket.open(site[0], site[1]) hm_loop(s, site[0], site[1]) end connect_thread = Thread.new do server = TCPserver.open($port) loop do ns = server.accept addr = ns.peeraddr hm_loop(ns, addr[2], addr[1]) end end connect_all = Thread.new do others = $others.dup while ! others.empty? todo = [] others.each do |site| begin connect_site(site) rescue todo << site end end others = todo sleep 1 end end if $master == BDB::MC::ENVID do_master else do_client end connect_all.join connect_thread.join ruby-bdb-0.6.6/examples/replication/base/cl.rb000066400000000000000000000014461154714021300212200ustar00rootroot00000000000000#!/usr/bin/ruby def do_client $env.rep_start $me, BDB::REP_CLIENT sleep 5 Thread.new do db = '' begin db = $env.open_db(BDB::BTREE, $db, nil, "r") rescue sleep 5 retry end while true break if $master == BDB::MC::ENVID display_message("content #{Time.now}") db.each do |k, v| puts "#{k} -- #{v}" end sleep 3 end db.close end Thread.new do count = 0 while $master == BDB::EID_INVALID if (count % 2) == 0 $env.rep_start $me, BDB::REP_CLIENT else begin $master = $env.rep_elect *$env.param rescue BDB::RepUnavail if ($env.empty? and $env.priority > 0) || count > 10 do_master end end end count += 1 sleep 1 end end end ruby-bdb-0.6.6/examples/replication/base/ma.rb000066400000000000000000000010431154714021300212100ustar00rootroot00000000000000#!/usr/bin/ruby def do_master $master = BDB::MC::ENVID $env.rep_start nil, BDB::REP_MASTER db = $env.open_db(BDB::BTREE, $db, nil, "a") Thread.new do while true print "#{Time.now}> " $stdout.flush line = gets break if !line line = line.chomp.downcase if /(.*?)\s/ =~ line db[$1] = $' else case line when "exit", "quit" puts "at exit" db.each do |k, v| puts "#{k} -- #{v}" end exit else puts "error : TICKER VALUE" end end end end end ruby-bdb-0.6.6/examples/replication/base/mc.rb000066400000000000000000000046351154714021300212240ustar00rootroot00000000000000#!/usr/bin/ruby $LOAD_PATH.unshift Dir.pwd.sub(%r{(bdb-\d\.\d\.\d/).*}, '\1src') require 'bdb' require 'mutex_m' require 'socket' module BDB class MC < Env extend Mutex_m ENVID = 1 attr_accessor :sites, :priority, :timeout def initialize(home = nil, sites = 4, pri = 10, timeout = 2000000) @sites, @priority, @timeout = sites, pri, timeout @mach = {} super(home, BDB::THREAD | BDB::CREATE | BDB::INIT_TRANSACTION | BDB::INIT_REP, "set_verb_replication" => 0) end def param [(@mach.empty? ? @sites : @mach.size), 1] end def empty? @mach.empty? end def mach_name(eid) @mach[eid] && @mach[eid][0, 2].join(':') end def add_mach(f, h, a) @eid ||= 2 self.class.synchronize do @mach.each do |eid, inf| host, addr, = inf return eid if h == host && a == addr end @eid += 1 @mach[@eid] = [h, a, f] end @eid end def remove_mach(eid) self.class.synchronize do @mach.delete(eid) end end def comm(eid) return nil unless @mach[eid] res, s = "", @mach[eid][2] nb = s.sysread(10) nb = nb.to_i while res.size < nb res << s.sysread(nb - res.size) end return nil if res.size < nb Marshal.load res rescue remove_mach(eid) return nil end def bdb_rep_transport(control, rec, lsn, eid, flags) self.class.synchronize do case eid when BDB::EID_BROADCAST new = {} aa = Marshal.dump([rec, control]) @mach.each do |neid, mach| begin mach[2].syswrite("%010d" % aa.size) if mach[2].syswrite(aa) == aa.size new[neid] = mach end rescue end end @mach = new return 0 when BDB::EID_INVALID puts "received INVALID" return 0 else @mach.each do |neid, mach| if neid == eid aa = Marshal.dump([rec, control]) begin mach[2].syswrite("%010d" % aa.size) if mach[2].syswrite(aa) == aa.size return 0 end rescue end return BDB::REP_UNAVAIL end end raise BDB::Fatal, "cannot find #{eid}" end end end def open_db(*args) db = super db.instance_eval <<-EOT def []=(a, b) env.begin(BDB::TXN_COMMIT, self) do |txn, db1| db1.put(a, b) end end EOT db end end end ruby-bdb-0.6.6/examples/replication/base/op.rb000066400000000000000000000023611154714021300212350ustar00rootroot00000000000000#!/usr/bin/ruby require 'getoptlong' parser = GetoptLong.new parser.set_options( ['--master', '-M', GetoptLong::NO_ARGUMENT], ['--client', '-C', GetoptLong::NO_ARGUMENT], ['--home', '-h', GetoptLong::REQUIRED_ARGUMENT], ['--me', '-m', GetoptLong::REQUIRED_ARGUMENT], ['--nsites', '-n', GetoptLong::REQUIRED_ARGUMENT], ['--other', '-o', GetoptLong::REQUIRED_ARGUMENT], ['--priority', '-p', GetoptLong::REQUIRED_ARGUMENT] ) $home, $port, $others = "test", 5000, [] $priority, $totalsites, $timeout = 10, 4, 1000000 client = false parser.each do |name, arg| case name when '--master' raise "can't be a client and a master" if client $master = true when '--client' raise "can't be a client and a master" if $master client = true when '--home' $home = arg when '--me' $me = arg $port = $me.split(/:/)[1] when '--nsites' $totalsites = arg.to_i when '--other' $others ||= [] raise "bad host specification, expected host:port" unless /:\d+$/ =~ arg $others.push arg.split(/:/) when '--priority' $priority = arg.to_i end end ruby-bdb-0.6.6/examples/replication/example000066400000000000000000000003111154714021300207270ustar00rootroot00000000000000cd {base|mgr} rm test?/* b.rb -M -h test1 -n 3 -p 100 -m some.host:5000 b.rb -C -h test2 -n 3 -p 50 -m some.host:5001 -o some.host:5000 b.rb -C -h test3 -n 3 -p 20 -m some.host:5002 -o some.host:5000 ruby-bdb-0.6.6/examples/replication/mgr/000077500000000000000000000000001154714021300201435ustar00rootroot00000000000000ruby-bdb-0.6.6/examples/replication/mgr/b.rb000066400000000000000000000071701154714021300207160ustar00rootroot00000000000000#!/usr/bin/ruby $LOAD_PATH.unshift Dir.pwd.sub(%r{(bdb-\d\.\d\.\d/).*}, '\1src') require 'bdb' require 'getoptlong' $master = false def process_args parser = GetoptLong.new parser.set_options( ['--master', '-M', GetoptLong::NO_ARGUMENT], ['--client', '-C', GetoptLong::NO_ARGUMENT], ['--verbose', '-v', GetoptLong::NO_ARGUMENT], ['--home', '-h', GetoptLong::REQUIRED_ARGUMENT], ['--me', '-m', GetoptLong::REQUIRED_ARGUMENT], ['--nsites', '-n', GetoptLong::REQUIRED_ARGUMENT], ['--other', '-o', GetoptLong::REQUIRED_ARGUMENT], ['--priority', '-p', GetoptLong::REQUIRED_ARGUMENT] ) policy = BDB::REP_ELECTION home = "test" message = { BDB::EVENT_PANIC => "EVENT_PANIC", BDB::EVENT_REP_STARTUPDONE => "EVENT_REP_STARTUPDONE", BDB::EVENT_REP_CLIENT => "EVENT_REP_CLIENT", BDB::EVENT_REP_ELECTED => "EVENT_REP_ELECTED", BDB::EVENT_REP_MASTER => "EVENT_REP_MASTER", BDB::EVENT_REP_NEWMASTER => "EVENT_REP_NEWMASTER", BDB::EVENT_REP_PERM_FAILED => "EVENT_REP_PERM_FAILED", BDB::EVENT_WRITE_FAILED => "EVENT_WRITE_FAILED" } opt = {'set_event_notify' => lambda {|e| puts "Received #{message[e]}" $master = true if e == BDB::EVENT_REP_MASTER $master = false if e == BDB::EVENT_REP_CLIENT }} opt['rep_set_priority'] = 100 parser.each do |name, arg| case name when '--master' policy = BDB::REP_MASTER when '--client' policy = BDB::REP_CLIENT when '--home' home = arg when '--me' me = arg raise "bad host specification, expected host:port" unless /:\d+$/ =~ arg me = me.split(/:/) raise "bad host specification, expected host:port" unless me.size == 2 opt['repmgr_set_local_site'] = me[0], me[1].to_i when '--nsites' opt['rep_set_nsites'] = arg.to_i when '--other' me = arg raise "bad host specification, expected host:port" unless /:\d+$/ =~ arg me = me.split(/:/) raise "bad host specification, expected host:port" unless me.size == 2 opt['repmgr_add_remote_site'] = me[0], me[1].to_i when '--priority' opt['rep_set_priorityrity'] = arg.to_i when '--verbose' opt['set_verb_replication'] = 1 end end unless home && opt['repmgr_set_local_site'] raise "home or local_site must be specified" end [home, policy, opt] end home, policy, opt = process_args Dir.mkdir(home) unless File.exist? home env = BDB::Env.new(home, BDB::THREAD | BDB::CREATE | BDB::INIT_TRANSACTION | BDB::INIT_REP, opt) env.repmgr_start(3, policy) flags = 0 flags = BDB::CREATE if $master bdb = nil loop do print "QUOTESERVER#{$master?'':' (read only)'}> " line = STDIN.gets break if !line line = line.strip.downcase case line when "exit", "quit" puts "at exit" break end key, value = line.split(/\s+/, 2) if bdb.nil? begin bdb = env.open_db(BDB::BTREE, 'quote.db', nil, BDB::AUTO_COMMIT | flags) rescue if $master puts $! exit end puts "Not yet available" next end end if key.nil? puts "\tSymbol\tPrice" puts "\t======\t=====" bdb.each {|k, v| puts "\t#{k}\t#{v}" } next end if !$master puts "Can't update at client" next end bdb.put(key, value, BDB::AUTO_COMMIT) end bdb.close env.close ruby-bdb-0.6.6/examples/txn.rb000077500000000000000000000022151154714021300162060ustar00rootroot00000000000000#!/usr/bin/ruby require './clean.rb' BDB::Env.cleanup("tmp", true) module BDB class ThreadHash < Hash def start(val, num) Thread.start do self.env.begin(self) do |txn, b1| p "Thread #{num} Enter" b1.delete_if do |k, v| print "\t#{num} #{k} -- #{v}\n" k == val end p "Thread #{num} Pass" # Thread.pass b1.each do |k, v| print "\t#{num} #{k} -- #{v}\n" end if num == 1 txn.abort else txn.commit end end p "End Thread #{num}" end end end end env = BDB::Env.new("tmp", BDB::CREATE|BDB::INIT_TRANSACTION) db = env.open_db(BDB::ThreadHash, "txn", nil, BDB::CREATE) {"alpha" => "beta", "gamma" => "delta", "delta" => "epsilon"}. each do |key, value| db[key] = value end db.each do |k, v| print "0 #{k} -- #{v}\n" end t1 = db.start("alpha", 1) t2 = db.start("gamma", 2) t1.join t2.join db.each do |k, v| print "0 #{k} -- #{v}\n" end env.close ruby-bdb-0.6.6/examples/wordlist000066400000000000000000002701141154714021300166440ustar00rootroot00000000000000asceticism chronicler ale champaign bulkhead cattle creed arbitrator constitute accumulator butted calculate charitableness bas blinders animator's classifications admonition chronicles boomtown's consider backache's bars bury clattering brooch's crossbar articulate carton amphibious bessel affinity's bronzed airy burrowing coordinating acquiescing breweries ancestors comparator abstractness conquerors beetle consume audaciously axon cataract awakes breeze capture clinging capitalizers booze cremation aglow burlesque broadening besotted arching camels archdiocese bartender's antipodes bleating buffer's creative bashes conceptions bleeder axiological blankest bubbling andorra apocrypha airships battalions belfries concomitant castes bedrock's acceptability bulkhead's appointment conscious adventists bipartite boatloads aerodynamic bucket's babyish billers chastely browbeaten attorney's convincingly alerting criticizes avoiding corollaries arithmetic confidant airway cancers abhorrer antinomian annuls commemorates clamped boggle allegedly ancestral cabins complicator ablute bondsman belligerently appurtenances collaborated abstractor's cheapening aniseikonic admitters aperiodicity aesthetic blacklisting bib's bleak conversantly boatyard's beautifully bypassing comments cascading choker chime's crib abstracting apprises blitz's britons bugger's accusations angers caught concretion annul criers bookish asterisk's cartography backarrows chaps coincidences byproducts communicant's automate arachnids afflictions affliction's authorized adjective came cements asunder accession clouded amalgam's couple calamities correcting coronets bellhop's audience apocalypse admitted chases crossover's certifies cheapness backplane's amend bodice broadcastings certifiers accompanies assessed brat cries clarifies antennas aspiring anywhere brochure chained anguish audiologist brusque bodybuilder's bygone collaborative anticipated animate coarsely complicator's concealer craving breastwork's bailiff's are aviator cheerless acknowledgment's auscultations bikini's anachronism colonization bodied bemoans big brightened brittleness betrothed controllers convict ambition's bijection's crawlers bodyguards cataloger couldn't attribute confirmation's confronted crudeness booklet aught activate bash childish catalyst's characterization's adaptive combination's cheerful condemn bankrupt computability bully accidents coalesce belonging buff colossal associativity ascendent aunts consumption's abstaining communes bodies anchor codifier's budge cricket cripple canyons bleakly august atmosphere's arbitrarily crab aspiration's bunny advancements calming blinded binuclear commercialness clanging amputated bathrobes appellant argot blossomed altering commands connotes captivate affair cartoon aversions connectivity bookkeeper blast attending beef contradictions cashed compressed assure brunch crowded absorber alternate arbitration communicants chiseler bauble beaters alabamian backtracked criticized breathers comfortably bimodal champagne conflict contraption cautious chores acquisitiveness crow contingent's amazon communion antenna's bottlenecks coronary amended claws bungling buyers bottleneck confronters cowling codifiers counseling counsels bellwethers binocular bowed articulates beefs admonishing brigs cooing boy bullets constable alluding couriers clippers aphid's centralizes compiler's communicating chilled clinked cocktail clawing assist comprehensibility camping chivalry authorizer come arrowheads antigens armpits attune correct caveats backgrounds abased alchemy confuser bramble aerating clocks breakable categorically cleverest assisting bind aftershock coaching arctic bayed bloke's compartmentalizes confinement brother's creamers advisably capacious corroborating chancellor bier capitalization cloudless censuses cringed astounding acidulous conception's clearance's cooped avalanched chaser actuals assailed continuation averted commutativity bunted crossed awls belonged admix augmented crest cascade coroutines brilliancy abiding compel anticipates brays affective animating auditory bibs crazing assassinations balm belittling checksum's citizen causation commissioner barrelling collapse aborting coroutine's blight acknowledging arteriole creaks caged adjudicating almanac's crew bundled backdrops blocked balms appointees centralization cabinets connective bedroom adaptors capping browbeat commodores centerpiece constrained closenesses antiquarian's compounded bridgehead aqueducts coveting bouncing clumps conveniences benignly completion competitor boomtown commandants astronautics affects clustering benefiting bridged bead acolytes broil blanches archaeology amaze artillerist considers boosting accumulated alaska abolitionist beverage's cottager agonize camouflaging airframes conjuncted counteract cautiousness assaying affirming accusingly beachheads babying arguer cleft crag's bedrooms aesthetics age comprehended complicated angled amphetamines apportioning addresses brings clink apparatus admitting aesthetically clutching aloe bevel clerks conflicts blimp's ameliorate breeding counsellors consciences cravats campuses chasing bugs agar am blanch amuses bigots antithesis cohering axolotls badness colliding adopts alumnae accompany barbs challenged arteriolar cleansers bookie's consciousness assertion ameliorating adhesion bookcase beginnings continuance's brimful calorie crater appreciable closure bowel's adamant classified circus's adieu amphibology bazaar bedspread's bans cower coloring bengali breachers cheapest contradistinction catholics bayou cruelest biplane's bunch botanists comer campus broadcast cataloged apparently corn calm companies accordingly appealing burghers amoral adhered ballet additional carbonizers bid's ascend ablest arabesque aye benighted additive crankier calendar's availably calibrations codeword aforesaid balmy addition's crosses banker consumers agenda's bragged average alleviates crevices barbarian badger crazed assimilating clinically caps arizona blindfolded brushfire's coarse contingents animator baptist's comedy combinatorics affiliate chambered colonizers charmingly babble beauty's courtroom's creation achievement bounties cliches catalysts attendances corporal's crouched chasers arrogated arrogant bespeak barnstorming compiled archery butterfat airstrip's abdomens apologize affecting adds amalgamating beats between competitively betterments attenuates awhile basics complains barium chairperson angered applicability buyer's admonishment calamity's consciously archipelago airfoil attendants bunters bookkeeping adapters amusement backslashes courageously bellies absentee corrupted cowl blustering artfulness admission book accosts cleanses booklet's ballpark's breadwinner's blabbing anglicans beers angle animized channellers classmate boor arranges bless bellowing aviary code casts ballot's airlocks confinements commencement counterexamples asiatic autograph anxious behaviorism beryl contoured advisement bodybuilder actors apartment's anchorage's bruises adduction creamy backspace competence contraction bounden aliased boron calmingly commonest chute's allah abstinence binds bosses abrasion cobbler's controversies arms compactly acquisitions clothing affiliation armour blacksmiths ascent astronomer's clan checks advocates cathedral cognition broadeners census's avenger botchers antiphonal annihilates bloat cancel allegiances borough ardently bitter archaicness cornerstone chiefly collecting black brain brighteners coercing bath billings bauxite anarchists bequests battered clangs arboreal abnormality cdr congregated confederate ambivalent avouch adducted accompanist's abysmally avenged baptize consumptively consideration basket's bobwhite's ass's coasts an asymmetry anymore clown confusers chosen cabin cargo coasting beagle's accorders baleful armed bothersome blonds bookkeepers carbonates crop clues coverlet barter benefit bases affected brightest cinder's anchoring advisee argos airstrip confidant's antimicrobial berate celebration cheek bondage comely butane citadels countered bobbin's commutative clarified blackjacks brimmed buzzed chemists castles crescent's choppers buzzwords biases apprising balanced auras company's confiscates affirms bellwether admired clones boatman arab catalyst begets contraptions absolutely chuckled amplitudes agitating alkaloid abutted circumvents conjecturing bastards astronomical accessory accommodations carol braving correlation axles brushy assume act canada aerator beadle's blabs avail clinic behold boyhood antennae continuation's apple agent bandying clime changeably bootstrap's croaks autocracies baptismal countable apportionment acre biofeedback accumulates cannot catered crave appointment's bending cooperations australia consumes alphabetizing breakfasters captor accompanists confession baffled crabs cornerstones breather additive's betting coaxed court comparative construe bearably advocated boisterously arrogating consumptive crueler conveyers coop contrasters berry's channeled berries columnized anecdotal abolishes cajoling carved buckled arched appearances biting broaching behaves celery analytic adaptable beaks coalition annual acrylic agape abridge afghans amphibiously blaming bucked chop coke backlash colleague's commander assertively asteroidal archbishop adsorb almond aspect bricker aliens coached ambiguities awesome altos commemorate balance condensing attributions abrades attached awaken atrophy billions brazes counterrevolution choruses counselling brewing adrift coupon checked chair below chips ablaze botching attraction causes battlegrounds assertions buy coin befouling coverlet's admirer career barnyards brochure's contrives asserts cleaved cannister contrastingly blending boggling awaits congregating bandit's anacondas chimney's adhesions bandaging audacity blot's bathing blunting bequest's any backs certifier bloke carbon's breveted altered antic convertibility amassing admission's bracing canton borrow company camera's absentee's advisability blackboard's crickets buckboard's allocators collected biopsy boldly canoe's altogether breads autonavigators bilges combed basses broadly classifies blend bereavement another's backward beater clambered congressionally acculturation capped adventuring appeases buoyancy bridesmaid's converges biographical aftermath audiometry affixed bytes astrophysical chorus boastful administratively causation's cogently creators comrade calculative anemometry bullies bulletin's cashiers clockers certified canonically ambulatory chaplain's chubby articulately context america's anger cranky aspersions countries communicator chroniclers coronet barest boxed compatibility amateur characterizing contemplations agreements caw anodes blazes concurrence anachronisms county commends cliques correspondingly busboys approve absconding barbarities absorptions cider aggravation capturing braid bonds clam commonality artichoke's bringer alters authorizers beginning's bounded candor chancing agitated approachers covets cools bluebonnet boomerang apprehensively bickers banshee's checksums anteater airstrips bevels bedtime arsine campaigned aggressive avoid accelerate copings armies astuteness blips compilation's bureaucrat's bandages brainy canonicalize booms charmers capturers applicable alas academy brawl bangs atypical crooks consuls antelopes bladder's crucial bottles binge abscesses analog blurs columnize buns accountancy ardent achievement's corrective afferent anthem's adsorbing abutment averting blackberries agate allegation's anonymity boor's airfields commence collier bedspreads channels bisection's appellants councillor's arguable anomalies armor alienates absolving basset combat crimson contributing acutely bachelor breasted accumulators censure abscissas cots boll aspirating browbeats abet blanketing craziest boomtowns aberrant adequacy alleles adulterated buzzer banging aren't accumulating bondsmen centralized appreciative aggressively colonized bifocals activist anniversaries cradled arithmetize chemistries choose bedbug's celebrates converter bunkmates coyote baseline acrobat's arianists coach bedbug antibiotics collides contour cot's cloud asses conveniently birthed angels chronology confidentially consorts angola algorithm advertisements arrives claimable brag conclusions astringent commitments capitalists climbed bobbins ballerinas corkers bootstrap agitation comprising avid alibi's anesthetized argumentative boost appointed conservative baronial compelling breakfast congratulation antitoxin's alarmingly autographed backup bitwise compromised abolition boulders cane causality ambassador classifiers baggers boldface arguments chairs agonizes birches acoustically attendees accusal consigns condescending clique control's cells corridor's antithetical bandwagon amassed bikini ambivalently bridgeable bandstand's aureomycin commentary beatific coexisted arithmetizes appalled appetite combustion beauteous built animatedly catchers abjection antiquities brilliantly anode's cowardly concedes cohabitation contested bismuth coves banking clauses appropriating befriend academically breakdowns afresh brier contour's appease bantered astound advertisers benedictions addressable complaint's arose burgeoning automatically crackles abducted bluing comparatively butchery bridesmaid blurting confuses complemented annotation bafflers absorption's announcements affirmatively cantor's assertive automotive bicyclers beholding bootstrapping angiography amphibian's colored algebraically coordinated bibliographical aqueduct's atheist circle contrived asians cancer's applicator's balloons attempter airs barkers apparent balancers berlin bravest adjustor ameliorated algol buildings contacted clock bedders conjuring cantankerously accountably bibliography canvasser bulging collector's ascription anchovies babied bridges bassinets crawls chestnut's barrage's aside correctly capitalized babyhood collection's bookkeeper's correspondent's aflame belays bordellos animated apologizes achievements alleging crowning criticised actuarially athletics belles cab allay blamable constellation attract bunnies bushwhacks bartender conference's battlefront's arterial boring adulterate alarm counts alphabetized considerations bisector connection browning bravura catcher blocks affirmations barren bufferrer backwater confined bungled casualness creature benders bleedings bathtub colon aborted conquer advancement americas advising bibliophile coronet's administer bombards contaminated arousal assuming condemned ampoule's assenting courting attunes adoptions anabaptist's bedder's applied bonnets arise bulb becalming biographer contradicts breed angularly cocked chatter boatload as broadener cache columnates clays capitalize armament browned aquifer continuities colony ancestry clam's backing counterexample abridging broadcasting beaming constructively betters combing belly credibly corps comedian's comfortabilities belie convoys crossbar's chanticleer's amelia apologized avionics conversant batons considerate burgher closer alleys chloroplast's bootleger buffered acidic advertise brute's buff's concealing criticise ash college's accredit abridged crowed considering begot alignment bylaw's beacon academies alleged adjusters battlements autocorrelation aperture arabs conjurer bones considerably capricious admonishes abrade aloha canonicalizes cot ashore celled cringes addresser continuum breeze's boosts abbreviates coasted cavern's catastrophe busy coercion busts clench bell boys beveled bellyfull courthouses billets bottled audition contest attractor bootstrapped clerking circumvented conquers aliment anesthetizing bathes continually conveyed banner's collapsed canvases analogue's contradiction's amorphously blitzkrieg backbends caveat's bankrupting conspiracies cardinal bicarbonate broiler abortive befogged crested bisection beatitude's crept assessors convinces aimed clasps camper accustom ballistic claimed croppers concatenate block connote adjustably continents appreciation connecting asteroid corpse's breathed abruptness calibers codification's albanians analyst's assessments abscissa benign classically bedraggle abash bride abducts ancestor's autonavigator's basing chivalrously conceptually advantaged butts compactors bake certainly byline's contingency antisera beatings audaciousness brasses concerning bit bobs counterpart's accepters boxing bestowal circuitously amorphous augur accesses belabors attraction's booting creditor clue's baptizing countryside characteristics complete coconut abstract bleached compensation confused coexist accustoming breakpoints cities attainably arena cinders antipode backwaters corrupting carder also arthritis blackmailed cobweb's bandage broadest abeyance broadband adequate adversity appropriators ascending business's ambled chide capitalist cellar cosmology audiograms abating blimps bet's blaster businessmen bricklayer's bracelet contractual cherished antiresonator burp braced conduction analogues blockhouse basted ballooning bolstered barbed characteristically bunk convenient broils boatmen addressees abolishment cemetery antecedent's accommodated canto countenance admixes arianism blazing bestow conspiracy aft autobiographical airfield's compartmentalized blasts airman commons alliterations biller aims compile counterpointing ascended brindled chandelier buoyed alleviating crudest cremated camouflage bog's contraster confer convenience courtier's bulldog admonish awarders arcade bloating adagios archived anesthesia bluster confirming afraid chinning bonfires courteously bravado bumble comet's coffees bookshelf's abode complication adumbrating archeological correlating apostrophes ambushes abusive chateau's allowances baselines concession's charmed authenticators attracted assembles babies blasphemousness cremating bubbles attainments bluish checkpoints banquet contemporariness bargain blacking committing caption abashes confessor aerates comical country's behest antinomy airing backstitch courtroom brunette bible's circumvent bilabial accusative clobbered bear cackles byte captivation cloning behavioral amends allocated boathouse blusters coursed alveoli cottage awareness ablate application's anglophobia bodyweight anachronism's caption's contains apartments approachability connectors acrid arduously cowslip's approximation arduous civilizations brayed communicate awning acclaims closet academy's achievers adjacent anarchist boomerangs brigade action charities auscultates concealers convention's arrangement adducing choice anion's contrive applicative accomplishments asters allocate chronologically claimant closed attacked artifacts bank bedroom's cannisters clobber becoming bandwagon's calorie's converse articulators abnormally abrading brunt broom's airbags allergy abreast adjusts alcibiades commutes appellate convicted aristotelian africans concatenating abductors actuarial commissions baud column ballgowns baking blitzes atoned acquire businesslike civic clover brands climaxes buzzes cobwebs conceiving allegiance's bushwhacking astonish betide argued bolt conquerer arsenals agrees continuing coefficients aeronautical academics caverns comparison autopsied auspiciously civil balcony championship's blockaded bulldozed blankly challengers confounds albeit berliners best atomizes allegretto awkward cathode's adoptive amps arm codifications changeable consequence's cranberries amenable blustered burnishing aspirators acoustic buries breadboard consumptions bedazzling causeways cousins bathrobe borneo carry crazily climbs crackled conspirator beautifier arbitrating concession cookery adultery conundrum's acquisition's blasphemed coops connoted communist's codeword's complainer authentically aerosols buckwheat abysses agitate bedside behoove absented continuances affronted ambulances ballast's cleanse blunted bend cautionings averse commissioning assembly belligerence commanded briton's abjectly console cookie contracts algaecide contractor bitch appointee avocation's complying asks coherently abodes croaking consolidates blasphemously braided atomize continuations broth crag booster anesthetic assessor convenes broods canoes cleaner's causeway's anthropological chirped bargaining bees centimeter aerobics clothed closures astronauts allows bridegroom circumlocution advisor's bloodhounds bogus besieged calculates agers bloodshed chain beachhead's attend bushel's booboo aspirations allot bent concentric aphasia burglarproofed christmas cooperator's construct balkanizing creature's cavalry backyard bestowed bruised bedspread bewails cohered bluebirds aggrieving berates addict conveyances civilian availability abbe captors antics acquired colorless barbarity attendance brilliance accessibility brotherliness bride's closeted bedridden annoyer conceptualizing abolitionists consented adopted convinced bathrobe's benediction's circumstances accumulations accurateness assumes bribing criticisms bra atheists anesthetizes concatenations brigadier cheapened anchoritism contemplated bushes bootlegged blackmailer comprehensively censor admissibility assayed abduct auscultated bromine courier's bely amusements bards auxiliary colleges alkali's colonial amenity chlorine condone appreciatively audiometric bustle chisels coons congresses choke animals askance amigo azalea's attiring consequents administration's comparably advantageous avenue ablative butterfly blaspheme acclimates bellboy cheated arrive chewer bargained busboy's boned canker alley circled abstentions agglomerates appointer composure admittance accuracies amateurish boosted agilely bellmen chin's briefing coolie's calmer centered absenteeism banshees change ascribes bruise charity counterpoint belted confiscating banquetings ceaselessness compare askew averred befogging blondes ballyhoo chore argonaut clambers acquits attendee abhorring bolted bedeviled brandish constructor's acceleration attains aerodynamics cooky bet appraisal's blackberry crashing boat brink aluminum countless ascends allotment complaint computerize ascertainable apace cracks consolidate brazier's crams breadboxes commencement's bartering appeasement copious bridal actively casting crews anchorite acrimonious client adhering answerable committees bayonets bloodstain's ceiling's announced consists bug correspondents carbonate commission anthropomorphic butterfly's apogee blip brutality anxiety admonished addressability anomaly condemns blocker corroborates annoyance concealed appendicitis cheese absolute broomstick's competent confidences confessor's apprise commercial brushing clanged avoidance california beckoned carolinas answerer conspired battlers anion auditorium anathema comforts afoul colonist's arguers aphorism borders approves bited belligerents cozy assemblages crisp accorder bludgeon banana bazaars acyclically artificially annotates contagion conveys collaborator's amoeba's assured businessman calves assyriology bylaws barbarians clause's aboveground buttered behaviorally activators bowstring's cleaner affectation's cleave buffet capitalism bifocal coroutine buds cognitive amendment brae's booming cautioned baller carbonizer bowls crucially bunion basketball atheist's become bunter booksellers antenna admonishments bantus amputate carpenter's actor's anchovy clears brews command's biomedical ashtray's boxers barbaric bask biplane crags breadbox clasp bewitches crawler calibrated beyond associative anaphorically bituminous credulousness blocking chamber axiomatization acts activating antislavery commences airlift's civilian's allowed commentator blandly attender basement's accompaniment approximated bufferrers bide conspirator's anyplace cages compelled campaigners butterflies chat bedevils amplifying breathe credulous apostles arcs befuddling avoided arabia autumns anointed bystanders corporacies abstained barrel's antlered accelerometer badly befit barley complicity blackening attempts browns brazed birdbath's benzene ascender academia constitutive bulldozer ahead belied agonizing bounced banned answered bubble bibbed attests blockers bumming conscience bisect beams appeared airer autistic communications crescent buffoons bladder allophones citation christian asking cornfield's avenging assigning comprehension canyon burgeon bypasses bowl bellows audiologists cohesiveness coatings crawl balkanized captives adapt accompaniment's battering bugle bellman contradict biddy aspic anticipation consuming accurate artfully coconuts clone conserve chalking condenser boasted cancellation's bewailed called ashman brood clarification archangels catastrophic brother bandied assuage cliche's cogitation churchyards beholder ambush conclusion's baroness allaying alphabetizes assets coupled agony beep cohere apes appreciated cashers baronies beg concealment adaptability bugger audition's buoys career's adjudicates alive braille astounds chase concept's bumblebees altercations caner bleaches boastfully administers alumnus conductor conceptualization affinity cager bagpipes boxer bay bouffant comptroller barn adaptively applier approach controlling ampoules attuned clusterings bench administered chronicled correction alleges annoyance's berry blacked artifact's cracking almonds clashes bucket coerce bail assuringly carters alertness absence chintz aryan charge blanket appendix's bussed bidding committed boners covenant attaching concerts bedazzles bluffing crankily compass bowdlerized click amplitude's birdied acquiescence belabored blindfolds contrasts boulder's antelope approximate bridled bill azimuth coolie atomizing blacken angst advisor communists connoisseur accentuate columnizing alliance's concentrate agitates citations autopilots auscultate corroborate ascertaining creek's bagatelle's braids concentrators blanked copy actress attesting amazers consistent accessor admiringly conceited commentators autonavigator breakwaters consequentiality acquittal beveling actinometer chimneys adjudicated awning's banjo blooming commentator's carrier casual chickadee apologies broadcaster amounted attendance's confidential chests churchly alpha amortized churchyard autographing beneficences craftsman across consequence appendices barons comfortingly beet's callous crevice biology absenting backstitches booted adversely cheers coexists alphabetical arraignment's adjustment afterthoughts baton cremates appendix basin's ceremony's coincidence's amputating acquitter asthma constructed comfortable conjectures accomplishing began afternoon's bushing christening chooser appointing constitution corset commodore appraises civilizes carriage billeted compactor's award brown brownest chariot bandstands cocks beaker averrer audits braces bin arrested coarseness blots breathes beaus accept bedevil bounty's coordinator adjourning algebra's cheese's accounting believers catalog axons circumlocutions actualization birthdays belfry cowed constellation's affection's certainty aviators bloodstream constructible compulsory citation's brothel apotheoses camera accretion corning bring brass addiction conjunct breech abundance blower belgium athenian alliterative assumption's bog acids acrimony brains arrestingly blasphemes buzzword circulating chin budgeters coils beaten battlefront cohesion accoutrement afford aquatic boycotts bloater bagging abstracted consenters baroque actuality counsellor's accordions canonicalizing chocolates bypassed cannon absconds chiffon cons cop anthem basalt barefooted conquest's bewailing annex broom apprentice aural authenticity corner antagonistic banister's arsenal catched breakfaster banners contrapositive blows barbecueing assimilate acquaint anticipations bedsteads bob's belittle born antisymmetry amputates blob's chew battlement arrogate confiscate becalm befits creaming boxwood cackling algorithmic constantly articulation cowslip axiomatically accessible borderings contaminates autos conceptualized arson confrontation's bumblebee's antifundamentalist accenting accounted bicycle compression anybody coupler bleachers afghan abstractor chickadees brakes conversational bishop's atop besieger abstracts borate brackets breakers bedlam assimilation atom's allies comprised bowstrings astonishment abasing circulated circumstantial breached cheat colder authority ballad coverings alternator blush cemeteries certifiable acclamation aeration accomplished burdened airways blissfully corresponds containable ague allots biceps convene cowering assassinating cessation accessor's benefits ashamed cents comparators advisee's calico courtiers birefringent blizzard's bunkhouse's boy's complexly afforded cascaded bootlegger bullish contenting compartmentalizing appointers consecration correspondence affianced armored awakening bleach catheter coughed cafe's compromisingly crashed counterfeiter affidavit aggressor crowned blistering anything adroit abatement beneath announcer barking convertible belay ail bumbled conditioners antarctica brake bearable civilization barber cleansing cleaving architecture adapts conditional amalgams contamination aimlessly assignable buggy counters civics cram complicating barer bites bossed ant characterizers axial clippings asymptote's bureaus attractively compels competed adopters baptistery blooded consultant carpets adjudicate civilization's ample cloudiest annoys april cigar colts bicep biomedicine coward camouflages collies converging beggars being conversely baseboards ah briefcase's coverable coarsen clamping baton's corroborations archiving alnico alluded classify crossable blinding circumflex assaulting beseeches conservationist's becalms beige cheerlessness chargers coarser abscond courser constructibility austria clams coachman attach blackbird's broadness basil champion ancient broken avows adorned authenticated brows broadened adore chock's abolishers ampersands aborigine boarder blockage's blurry crafty calendar brainstorm's attackable anhydrous break arena's briar brutalize adored arpeggio's absent caging apportionments carrot assents allocator's corrects bicker alcove antihistorical clergy countably artificial belong benched ceases chivalrous crashers coexistence cater checkbook's burgesses composing assurers belch coupling anyhow afflicted arcing bests concisely conception bulldog's baked captained conquered conceptualize casks antelope's cloned belt compendium bloodiest apostolic cheeriness army bronchioles begrudging adrenal canal comber asia cravat's assistant archaeologists authentic arbors butchered aimless cradles crate affectionately blared amplification appallingly adjudged apathy balling administering cooked acquiesces chronic aped befouls brokenness abbreviations breaks cheerfully bedbugs chock adjures accessions airlock alder aping bungler conceits authenticating baskets bisons acorns civilized conquering babe's brushes cash accosting affirmed borne chess constituent's buttonhole bisecting blow consonant's after bicameral beneficiaries befuddled axer cringing anaesthesia arbitrate clique's breach brushfires bitterly blithe burgess's contributes apiece blends agile columnate anonymously assigner capably coolers conjuncts blaze cheer afloat billionth closers auditioned analyzable bugled celestial confronter alike adequately cherub's antiques anding casing awfully beatnik bookie costuming accomplish artifices chastised boulevard batters chastisers corroboration angling anchors accentuates bankruptcy's angry acted antagonizing crowds cowerer brokers apportioned commemorated abortively commerce craft aftereffect audiological collective collars appropriately allegrettos commemoration arbiter application concur bombarded balustrades audiometer consequences buttonholes cerebral beside aristocrat boating completing beverage consulate's aristocratic cannibalizing billeting catching biological ceased bootstraps bankruptcy cleanest annulment confessions allegorically capes bearings chilly composition agglomerated cooperates beautiful brainwashes bobby bangladesh applauds auctioneer backwater's anastomotic admixed configures acclaim amber brevity canon's athlete apricots absentia acceptances advent airless auto bridge bounce available bewildering bored bused bequeathing alginate choosing characterized clubbed balcony's bike clamors bows corpus bing beginning brooder acetate canned buzzing coating airspeed bussing allegro's ave brutalized bequeaths asphalt caking animations admissions congressional bottle atmospheres captures archivers answerers chaperoned attacker critiques batches cigarette's aiding archeologist abstruseness crescents burglarproofs bewitching clogs acquitting articulations blockhouses blackjack beck brute base chokers canary's bonfire's allied bach's admit contacts areas auspice auto's chokes article clearing condoned britches consulted chambers clamps aimer alienated chemically cleavage burdens choking contentment arresting betrayer crispness clamp codings convincing better brutally affections copiousness counterpart afire convening cherry closes blacks coo advisers captor's amphitheater's condemnations assails antiformant accommodate accompanist annexation compact bluebird's cheats consul aviation bitch's athena agglutinates casement's accommodating bottler buddy's bathroom background's assassin bellhops assembler bunkmate's caked coexisting bearded approval cropper's affidavits caravan's anchorage creek busboy attrition creditable candlestick's allowance's abhors critic aristocracy boater courthouse's avocado ascetic's ambiguously baubles blurb constituencies analyzed accretion's collateral actress's confrontations combats blamer aggregations convince charter addicts committee's ascertain carnivorous bicycling besets blundered beadles bowler apprised concretes biologist's capacitor's canvass aerosol ailment's capitols cherries canvas's anchorages asynchronous affluence clue conform allotments chateaus appetizer bottomed alfresco allegoric bran adduce compensated arrival's appall avarice bombings bird bamboo bangles adjudges clearing's baneful attuning confirms attributively compassionately cosmetics abstractly chinners clenches arcade's atavistic attenuators appearance animal colorer affinities bivouacs burrow cleans booker centerpieces bets cloves boos bulling bitingly chamberlains aptness arranger colleague anomaly's combinatorial chirp coffer collaborates births brownness batteries artist's coalesces charges acyclic assignee's ceasing cliff's consequently cautioner bantu columnating bigness bouncy afar crippling caribou berliner beaded arresters anxiously appendixes concatenation cocoon accorded coped ayes amphitheater berets birthday beefers clashing advisedly burntly conceal complain auger's concert battlefield's beefer causeway cousin audit bereft capability's barometer's botched bumblebee appertains chanter affable abstains clung adding biographic architectonic advertising capitalizer coconut's construction crasher chubbier banished baits axe cards barbiturates braes contrast blinder bluer carnival crucifies alternatives advancing cavity's adjournment affiliated buffoon baritone's asked compared armistice cones cinnamon alden amatory batten chant adulterously aggregation avocados authority's backed boom crawled arbitrary authorities asset's baptized crop's bishop advertiser capitalizing constitutional air avails croaked cessations assimilated counterparts censoring circumstance's barnyard accuracy confronts commissioned alcohols copies ceremonial becalmed appealed byproduct contributor calculating combinations adductor collaboration botulism combination converge conversation's conclusively corrector amicable aircraft arpeggios admonition's annunciators commendation confidence benches arrogates brambles autotransformer ate administrative aphorisms counselor's bunker's concatenated anecdotes banal bibbing asserted appreciating avoidable bravery affords cable cleanser claimants anesthetically consultant's agitations conserves cheater audio buckets brotherhood arithmetics colt's acorn's considerable airmen booth avoider commentary's befriends ages attributed access consoled baying blimp boundaries avocations connective's crawling coming cheap concretely alone agnostic's babel airmail bitten alteration clime's announcement appraisers briefcase braveness can't convent's coders albania collapses compromises buffering canvas consulates assailant brothers abetter buffalo beehives bowlines buggers cannibals barrier's casted activist's beryllium brewer alerts applicators belongings crossly ballast arclike appreciates agreement's assaulted capitals almighty benevolence analyses comically americans casket briefed coffin's adjudge bestseller's beckon agreeableness breadboards blot consolable bagger bare bumbling affairs affixing course chinese benedict acute conflicting comptrollers adverb absurdly bobolinks courtyard askers brandishes altruistically chip's compresses circumventable copper backbones adder avaricious alarmed captivates beguiles afore cart collects awarded authenticator crewed consolers coaster concentration breakdown absolves acquiring bribed blueberry's blond caliph cruelty circumventing appurtenance blindfolding censures candles antagonistically bowdlerize bedspring's algerian adjusting carpeting apologist's carol's cozier beckons commonalities cooler allocation credits catering blazer chaff begin axially accented blackout's armstrong creams blokes brim assemblage abscess apropos acknowledger archer accustomed chuck's balkans cocoa ashes arrange coffers bellicose concentrator biweekly bunched ability alveolus conspires crab's assorted ambient acceptors chronology's besotter birdbath carried courtyards ceremonially contrasted alleyway's cramp abhorred connections coarsened assessing airlifts courtly brooches adjacency credibility chateau bittersweet apprehensible canyon's anomalous awards advisable canner compactness chirping brainstorm accountant commemorating codify conversations amusingly anionic bivalve's criminal beholden bootleggers chord circling charming bather conversion boathouse's advisees baffling bellowed attracting automobiles appealers bourgeoisie changed acculturate boxcars ambulance's adornment causticly captivity ariser comparatives bananas avalanching alienation ballooners chapel's axiomatizations courageous cobol classical bedstead comma's armload annexed attenders castled adjudication bilks boyfriend cajoled axing consultations adumbrated club bathe breathlessly cloudiness convulsion's blubber assembled barns chinned biped clearings chemical barriers beautified ajar collections artful ballplayer's beads caches conspirators cowboy's cormorant auscultation checkpoint coronaries contemplate ballparks canton's bulldozing bushy capita allure afield butterers antiquated clearance boasting basal carving apish complexity admiration broker agleam by anglicanism beaners afghanistan barging baron chiseled bundle capacitors belle's alludes attractors constituted beastly advance accomplisher coding ascertains astringency aghast backers cop's bra's concurred bibliographies conserving aries anarchical adducts beggary contagiously complexion commitment's brooch cool clod's arrivals aerobic chasm's chalked attired convincer be articulating barring auditor's belatedly baritones codifier beady applejack collect befriending bonders afterwards bleaching consumable bimonthlies ceaselessly cliffs coon bagged analogical attendee's credulity conjunctions aloof armpit aggrieve approximating adjustments acceptably adoption bookstore's clairvoyant abuts browner attaches calcium bewilders characterizable bludgeoned categories covet auditor coercive boob accolade calmed cackler car cites abnormalities changers authoritatively array autobiographic beetles christen crochets classification conformed censors birch ballot antibacterial coinage burgher's beasts bastard's beaked adherent's constructs complimented convicting confirmation chairmen blindness acculturated costumed cereals coincides check besmirch borates centimeters clout brandy astronomically beaver's biographically airdrops combining beta ad adornments collector chances affectingly cashing biddable creases condoning allegation consecrate breakdown's airship's beloved acrobatics cathedrals articles commandment attires amusers belching circumstance blissful confederacy biddies anterior bowel contributor's courtesies atoms boon cautioners cruelly cornered architectural chides ambassador's belief's admits circuit calibration call bestselling bywords barges alto's biannual commits augustly attainment's consort clogging asymptote apothecary briskly again casters apiary craves compares concerns complimenters contention's chanting configurations associations chalice's chops blares card attained coats component's chopper bribe constable's confessed adolescence coated candlestick clowns altruist alternative briber coastal consummately applauding bulbs attentively chopping cans contagious clay buttering captain counterfeit boaters basis board adroitness brides colors converted blessed abuses bumpers bipolar crowd cancer container cables attribution chauffeur ant's cooking asteroids bashed bounteously bodybuilders crowns buckling adolescents copier chairperson's artillery amateur's arraign antidote aorta carcass allude connector's conceded composites belies bud anthropologists boston brazenly belgian's cohesively contractions attenuator arcane canonical bard balls boatyards bobbed believable backpointer's amphibian axle blundering autocracy caterpillar's confiscated bellow collaborator breaded casualty buffoon's associator's anvils cheery banged acknowledged appalachians confederations contexts blizzards brigantine autosuggestibility cranberry clubs arbitrates brewery circus clipper's cautiously boyishness bicentennial assassins banjo's circularly blindfold briefest aliasing allays annals appears botswana aphorism's cleaned contain congruence bringing brewers car's chord's absolved apollo almost burps apt bonanza's commonwealths betraying convicts beneficiary certain alderman conditions ager brinkmanship armers bowing bragger carolina airers blabbermouths burro adhesives corns bell's complementer alumna's bursting chute arbor creasing abhorrent adherers abductor braining bulls bills buying confusions bar's cackled candidly contraction's consonant cloister's beforehand assumptions characterize considerately attributable colony's buoyant basketball's bus caper controversy's bowling broke bandaged abandoning brags chapel austerity aeronautics contractors counterfeiting adjure beautifiers creativity counterfeited airship compulsion alley's chanticleer bankrupted able buffs allegiance airbag agglomerate beatnik's biologist barks bijection assumed bust adherent crouch anions confounded annotated baldness assent abnormal clump binder costume compatible animal's clear campaigning chandeliers beatification acquaintance's archangel's accrued atonement arsenal's brutes beseech blaring abolish arbitrated compounding accumulation assort boomed carcass's crouching abases beautifies candle bantering creatively anachronistically cackle answer courted abortion's blizzard bustards armchair banded circuitry bathed birchen attenuated airborne aftermost auctioneer's abductions articulator bucks begrudged contrary azure buddies bridgeheads bled barbecue conversions alligators commuter cringe crucifying contention belts coheres acquaintance chairpersons basely connects barrage arrowed cow bloomers basement aboriginal alternately bookings bassinet capacity absence's abrupt authoring causer boatsman corridor amid carryover blacksmith critic's adaptation's conventional bilingual abated ascii affiliating atheistic appraise bronze approacher consisted acoustician burgeoned adept argument creep bequeathed compose abrogates ability's admissible capriciousness college chinks arranged birefringence bostonian's chucks creaked cleaver cognizance attainers assigners ascension comedies cooler's cap's assassin's congruent argumentation coder aviaries christens agreer characterizer circularity creak coiling aunt boyfriend's calms atones anise blouse boolean agreeable chairing cleavers cranked copyright's breakwater's confines cawing chinner aprons balustrade's conditioned alkaline confessing adverse awaited collaborations awkwardness approached cartesian atmospheric attest atonal contently ankles bleacher abut assistant's attachment's accepted apologia atrocities auspices chinked costumes ascendancy cloak canonicals conclude beast autobiographies arithmetically colorings additives crowder cluttering couples chillingly bendable bullion befuddle confine correctness apex binomial citadel's contracted anglers bisque breakwater creditor's akimbo calibrate annihilate appending aide centralize awaking cambridge anther benediction allying burrowed barrow blockading atoll's adduced bottoming appeals angering aspirants cherubs color crimsoning bingo binders containing aplenty beam astronomers bob capitalizes bats ancients braking arabic applicants aseptic affirmative breeder abyss autobiography analyze accompanying condemning beseeching casher cowerers coordination billowed creaking canon absorb bow browse allotted banisters ballers affect constables calculated bisectors adjoined anomalously characters amount blasphemy binaural axiomatize beginners bivouac comparator's beheading beetled benzedrine arbitrators comedic context's crackle contrasting availers alien architect's apocalyptic creator's budgetary ax consultants aspirate barnyard's avenge bewilderment appraisals afflicting bared appends antimony archaically comprehensive confidants annunciated blowfish bulled bestseller bounding aging blunts composite concurs abortion athleticism biracial accuse assignees commenting climate adoration analyticities cords ballots comprehend arches coffee's bilaterally attendant appanage agency attacking anechoic clucked conspiracy's beaches covenant's alkalis branches apology agricultural analogies bettered cottages criticizing capacitive corporations beading costs cork beaver augusta coalesced arguing calculator's active contempt compensations bluntly blackjack's capacities butchers american's billiard afflictive beggar chap croak binary buttoning chewers banish corpses cancels antique briefing's choir's bourbon boxtop's crisply adjourns autocratic boiled charmer archaize bookseller's addicting correlations averts backache attenuate accordion carolina's confirmations conceptualizes antique's blacker crackers artemis boar advertisement's alight contracting cartridges ablation commensurate bookshelf chiding augmentation accessed affectations conveyer betrothal comprehends blockages connector advocate billows aggravated boo agenda airport's connect bulletins atrophying anew concurrency bilk crafts bilked asymptomatically compacting coal bailing antitoxin await attentive amazed adherer because benchmark's antagonizes condenses belaboring astride annulments brandishing cafes bunting antibody acting charting assault chanted coacher carries adversaries blackest americium case assuring analysis betray coasters annexes concatenates ace's abandon covers auckland arrestor's boyfriends blackberry's concentrates brashly amnesty complicate anthropologist chilliness combatants chafing broadside boors correlative accumulate crane's beamer carbonization anatomic bigot address circuit's arguably breadboard's antisubmarine announcing beating complimenting apprehension's coined aphids apprehensive bearing adhesive's banally breakables amongst arc blazed cove correspond animators community approvals boatload's adjourned buys consensus counting crisis augments blustery arsenic acronym chieftains backups compunction clean arrived assemblies conscientious bang auxiliaries abstain cashier's commune camped boxtop abutters articulated cantors collaborators consummation bleat acquirable beauty attaining becomingly benedictine cereal boldest crossing companions chefs clamoring barrels cluster bequest bricked athletic adhere cobblers bombproof clearest chattererz accursed admiralty chandelier's billet cloisters communal attenuating conventionally arouse antidisestablishmentarianism bilking abductor's angriest bowline's colonizing conjure connectedness abbreviate acceptable cared cowboys cotton aerators blended creepers baggage bicep's clods codifies correlate brackish contiguity composed bassinet's bostonians bombed coursing businesses constructors contract acculturates aristocratically clucks corporation's artichokes arrival boss boggles aggression ammoniac barters backscatters chords bone constructor acceptor's authorize acres conviction creating baritone avow chapels bin's armadillo backwardness aerosolize ambitiously blamers cogitate administrator banters allotter auditions aloneness chasm alfalfa cigars axed cramp's archival bud's ban's cramps badge bores affording carnivorously accomplishers avoiders balancing cleanliness bandy anodizes claim admiral's apprehension bibliographic algorithms artists bisques adjudication's ascribed alongside chanced boastings algorithmically clipped convincers chieftain's befitted creates beechen classifier anxieties arthropod's chunk's banqueting backstitching communicant consumption chilling bailiffs consulting attempters bane busied blocs ablated advanced ballgown's balances clerical blanched benevolent alderman's antisymmetric coax awry altars budgeting archiver bleed bakers cranks counteracted agonies blurt cannibalize close computes coughs courage canoe blossoms celebrate beguile aerial chided bureau's accord beguiling bonnet bowman costumer birth abreactions awfulness antipathy courter badger's beefed chick bungles carpenters accompanied bewilder attachers army's bunt blitz comprehending ashtrays bunches beggarly attentions axes aerial's chastiser condescend criteria battling courthouse breakthrough articulatory bold astatine cling complex contacting brainstem's camps cedar competitions casualties brooked burner abjections burglarproofing classes clutches adversary's baseless abdomen casings binges chipmunk chatterer barometer breakpoint's constituents bumblers champions constructing carryovers barked aplomb brassy client's bodybuilding attorney achieving authentications baggy conjecture appointments blotted appraising beau's barbarous bits annunciates computation cremate appenders abandons celebrations artwork brooms compositional allusive arrays bagels bovine clamored aspirins assisted buster cowing bracelet's alternations alcoholic aphid accommodation clever bathos banishes counselled corollary's contesting bulb's balkanize appendages apprentices bonded abbreviated boundary cotyledon's ballroom comptroller's complements bedfast accruing componentwise approvingly arisings befitting chunks advertised consign algebraic coziness combinators balking commodity aspersion's beecher correctively builder actuators bolshevism beatitudes arabian area's asleep barflies composedly battleground's captions awoke antisocial anglophilia bureaucrats accelerating boatswains camp ballplayer burrows bicycled cast's bumptiousness budgeted antagonize conjured courier basic cooperated armory courtier acclimate cross aggregately behind collaring clouds battle assiduous absurd concord adduct bumper cordially anthropomorphically aspires aquifers agreeably counsel brainchild's backarrow council's african blunderings busing accepts centipede's courses betroth care chivalrousness boxcar bach blithely constancy assignment's bulked bostonian arises authorizing airspace autographs breaching belayed aid continuity collisions arterioles approver cops checkout accessories bespectacled comparisons accuses cheaply airlock's assorts alphabetics bidders conductor's acclimatization councillors compartmentalize central actuate cashier bar caves bangle's accountants bricks competitor's axon's consoling breezy buckboards christian's cradle balalaikas balustrade capaciousness analogy's amendment's carvings apprenticed bidden crossovers archaic bachelors convergence appeasing boundless bumps chartered conservations belgian armchair's canner's clarity adulterous berated addiction's commandingly clinched corrupter collide alkyl ascetic assenter adornment's conserved butt's arising breakthroughes bull clinical beaching crossover crown beget abolishment's bloom cartridge's blip's convey cataloging bricklayer agreed biters aim bed combined aphrodite catalogue comparing beneficial conjunction's anthems avenues abbot's capacitance crests asphyxia appreciably blindly anniversary callers anniversary's accelerations chip bounds attempted continues aptly constituency bisector's commute copyrights commodore's bookies covenants assailants confiscations cheeks blackout clearly bipeds braze challenge controller's accolades battlement's bermuda accreditations critiquing branch adjective's asinine alternators addressers actuating attackers box chalice brightener bladders blotting corporacy bolder adapter channeller's checksum coffins barfly autocrats backpacks beat burglary's candidates aggravate comprehensible commuting cab's collared bitters accidently cabbage's artisan's bicycler absurdities boredom associated comers causally aberration chatters authorization's breathable celebrated airports boasts adjudging barbell's cracker constructions burntness blasting consisting blouse's abrogating biblically approachable bravo cheerfulness antigen artless courtrooms arbor's converts antler accelerators buildup condensation bigoted abides besting criterion butterer automation clinches avenue's conceit cats birdies adages cavalier acquaintances amortizes chamberlain backbend broadenings annihilating crows babbled converses bass's augmenting borderland binding bathtub's busses bias cordial anemometer clothes contaminate budged bottoms catalogs converged bungle barnstorm cluttered commendations atom arraignments adjustors bugged comedian alarmist corporately balsam compliments conciseness blond's adducible continual breadbox's answering aggression's conditioning chariot's buried attain arriving competes booking carbonation created beds barrenness awed adjoins builders aides badgering confiscation compromiser compartmented brochures cause bricklaying certificates bandies commanding arcaded asymptotes anvil audibly corporals byword ampere beer conservationist confidently artifactually commonplace carrots contemplates blueprints commitment abrasions beverages cod bandit buyer compressive blueberries bagatelles annoy constants clarifying cowslips bumptious allowably bindings barely corrosion cocoons communicated chiefs aptitudes adjectives calculators caveat actualities bight administerings bastes childishness bagatelle confront apathetic catches axolotl's blackbirds airfield callousness arid adamantly crime buss computationally blessing clefts artificialities contrivances blear chef's alma bonuses appendage's casually adorable belfry's antic's butcher cold bookstore campus's blurts acrobat congregations abjuring blindingly averaging bunkmate chocolate candied climatically adjusted bluest bacteria achilles beauties attitude's airings boner battery abatements berths bangle adventurer companionable bitterness adventurers backstage analytically bliss arpeggio away apartment briefcases brewery's aided cleaves became arrack converting apologetic assess alleviated caskets adverbial bed's chapters bandwidths abjured clocking ballet's birdie arrowhead's bedder cheerlessly amazing beach artifice compatibly crowding cabbage conquerers cooling apse aileron completely assessment ape commuters adapting arkansas accentuation caress activated circulation agglutination centrally betwixt bisections burro's breakfasts bleeding cheapens burners ask consent chillers bosom's complement adequacies continuance allegories beaned clinker confidingly camel corrections beehive affronting abets both comings bringed cheered annotations consoler chapter's compromisers adaptations aforethought bouncer amperes apostle chartering bonneted countess chemistry bilge's bastard aliments attacks chamberlain's commoner's alee cropping bitches breezily along breathtakingly aqua consolation concessions corners blistered crimes abhor aback budges acclimated allowing blasphemies attics canceling adiabatically banked condensed burglary amplitude aggravates admirations amplifiers confronting alterable coolest advocacy contributors bumbles bulged cracked attends aborigines admirals brazil cloister comply amplified candies compatibilities breakup clicking cadenced cardinality's ailerons bedpost absorbent blister cereal's alerted conferences bodyguard's bleeds creamer crease consistency convulsions around alleyway airplane arbiters anciently blurred conforming bolshevik bounty contender backdrop's citing associators assented barbell brutish conquests borderline compensatory centripetal affiliations asker chastise afflicts blunter afoot congress's clocker column's argentina availabilities blighted activations bashful coiner bookcase's blunders advantage carter brook alterers chopped century's consults calculations crafter commodity's aberrations argument's bucking brigade's compilation audiologist's brainwashed alteration's brow copyright adage chirps bricklayers brash commercially belligerent commemorative bramble's astral class configurable assiduity acne burdensome contrapositives amphetamine companionship cabbages apprehensions batched backtrackers bluefish consoles critical charts beatniks church beret's biography amusement's botcher amiable bogged ammonium amenorrhea bloody affront british annually compassionate anisotropic autumnal bathroom's boatswain's archers cat's before classifiable contradistinctions blur bareness abstraction blood coaches buzzard alba climatic blaspheming bays annihilation affiliates balks besmirched character's antiquarians classroom's brainchild attendant's combinator apogees accelerator comestible bayous bean contradiction bridgework coweringly abbey argon covetousness categorizes aromatic clambering auscultating corridors antiquarian clusters bested brew bonanzas blink bravos cooperation barbecues adulterer adsorbed clutters compartment blur's county's attractive comprises abounding arthropod assassinated bottomless cricket's anabaptist abort chanticleers charcoal brusquely communicates bedazzle biscuit's bizarre chap's auctioneers amalgamation categorization consents communist bearer corporation accomplishment's cotyledon baltic bikes counseled anyone blackmails colonist atone amorous ace chopper's adaptor commas computable babes broach amicably besiegers axle's crooked ambitions automating absents atomized cohesive category bagel blues azimuths athletes adventures commonwealth contact borer absorbing auditioning attachments canal's brainstorms absolution composers appraisal children cruiser cruise bombers blueprint beautifying carbolic apologetically chewed circuits aniline conceding clairvoyantly bursa bikinis capacitances colonel's alphabet bracelets criminals abstention atrocity's analysts costed cape bidder ampersand convenience's antarctic alliteration's chuckle constitutionality bootlegger's attacher availed cars barbados caresses chimes absorbed anagram's chattering compacter avocation cosine allusions ambushed blue assaults blackness brat's acme anabaptists communities cinder art's apron countermeasure bayonet contends aligns codified clinic's burglaries architecturally amulets chemise city adjutant acceptance's copiers africa comparison's biased acorn characteristic akin caters compactor concentrations cloudy apparition's addition chickadee's asylum automaton clipper assortment babbles backpack's arroyos corporate acknowledge canals corrupt ambles compounds charity's centering constraints cranes brand contester conquerable combinational benefitting attempt chariots all careless briefs bureaucrat asp cough awake aggressions blasphemous aldermen bible agency's blank alleviater bombastic affluent abstruse clog's bakery's blackened anoint alimony avoidably counties configured concern beehive's affidavit's accessing anodize chaste circuitous appoints contemporaries bolstering confound beneficially authorizations assignments collectors anticompetitive accedes adulterer's council cruel chutes bugling airframe beret chorused appareled colleagues contestable beau associate bobwhites consortium aboard attractor's brawling anomie alternatively aces correctable criticism's careers containment's councils consultation's conferrer's balancer awful apology's averages accompaniments bankruptcies accumulator's casserole's boasters bleakness affricate bristled clockwork brigadier's botch carbonizing comforters computation's blemishes blasted boatyard beards contouring chairman blouses amazon's avidly choirs afternoons barbiturate afterthought anaconda calamity colonizes bylaw codification codewords adjustor's burglar aviator's combs bewail accentuating claimant's blankets beatify bawled conveyance's compacts absconded bevy aunt's adorn create cactus autonomic accident controllable bookseller baiting blanking contemptuously artificialness cat colds already crewing canceled critically correlated burglarizing adducting cheaters convergent carpenter associational clerk anorexia championing anarchic classrooms catsup cookies coordinator's albanian clobbers can's aura affectionate breveting anaplasmosis apartheid burrs boldness bouquet's corers aids configuration acquainted brushfire armer antagonists cheering appalling accost breading computed brazing aristocrats crook bonny baffler carts barrel been astronaut complaints bun aeronautic accentuated churned agility applause betrayal amalgamate baseball consigning baldly balkiness balled creativeness classics bagpipe amounting bombard airline adorns chaffer cancellation blunder bouquets airliner catalogued beet apron's arisen chime cistern's buggy's behooves configuration's checkers chalk appointive costly chill charitable copper's alloys balding acuity bureaucratic atonally combated angstrom bellhop backtracks accessory's commanders blanketed brazenness blasters bellboy's adjoining countryman ascribing business amide agent's appropriated closeness bemoan concurring cheapen arcades baseman accomplishes antecedent appealingly cobbler congested averring antibodies battens compositions companion's cannibalized compensates birthrights appraiser condones canvassers bald backyards climbing brooding consequential chunk cheerily chaplain cowers about constrain adjudications cautions arranging amiss cleanly beamers ballerina's biscuits coinciding camouflaged bunions behead analyzes commentaries basketballs conclusion bashing courts continent backbone's cloaks approaches beachhead borax calls consummate charters creamed atmosphere armadillos contained boulevards contradicting conjures blanketer coolly arrogation belated audacious bonanza acquainting clod bracketed critics alias clarify boorish controversial azalea chef atoll abrogated afterward butte belaying censurer belches artistry abraded balalaika's consulate almond's apologists basked conforms citizenship bungalow's bureau begrudges circuses bound bemoaning classmates bickering beatable capital alum branchings cheerer affair's ambler brightens bookers antagonized bootleg besmirches carbonize bite augment adjust axiomatizing boisterous authoritative anemometer's buttonhole's aroused accentual booths cloak's computational bunker beautifications acquisition beatitude bolshevik's carnival's birds contemplating confession's basso absinthe canonicalization bludgeons aerials channel competitive clogged compellingly computer's actinometers contiguous ark bleats cabinet accosted assay beckoning crepe burglarized antidotes airport concurrent conceives cherish arteriosclerosis certainties abasements awl's cosmetic caterer candidate's conferred claw airdrop atomic cautioning abater bland ashtray axiom's ammonia checker admirable bulkheads amsterdam breakaway apprehensiveness canons appertain breadwinner apologist campusses byword's blamed continuous benefactor's alien's chalks alterer alphabets actuator's byline breakthroughs consequent cotyledons construction's candidate chiller barracks armament's aerated colorful approximately creeks coincidence clips acoustics cadence commodities cooperatives angrier addressee bloodhound's burnt biographies alluring artisans breastworks abetted connoisseur's alignments burgess convictions cord bag cavities contribute cartoon's convulsion backlog couches community's ado blind antibiotic assert beetling arrester clang contend bloodstained absentminded controllably bungalows bereave capillary broader collar aftershocks blinker circular cleanness attainable appalachian char bandlimit bowers continental bookshelves amulet cannibal blinking carefree brighten classroom contributed cajoles aptitude baseboard autonomy creditably controller bright amendments bosom boaster apportions answers criticism amateurs attributes couplings checkable acknowledgers atlas ally brained autocorrelate backlogs bigger agitator alleyways butters abuse bowline ballooned blackens abruptly campers bourgeois beguiled animation armageddon condense ambling cropped breaths adversities apparition belying bum's autumn breakpoint acquiesce chaffing beans continuously birthright's billion clamor cathodes bursitis battlefield bights component bringers blanketers celebrity's animates abide chieftain absences bewilderingly colonels aloft bolster absorptive bids acidity choring abused boiler batter amplifier anticipatory ambulance crafting chink antidote's angel bolts assign artifact adduces cessation's anatomy bolivia cellar's beamed carves britisher blacklist constrains bluff bumptiously aforementioned amtrak archly captains congratulate beheld adventured bibles backspaces armpit's accountability associator adjoin appointee's coyotes barometric above centuries abstractors basically cavalierly cigarette autonomous adrenaline circumlocution's antiseptic abjures algebras basin build accent assassinates casements commenced crucify bandlimiting consorted changer capitalizations bronchi chartings abode's contemptible bugler concentrated capability aisle coveted brisk ached characterization append consenter cent albums ammunition coordinate cascades continent's contradictory acceptor clockings bumped abrasion's analogue browsing authorship adolescent block's automatic ascetics canary assonant blockade barricade cardinally accepter abandoned assassination bunion's balalaika bedposts clicked boast astonishingly arrangements clergyman byway astounded caustics aureole confederation crane complaining biographer's bumping consequentialities consecutively bares beavers abridges alveolar candler amuser biologically borrowed buttes chaos austin authoritarianism carting artery's calories clumping alabaster comforting conscientiously blonde categorizing butting celebrating accelerometer's cannibal's brazen applicant campaigner compacted allow alcoholism allocations contrivance's combines airway's boric clipping closets bulk conferrer beauteously cartridge conspicuous aspersion calibrating abstractionist bummed achiever arithmetical bawls adhesive adiabatic avalanche believing conundrum barbital accountable associating adsorption briar's advisements clay's conducts cajole ascribable barony collie awaiting burglars besought conceptualizations ascenders agates archeology aristotle consumed broadcasters approved arbitrator's abided avert arabians bile crude apportion brewed bombs bordering addendum admonishment's anesthetic's barometers burnishes abundant algebra combine azimuth's correctives blockades complicators asteroid's attache appropriator's bat brow's cholera angrily clipping's cousin's biography's axolotl boarding aggressors craze amply compatibility's absurdity's clinch contributions alundum crowing butyrate botches barrack action's bombarding briars coon's caravan actinium comrades compliance counselors cardinalities bounces counter blanching autopilot's conceptualization's containers banter bookstores bunkered backwoods compactest actuated bolsters bulks bellwether's acoustical bark conditionally carted blades blatantly autocollimator cornfields anointing comradeship asocial banshee cooperate countering bridling contingent analyst bloodstains brisker consul's cluck columnizes claiming bologna bastion brownish asymptotic blew brevets aspects cleverer axiomatizes boggled acid backpointers brig's clash channelling battleship adviser alter befoul admiring anastomosis bumbler annoyingly charted braiding branded busier confiding bromide's caret constituency's attracts amorist audiogram butler's administrators braver bartenders billow associates butler burnings collectively angel's casseroles barricade's asher automata arraigned cases braying borderlands baccalaureate clocked assignment bloodless authorizes compress aura's behaving compressible arrest attitudinal counteracting amphitheaters cement could bachelor's alms advocating boulder bottom babe crosser bomb containment cakes craved blackouts aqueous baring bass barker comradely cogitating concept autism bonus cognizant asymmetrically clause clustered burning blackmailers broiled brownies bloc's archetype buffaloes colonize contemplative consolingly appropriations beefsteak brief beings coded affricates cardboard competition's airily chronicle bloods acquiesced conservationists anteater's acknowledgments abates chisel contrivance cafe autopilot admires bimolecular bedeviling adverbs bungalow bristle appoint coals blackbird alerter animosity concernedly buttress assuredly bothered aching altar antitrust brightness admitter anastomoses creations castle brotherly consolidated candid allusion acetylene audubon ass bunching burial aggregated courteous babel's befriended butternut chicken blames bid awe comforted comic's cased appalachia couched boot adjustable computations cheeses circumference baser agreers biasing amity ashamedly adopt avionic circles braziers ambiance busiest bower admittedly buildup's centipede ailments carrot's apples ballpark boughs breath churn bottling austerely coincided charms ceilings corker abolished altercation alliance appraisingly backlog's burningly architect annum blatant consorting assistantship anticipate conductivity causing bomber bankrupts chronologies appendage amazes creeds catalogues assiduously arced chafe butlers ampersand's clumsily chemicals bandlimited authored astronaut's aspect's bristles crucified classifying braves allegory complexities collapsing anders contemplation cipher's bonus's auburn cribs clasped cookie's amen acacia bacilli canners confided accessors aficionado breaker belly's befall commit aged chars assail bike's correlates affronts characterizes asserter addressed corruption butyl antiquate alphabetically brothel's bankers commoners adjustment's breakthrough's burnished bludgeoning augurs abbots bashfulness assessment's bump aspired coupons architecture's adjuncts arrests contended congress consumer's breadth aggrieved creeps baiter adulterates brutal ceiling authoritarian annihilated breakfasted bewildered calibrates abyss's crossbars anaphoric compilations abounded arteries baseness bulky alligator's cancellations amazedly axiom aristocrat's bogs cathode congressman clatter assimilates assures cease affliction amain acclimating category's criminally brashness colonizer congregation burped arraigns chocks ascertained algorithm's acetone cabling colon's assistants acumen asserters aperiodic compromising climate's contesters almanacs bijections beeps chillier casualty's caution corer communally confrontation chemist's besotting agree brigades caterpillar anthropology aborts achieve arraignment coaxer bony backtrack buttocks achieves abbot concluding bushel congregates austere covetous bubbled councillor baseballs arrogantly anthropologist's allayed accomplice briefly complied bootlegging annoying commonly brawn clip's added align amuse aver blowup abstractions bundling abashed bulge childishly beset chastises clings conduct consolations baptists actresses approval's computerizing buffets armenian costing atrophic cite boarded allergy's allusiveness conjunctive comic contingencies annulling brooks aesthetic's concerned befell creator basting activator's configure ballrooms amidst churns bloodied affector beetle's canvassed bloomed concluded authorization clumsiness approximations bandwidth crash befuddles apply aridity bottlers balk bolsheviks affright airedale belle communicative adventitious certifications conducted butt barn's budded auditors closest ancillary byways anemia comforter arrow ankle adjuring billiards baptism bade convoy battery's algeria contiguously completes absorbs analytical cleaning combinator's allowance battalion animateness celestially axiomatization's allowable compensate buttoned accrues accountant's connoting cropper carefulness badminton cooperating archaeologist's breast calculation americana comb bedded casket's cast barbarian's amp congenially artist ballasts attic's compete approbation bit's allegro backbend's agitator's cowboy agriculture baptistries cares amass coolness bridgework's concrete anode bloc bubbly anus cannister's coring confirmed astonished cave boycotted aster archaeologist bakeries baptist abbreviating activation against backer authentication arrangers clog clearness burying cellular betterment allergies angular codifying combating cleared cooperator critique abrogate clap attested crankiest but astray cleverly bands beakers carbon ball applicator borrows achieved correspondence's alto agendas core backspaced boxtops campaigns biochemical appearers chattered balloon absolutes brightly alertedly broomstick adventurous aqueduct boycott boatsmen bunts brokenly allocating colorado abstractionism baste activities burned antecedents complementing aquaria administration antagonist bivariate aspirated befallen borrowing beadle anaphora blanks capable arduousness chasteness concurrencies countermeasures banana's conceivably comment belongs cocktail's categorizer cherubim city's assurer concurrently autopsy burly abandonment cliche abound agglutinate barbecued anon bounteous aborigine's bothering criticize airplanes alloy cask blanker altercation's contingency's agreement ailment aggregates churchyard's activity's candidness battalion's brigadiers antitoxins beardless carton's bodily corollary cited choicest cherishes adsorbs consist anagrams corked author bandlimits adventure charcoaled astrophysics centralizing allergic availing allah's arrestor continued conferrers bantam advances amasses closing comes benefited bruising asynchronism apparel boilerplate availer climaxed complications certifying among activates automated breakfasting carols coronation cherishing baseboard's aphonic centipedes allegorical cartoons begrudge azaleas atypically boils bushwhack astonishes consolation's child agglomeration accelerated cabled bloated appreciations billboard colorers causal broomsticks additionally crochet cranberry's admonitions awl cardinals clove alterations concise bends anvil's cornfield bathers burglarproof abusing copying counselor burglar's championed bowstring crops catch activator craters accomplices anemometers besieging bond airflow arrayed bijectively battles behaviors adulterating allophonic bison's blisters atherosclerosis befit's according adopter cooper alcove's cohabitations attractiveness cabs burdening breezes bridgehead's amateurishness bullet batch contests acclaiming chloroplast collectible covering citizens assortments archfool ascribe convex annexing bunkhouses brought boilers airmails concerted bluffs bobolink's amusing computers blown bijective choosers characteristic's affectation approaching attention's analogously anesthetics bursts attributive bandits agog bagel's bins briefings budgeter booked attentionality bout altruistic bombing acquaints alcoholics commandant's blinds annulled anal beneficence coolies bowdlerizes albacore cherub crashes almoner amenities believed buffeted capturer brainwashing autumn's bum arrant amble buzzy baptistry carbohydrate applicant's asterisk aspirates annotate alibi crib's confusion aired cantor abolishments compound crossword's clamorous billboards bags corrupts annoyed contemporary amateurism breadwinners coughing another aster's appellant's botanist's appeal australian archipelagoes conceals classmate's ablates canvassing bylines corresponded boatswain constitutionally adores annal alkaloid's arrowhead advice brush anticoagulation blob bravely comparability cloudier burlesques blase clawed badgered checkpoint's bootlegs arithmetized corpse appraised confiner brighter caravans batting allotment's coarsest ballads bronchitis chimney ambitious bonder compassion abutter anaerobic boats appropriation airplane's callously cohabitate abject conducive contrariness bimonthly bunny's bears cage ceremonies captaining carrying budding bordello's compulsion's aversion's coerced baited appropriate abortions album coffer's berating banner abdomen's ascot carelessly accidental blade's bun's brushed beware commotion challenging analyzers boiling amortizing conclusive compromise asserting bilateral additions character chemist bandstand amounters alternation briefer combinatoric chose bordered addressee's appear confusingly adopting bagger's archive becomes bengal burn coins anatomically cocoon's commencements battleship's carbonizes crazes clouding aegis byte's agnostic barbells cipher conventions building berkelium chastising annulment's connectives attentiveness antiresonance cores blemish's asymptotically caresser bathtubs alternating biplanes anecdote baron's booby comet complainers allocator affordable conformity annoyers alternator's closure's bedrock bacillus cemented convoying absorbency burst brownie's bard's adoption's crackling anodized collaborate ambiguous acuteness clients burros annunciate applying backscattering animately blessings challenges attitudes bypass aiming bequeath carefully broached argue bulldoze assumption assesses bureaucracy cameras amused comics bedstead's coefficient acidly begs attic biologists cornerstone's behavioristic channeller alphabetic clenched clowning carver brindle cored bracket amazer baseball's absentees concludes bathrooms bolting arbiter's ardor blame chasms ablating biconvex agglutinins composer babbling adaptation coffee brazilian courtyard's blacklists avalanches causations blonde's alleviation buffeting circulates anyway anarchy arab's calling caliphs birthplace allegations astonishing adult buckle allegros agnostics bat's companion applaud amplify convention charm credited compliment coast churchman backplanes combatant's cock cacti clinics appliers adapted alert baffle components abysmal aurally carriers basements alertly abolishing advisors agents clad bucolic amounts asynchronously abutter's accused contraption's aliases based clutch contents canaries atomics constraining apparitions adjunct's capaciously axis coaxing carpeted adulterers bettering birthday's conundrums cooled alkali begins comprise appliance acquit carbonic alarms agglutinating crank complementers athlete's anagram autofluorescence alumna bazaar's belittles celebrity craziness barefoot combatant avoids blandness baptizes benchmarks autocrat's cook compute appropriator adherents bicycles agglutinin bandpass cognitively assembling apiaries accurately aware blooms appended claps analyzer accede beautify affirmation abdominal automates belittled competing confederates chest apprenticeship bronchial carpet attended bereaved categorizers center assistances britain banning casement ciphers activists bereaving corded boards calmest content besides allegretto's conceived armchairs convoluted couch accoutrements audiology assigns conspire appearing alarming accustoms aquarius bestial accepting blackmailing careful booty changes courtesy autocratically cocktails buzzword's contenders coffin agrarian abjure bivalve consumer bridesmaids barony's comma adventist america buzzard's benefitted befalling camel's borrowers amanuensis auditing audiometers believe attractions contextually bisected clamber adumbrates cannon's bloodhound bowlers consenting actuator boundary's balky aphasic cowered allophone button bystander certify bartered ante choir conqueror chaplains conference ambidextrously bullying computer cartons bigotry constant convent chooses afternoon coincide circumstantially carnivals canning armorer coldest conjectured bush corresponding controlled adders cogent bustard's brushlike bullet's addressing buckler buffers atrociously avers accreditation completions boardinghouse computerizes ascendant audited convened copiously accusation completed census anthologies auspicious conservation completeness assurances band bombardment apprehend cardinality convoyed ants bluebonnets concepts alternated bulwark courters capriciously cisterns confinement's constraint bobwhite corroborated baptistry's confess chipmunk's bleary cleft's bureaucracies amazement accelerates beribboned carcasses ceaseless backstitched botanical bremsstrahlung cologne crime's assuaged carriage's computing bauble's buttresses capers backyard's chewing competition bastions clerked comeliness conservatives behaved alumni adjuster chicks abase averaged courtesy's although bargains beholds ambivalence cargoes chews alleviate assimilations benefactor banishing crossers abbeys awkwardly appender bah appreciate caved clarifications adults chins boxcar's bakes absorption consternation birdlike blowers comets choices abbey's bulldogs behave circumspect avariciously cripples administrator's buzzards aloud cemetery's argo corporal biscuit crediting baroqueness aspirin blueprint's ballroom's captive's caving composes applicatively caste baptism's breve absurdity balconies bray blushing cost affection balm's citadel arbitrariness artistic bidder's beagles blackboards algae civilizing contributorily agreeing apotheosis cap brick balkan beagle burden architects bobbing cellist captivating censured buoy censored commonplaces bastion's artichoke ambiguity concede abilities condition arrangement's aromas aspire creeper backdrop aggregate bobolink alerters blemish captive comfort amoeba books archaeological cobweb carve audience's conservatism bordello carelessness bureaucracy's beaning corder congregate biconcave attempting accrue canonicalized accomplishment atolls acidities boardinghouse's blackly cabinet's avenges colonists brayer anecdote's conscience's autoregressive craven bowdlerizing announcers combinatorially achievable computerized asbestos backtracking appetites commented absolve busily abundantly bundles baklava actor amending continue ambrosial briton account conceptual coerces beak committee confers bailiff back ammo bye cone colt annunciating blazers contentions cogitates conversed assortment's apollonian counterproductive acquires anytime conspicuously confident chloroplasts bragging colonel bee climbers climb correspondent acrobatic blossom abetting brave ascensions ancestor alliances ballad's conservatively cabin's abaft conditionals blinked bout's buddy brazier bitterest chance caressing coordinations bagpipe's brocaded casserole cried bridging advertises complimentary atrophied blacklisted aspirant's crossings astronomer club's amorality bushels catheters acceptance ankle's bristling coping bovines abolisher aligned bearish bilge baptisms creased articulateness creed's atomization championships considered brig blurted abate capitalist's catchable breathtaking cashes condemnation abstainer atrophies briefness breaking austrian abstraction's animism campaign compartments begged betrays atrocity affirmation's benefactors banister albumin ageless collided buffetings celebrities amino compulsions boardinghouses bribers contribution aspiration claims count commending announces calendars capabilities controllability bereavements brethren collision's coil biochemistry beliefs accuser allurement authenticates complained applique abasement brevet burnish byproduct's constituent communicators border apprehended blueness crack bystander's broccoli commonness announcement's bugles beacons barfly's ambiguity's conceivable credible batted alphanumeric covert burglarize antagonisms assistantships cleansed beholders behalf ailing confuse admixture blockage backslash apsis conductive categorize athens catholic cavalierness bag's bothers appetite's buses adolescent's bayou's amyl aquarium bayonet's agonized commandment's amalgam collectives bribes cellist's architectures adulation blabbermouth credence bunglers brunches comparable brutalizes commandments bought acre's consult bullied bereaves commercials acrobats cache's caring cokes caterpillars blueberry bluebird covered contaminating analogous cavity crier bronchiole bras climax construing cavern banks collegiate boil attorneys benchmark canopy biter affirm agencies clearer assemblers corroborative conviction's basins crosswords biggest annotating antiquity ballgown alkaloids aerospace autocrat chagrin bedazzlement breathing classic aloes candlesticks columnation altitude acronym's compressing blameless blinks anemone blare commendation's connection's collision attire crippled breastwork acknowledges aeroacoustic complimenter cover alleviaters congratulations copes audiogram's angler conveyance baby conductors awakened annoyances besetting confounding amplifies crazier bode consigned chubbiest acquitted bowled continentally bird's chief clumped chaired beginner's aspirator asymmetric acreage bulldozes birthplaces braved clutched battleships alibis arousing applauded bender ago badlands channelled ballplayers bums axiomatic counteractive additivity coupon's barrages awash censorship adulthood always bracketing couplers chart billboard's concreteness coefficient's consultation backtracker coverlets charging comfortability backscattered clattered control counsellor copied certification conferring abashing attachment carbonized apricot's aright balsa cantankerous angles blushed armaments coordinates autopsies cherry's barrier buttock banding breasts advantageously archaism arrestors ambidextrous allemande consecutive axiomatized artificiality brace abominable bouquet arch bodes bequeathal barnstormed blobs belched clobbering agriculturally barbarously attainment bellboys anglican accelerometers crazy beaner counted communication aligning angelic confide constraint's connected cooperative congratulated commoner allegory's advised clockwise backbone burr chestnuts accusation's busted accusing cell asynchrony craftiness alliteration assailing ads belgians bickered backwards adverb's asset browbeating burr's cheating alcoholic's buildups chargeable controversy clasping axers backpointer charged conservation's billed bipartisan coat anomic anisotropy breaches convert cowardice alps bloats ascendency applications cigar's branching adjourn chartable civility argues artery bronzes armful clip canvasses approbate contriver childhood ballerina chocolate's containments acclimatized buck airlift converters clicks battleground assemble chestnut appliances cantons competently adjunct bred assists birdbaths courtship ballistics coining brine churning bufferrer's beacon's clearances acronyms apricot buckles compensating boathouses authors badgers command apart chaotic archdioceses arouses clumsy bedraggled corks burping analogy brutalities bother cravat cake beatably capacitor botulinus audiences brainwash countermeasure's assigned bowels collaborating bridle addenda attack biking arthogram calculus brainstem asian bedpost's bluestocking cone's blinkers advantages agglutinated abreaction bidirectional anthology cleaners apical abler burl correspondences basket anemic announce builds brassiere associatively contractually acolyte compiles civilize appeased alienating beefing barb allele assembly's closely almanac battlefronts chants ceremony boulevard's booklets balked accredited collection anoints buckshot codes chapter contented barnstorms aspirant cheaper choked bedazzled boroughs comedians ably advisory counterclockwise appropriateness crossword amazingly commended contriving boxes armhole bombast ambassadors blab contemptuous brocade audible coincidental citizen's abduction abutting automobile boyish abscissa's besiege anesthetize combings constituting chills coldness acknowledgment amphibians cigarettes augers brightening choral bookcases accessibly churches amounter backplane combative allusion's captured atrocious assailant's coral bishops belligerent's cremations abduction's breakage authenticate basking bison conjunctively academic actions commandant boning bough's aerate alternates bawdy congenial complicates cellists christened consolidation categorical analyticity crises alabama creatures befouled climes atomically breech's antiserum believably combers contradicted budget affixes chased biblical cheek's calloused befog absently conjoined couching anti breacher chuckles baseline's amoebas belief brawler adjured and compiler columnated aloofness columns consummated burns cottons borrower calmness bemoaned broadcasts brainstems bales at bale actual accords apostrophe calf accounts battlefields betrayed breeds bawl challenger botany awarding characterizations chains ashen assyrian confirm bore connoisseurs ban belting banishment arroyo conditioner apologizing analyzing adobe archenemy creditors corking bread cope broad clincher advancement's asparagus artistically beard accents beech century athenians biopsies body amour art colonies christians baler assemblage's comedy's centerpiece's admirers abounds burrower coldly advise conquest chauffeured buggies bridles admiral absoluteness complexes brittle cows amortize cooks confessors adagio contextual addictions bacterial backaches afflict axioms coyote's avian attentional awarder butter climates bustard antithyroid credit antedate argonauts catholic's changeability anthropologically chubbiness assuages anatomical crates aimers chester consistently crafted budgets assertiveness cistern amusedly bouts bug's area avant assassinate arts aggressiveness antiredeposition cagers biennial bespeaks attitude coalescing confidentiality certificate appliance's ballets addicted bluntness broadens cocking calculator buffer coherence atlantic cooperatively alloy's bugging article's cooperators annuals believer aversion acclaimed creeping accession's blankness commuted bosoms colonially consonants approving archives arteriole's arrears activity altruism approximates barricades compiling beethoven altar's adumbrate bestsellers assertion's braked alcohol's arianist boots ampoule anhydrously cathedral's banquets billing bitterer blunt crevice's bluebonnet's casuals clashed cask's antigen's controls arachnid amazons bisects backpack cosines alcoves anteaters brambly commissioners allotting actuates american autonomously bedsprings abscessed configuring adversary arrows country coppers bilinear covertly buckboard bacterium almsman backstairs avowed assonance coherent admirably contractor's buttock's caressed agitators appearer convents aggregating compilers conducting approvers attention allege crudely antagonism administrations cannibalizes chuck admire bloodshot conflicted coverage charger anguished civilly anarchist's amalgamates bedspring circumspectly aroma conversationally clucking ballooner buzz constitutions borderland's bustling colonials begun complementary clutter accordance bloodstain cowls blushes constructive buttressed broaden abbreviation beginner coordinators antagonist's actually barge appealer changing condemners airfoils affix bibliography's contours barrelled annunciator categorized blackboard classed broiling anonymous assignee bearers botanist conveying burglarizes aggrieves candy bells attainer artisan chalices construed baths arrogance conqueror's astronomy climber bronchus apple's bong birthright beets battler allocates abridgment attenuation breathy broilers capitol's buckskins blade blurring chickens conversation bromides accordion's archangel befalls coopers buttressing confusing blamelessness consolidating apocryphal alcohol barringer assurance's bronchiole's arachnid's cannons avidity bunkhouse ache civilians appropriates buttons confides caustic boarders bonding bedding arraigning barred autobiography's anthracite amalgamated battled cloth blabbed antipode's beriberi bakery clothe chronological anticipating bewitched calmly condemner apostate buxom caused championship bodyguard bewhiskered aspen abjectness brownie adjutants begetting accidentally captivated checking ambition blackmail copse caliber chaperon circulate cream auger commencing begrudgingly archivist bunks accretions binoculars conceive adheres cogitated bushwhacked congestion begging checkbook belabor attributing bait conversing baker channeling coaxes ceremonialness boundlessness atemporal buckskin cementing asterisks cranking biennium colons arming ambuscade backscatter checkbooks acculturating bad bivalves assistance arthropods add beefy bough berth can besmirching bight's branding blowing concentrating badges applies centers alienate astute awakens conjunction broaches banjos alpine alga advertisement bandwagons contributory activism adherence advises carbons contending assurance cosmopolitan airlines accommodates commend confesses bulletin bunkers confining bobbin bigot's bottleneck's brothels cellars budging branched brilliant briskness believes carriages alphabet's appetizing capitally acropolis bluntest clubbing constellations attenuator's breathless brae aches abroad coiled begotten behavior brutalizing alphabetize background cliff acceded cardiac bawling bromide association bacon chaining chipmunks arenas breeches bewitch bonfire automobile's chum capitol amok aurora augustness chafer bib competitors arable boomerang's beached bosun adult's biographers abed auction cleverness brats anchored communicator's alligator bellicosity apostle's corrected common alacrity brokerage caster artificer awnings caller constitutes ruby-bdb-0.6.6/examples/wordtest000066400000000000000000000512771154714021300166570ustar00rootroot00000000000000asceticism chronicler ale champaign bulkhead cattle creed arbitrator constitute accumulator butted calculate charitableness bas blinders animator's classifications admonition chronicles boomtown's consider backache's bars bury clattering brooch's crossbar articulate carton amphibious bessel affinity's bronzed airy burrowing coordinating acquiescing breweries ancestors comparator abstractness conquerors beetle consume audaciously axon cataract awakes breeze capture clinging capitalizers booze cremation aglow burlesque broadening besotted arching camels archdiocese bartender's antipodes bleating buffer's creative bashes conceptions bleeder axiological blankest bubbling andorra apocrypha airships battalions belfries concomitant castes bedrock's acceptability bulkhead's appointment conscious adventists bipartite boatloads aerodynamic bucket's babyish billers chastely browbeaten attorney's convincingly alerting criticizes avoiding corollaries arithmetic confidant airway cancers abhorrer antinomian annuls commemorates clamped boggle allegedly ancestral cabins complicator ablute bondsman belligerently appurtenances collaborated abstractor's cheapening aniseikonic admitters aperiodicity aesthetic blacklisting bib's bleak conversantly boatyard's beautifully bypassing comments cascading choker chime's crib abstracting apprises blitz's britons bugger's accusations angers caught concretion annul criers bookish asterisk's cartography backarrows chaps coincidences byproducts communicant's automate arachnids afflictions affliction's authorized adjective came cements asunder accession clouded amalgam's couple calamities correcting coronets bellhop's audience apocalypse admitted chases crossover's certifies cheapness backplane's amend bodice broadcastings certifiers accompanies assessed brat cries clarifies antennas aspiring anywhere brochure chained anguish audiologist brusque bodybuilder's bygone collaborative anticipated animate coarsely complicator's concealer craving breastwork's bailiff's are aviator cheerless acknowledgment's auscultations bikini's anachronism colonization bodied bemoans big brightened brittleness betrothed controllers convict ambition's bijection's crawlers bodyguards cataloger couldn't attribute confirmation's confronted crudeness booklet aught activate bash childish catalyst's characterization's adaptive combination's cheerful condemn bankrupt computability bully accidents coalesce belonging buff colossal associativity ascendent aunts consumption's abstaining communes bodies anchor codifier's budge cricket cripple canyons bleakly august atmosphere's arbitrarily crab aspiration's bunny advancements calming blinded binuclear commercialness clanging amputated bathrobes appellant argot blossomed altering commands connotes captivate affair cartoon aversions connectivity bookkeeper blast attending beef contradictions cashed compressed assure brunch crowded absorber alternate arbitration communicants chiseler bauble beaters alabamian backtracked criticized breathers comfortably bimodal champagne conflict contraption cautious chores acquisitiveness crow contingent's amazon communion antenna's bottlenecks coronary amended claws bungling buyers bottleneck confronters cowling codifiers counseling counsels bellwethers binocular bowed articulates beefs admonishing brigs cooing boy bullets constable alluding couriers clippers aphid's centralizes compiler's communicating chilled clinked cocktail clawing assist comprehensibility camping chivalry authorizer come arrowheads antigens armpits attune correct caveats backgrounds abased alchemy confuser bramble aerating clocks breakable categorically cleverest assisting bind aftershock coaching arctic bayed bloke's compartmentalizes confinement brother's creamers advisably capacious corroborating chancellor bier capitalization cloudless censuses cringed astounding acidulous conception's clearance's cooped avalanched chaser actuals assailed continuation averted commutativity bunted crossed awls belonged admix augmented crest cascade coroutines brilliancy abiding compel anticipates brays affective animating auditory bibs crazing assassinations balm belittling checksum's citizen causation commissioner barrelling collapse aborting coroutine's blight acknowledging arteriole creaks caged adjudicating almanac's crew bundled backdrops blocked balms appointees centralization cabinets connective bedroom adaptors capping browbeat commodores centerpiece constrained closenesses antiquarian's compounded bridgehead aqueducts coveting bouncing clumps conveniences benignly completion competitor boomtown commandants astronautics affects clustering benefiting bridged bead acolytes broil blanches archaeology amaze artillerist considers boosting accumulated alaska abolitionist beverage's cottager agonize camouflaging airframes conjuncted counteract cautiousness assaying affirming accusingly beachheads babying arguer cleft crag's bedrooms aesthetics age comprehended complicated angled amphetamines apportioning addresses brings clink apparatus admitting aesthetically clutching aloe bevel clerks conflicts blimp's ameliorate breeding counsellors consciences cravats campuses chasing bugs agar am blanch amuses bigots antithesis cohering axolotls badness colliding adopts alumnae accompany barbs challenged arteriolar cleansers bookie's consciousness assertion ameliorating adhesion bookcase beginnings continuance's brimful calorie crater appreciable closure bowel's adamant classified circus's adieu amphibology bazaar bedspread's bans cower coloring bengali breachers cheapest contradistinction catholics bayou cruelest biplane's bunch botanists comer campus broadcast cataloged apparently corn calm companies accordingly appealing burghers amoral adhered ballet additional carbonizers bid's ascend ablest arabesque aye benighted additive crankier calendar's availably calibrations codeword aforesaid balmy addition's crosses banker consumers agenda's bragged average alleviates crevices barbarian badger crazed assimilating clinically caps arizona blindfolded brushfire's coarse contingents animator baptist's comedy combinatorics affiliate chambered colonizers charmingly babble beauty's courtroom's creation achievement bounties cliches catalysts attendances corporal's crouched chasers arrogated arrogant bespeak barnstorming compiled archery butterfat airstrip's abdomens apologize affecting adds amalgamating beats between competitively betterments attenuates awhile basics complains barium chairperson angered applicability buyer's admonishment calamity's consciously archipelago airfoil attendants bunters bookkeeping adapters amusement backslashes courageously bellies absentee corrupted cowl blustering artfulness admission book accosts cleanses booklet's ballpark's breadwinner's blabbing anglicans beers angle animized channellers classmate boor arranges bless bellowing aviary code casts ballot's airlocks confinements commencement counterexamples asiatic autograph anxious behaviorism beryl contoured advisement bodybuilder actors apartment's anchorage's bruises adduction creamy backspace competence contraction bounden aliased boron calmingly commonest chute's allah abstinence binds bosses abrasion cobbler's controversies arms compactly acquisitions clothing affiliation armour blacksmiths ascent astronomer's clan checks advocates cathedral cognition broadeners census's avenger botchers antiphonal annihilates bloat cancel allegiances borough ardently bitter archaicness cornerstone chiefly collecting black brain brighteners coercing bath billings bauxite anarchists bequests battered clangs arboreal abnormality cdr congregated confederate ambivalent avouch adducted accompanist's abysmally avenged baptize consumptively consideration basket's bobwhite's ass's coasts an asymmetry anymore clown confusers chosen cabin cargo coasting beagle's accorders baleful armed bothersome blonds bookkeepers carbonates crop clues coverlet barter benefit bases affected brightest cinder's anchoring advisee argos airstrip confidant's antimicrobial berate celebration cheek bondage comely butane citadels countered bobbin's commutative clarified blackjacks brimmed buzzed chemists castles crescent's choppers buzzwords biases apprising balanced auras company's confiscates affirms bellwether admired clones boatman arab catalyst begets contraptions absolutely chuckled amplitudes agitating alkaloid abutted circumvents conjecturing bastards astronomical accessory accommodations carol braving correlation axles brushy assume act canada aerator beadle's blabs avail clinic behold boyhood antennae continuation's apple agent bandying clime changeably bootstrap's croaks autocracies baptismal countable apportionment acre biofeedback accumulates cannot catered crave appointment's bending cooperations australia consumes alphabetizing breakfasters captor accompanists confession baffled crabs cornerstones breather additive's betting coaxed court comparative construe bearably advocated boisterously arrogating consumptive crueler conveyers coop contrasters berry's channeled berries columnized anecdotal abolishes cajoling carved buckled arched appearances biting broaching behaves celery analytic adaptable beaks coalition annual acrylic agape abridge afghans amphibiously blaming bucked chop coke backlash colleague's commander assertively asteroidal archbishop adsorb almond aspect bricker aliens coached ambiguities awesome altos commemorate balance condensing attributions abrades attached awaken atrophy billions brazes counterrevolution choruses counselling brewing adrift coupon checked chair below chips ablaze botching attraction causes battlegrounds assertions buy coin befouling coverlet's admirer career barnyards brochure's contrives asserts cleaved cannister contrastingly blending boggling awaits congregating bandit's anacondas chimney's adhesions bandaging audacity blot's bathing blunting bequest's any backs certifier bloke carbon's breveted altered antic convertibility amassing admission's bracing canton borrow company camera's absentee's advisability blackboard's crickets buckboard's allocators collected biopsy boldly canoe's altogether breads autonavigators bilges combed basses broadly classifies blend bereavement another's backward beater clambered congressionally acculturation capped adventuring appeases buoyancy bridesmaid's converges biographical aftermath audiometry affixed bytes astrophysical chorus boastful administratively causation's cogently creators comrade calculative anemometry bullies bulletin's cashiers clockers certified canonically ambulatory chaplain's chubby articulately context america's anger cranky aspersions countries communicator chroniclers coronet barest boxed compatibility amateur characterizing contemplations agreements caw anodes blazes concurrence anachronisms county commends cliques correspondingly busboys approve absconding barbarities absorptions cider aggravation capturing braid bonds clam commonality artichoke's bringer alters authorizers beginning's bounded candor chancing agitated approachers covets cools bluebonnet boomerang apprehensively bickers banshee's checksums anteater airstrips bevels bedtime arsine campaigned aggressive avoid accelerate copings armies astuteness blips compilation's bureaucrat's bandages brainy canonicalize booms charmers capturers applicable alas academy brawl bangs atypical crooks consuls antelopes bladder's crucial bottles binge abscesses analog blurs columnize buns accountancy ardent achievement's corrective afferent anthem's adsorbing abutment averting blackberries agate allegation's anonymity boor's airfields commence collier bedspreads channels bisection's appellants councillor's arguable anomalies armor alienates absolving basset combat crimson contributing acutely bachelor breasted accumulators censure abscissas cots boll aspirating browbeats abet blanketing craziest boomtowns aberrant adequacy alleles adulterated buzzer banging aren't accumulating bondsmen centralized appreciative aggressively colonized bifocals activist anniversaries cradled arithmetize chemistries choose bedbug's celebrates converter bunkmates coyote baseline acrobat's arianists coach bedbug antibiotics collides contour cot's cloud asses conveniently birthed angels chronology confidentially consorts angola algorithm advertisements arrives claimable brag conclusions astringent commitments capitalists climbed bobbins ballerinas corkers bootstrap agitation comprising avid alibi's anesthetized argumentative boost appointed conservative baronial compelling breakfast congratulation antitoxin's alarmingly autographed backup bitwise compromised abolition boulders cane causality ambassador classifiers baggers boldface arguments chairs agonizes birches acoustically attendees accusal consigns condescending clique control's cells corridor's antithetical bandwagon amassed bikini ambivalently bridgeable bandstand's aureomycin commentary beatific coexisted arithmetizes appalled appetite combustion beauteous built animatedly catchers abjection antiquities brilliantly anode's cowardly concedes cohabitation contested bismuth coves banking clauses appropriating befriend academically breakdowns afresh brier contour's appease bantered astound advertisers benedictions addressable complaint's arose burgeoning automatically crackles abducted bluing comparatively butchery bridesmaid blurting confuses complemented annotation bafflers absorption's announcements affirmatively cantor's assertive automotive bicyclers beholding bootstrapping angiography amphibian's colored algebraically coordinated bibliographical aqueduct's atheist circle contrived asians cancer's applicator's balloons attempter airs barkers apparent balancers berlin bravest adjustor ameliorated algol buildings contacted clock bedders conjuring cantankerously accountably bibliography canvasser bulging collector's ascription anchovies babied bridges bassinets crawls chestnut's barrage's aside correctly capitalized babyhood collection's bookkeeper's correspondent's aflame belays bordellos animated apologizes achievements alleging crowning criticised actuarially athletics belles cab allay blamable constellation attract bunnies bushwhacks bartender conference's battlefront's arterial boring adulterate alarm counts alphabetized considerations bisector connection browning bravura catcher blocks affirmations barren bufferrer backwater confined bungled casualness creature benders bleedings bathtub colon aborted conquer advancement americas advising bibliophile coronet's administer bombards contaminated arousal assuming condemned ampoule's assenting courting attunes adoptions anabaptist's bedder's applied bonnets arise bulb becalming biographer contradicts breed angularly cocked chatter boatload as broadener cache columnates clays capitalize armament browned aquifer continuities colony ancestry clam's backing counterexample abridging broadcasting beaming constructively betters combing belly credibly corps comedian's comfortabilities belie convoys crossbar's chanticleer's amelia apologized avionics conversant batons considerate burgher closer alleys chloroplast's bootleger buffered acidic advertise brute's buff's concealing criticise ash college's accredit abridged crowed considering begot alignment bylaw's beacon academies alleged adjusters battlements autocorrelation aperture arabs conjurer bones considerably capricious admonishes abrade aloha canonicalizes cot ashore celled cringes addresser continuum breeze's boosts abbreviates coasted cavern's catastrophe busy coercion busts clench bell boys beveled bellyfull courthouses billets bottled audition contest attractor bootstrapped clerking circumvented conquers aliment anesthetizing bathes continually conveyed banner's collapsed canvases analogue's contradiction's amorphously blitzkrieg backbends caveat's bankrupting conspiracies cardinal bicarbonate broiler abortive befogged crested bisection beatitude's crept assessors convinces aimed clasps camper accustom ballistic claimed croppers concatenate block connote adjustably continents appreciation connecting asteroid corpse's breathed abruptness calibers codification's albanians analyst's assessments abscissa benign classically bedraggle abash bride abducts ancestor's autonavigator's basing chivalrously conceptually advantaged butts compactors bake certainly byline's contingency antisera beatings audaciousness brasses concerning bit bobs counterpart's accepters boxing bestowal circuitously amorphous augur accesses belabors attraction's booting creditor clue's baptizing countryside characteristics complete coconut abstract bleached compensation confused coexist accustoming breakpoints cities attainably arena cinders antipode backwaters corrupting carder also arthritis blackmailed cobweb's bandage broadest abeyance broadband adequate adversity appropriators ascending business's ambled chide capitalist cellar cosmology audiograms abating blimps bet's blaster businessmen bricklayer's bracelet contractual cherished antiresonator burp braced conduction analogues blockhouse basted ballooning bolstered barbed characteristically bunk convenient broils boatmen addressees abolishment cemetery antecedent's accommodated canto countenance admixes arianism blazing bestow conspiracy aft autobiographical airfield's compartmentalized blasts airman commons alliterations biller aims compile counterpointing ascended brindled chandelier buoyed alleviating crudest cremated camouflage bog's contraster confer convenience courtier's bulldog admonish awarders arcade bloating adagios archived anesthesia bluster confirming afraid chinning bonfires courteously bravado bumble comet's coffees bookshelf's abode complication adumbrating archeological correlating apostrophes ambushes abusive chateau's allowances baselines concession's charmed authenticators attracted assembles babies blasphemousness cremating bubbles attainments bluish checkpoints banquet contemporariness bargain blacking committing caption abashes confessor aerates comical country's behest antinomy airing backstitch courtroom brunette bible's circumvent bilabial accusative clobbered bear cackles byte captivation cloning behavioral amends allocated boathouse blusters coursed alveoli cottage awareness ablate application's anglophobia bodyweight anachronism's caption's contains apartments approachability connectors acrid arduously cowslip's approximation arduous civilizations brayed communicate awning acclaims closet academy's achievers adjacent anarchist boomerangs brigade action charities auscultates concealers convention's arrangement adducing choice anion's contrive applicative accomplishments asters allocate chronologically claimant closed attacked artifacts bank bedroom's cannisters clobber becoming bandwagon's calorie's converse articulators abnormally abrading brunt broom's airbags allergy abreast adjusts alcibiades commutes appellate convicted aristotelian africans concatenating abductors actuarial commissions baud column ballgowns baking blitzes atoned acquire businesslike civic clover brands climaxes buzzes cobwebs conceiving allegiance's bushwhacking astonish betide argued bolt conquerer arsenals agrees continuing coefficients aeronautical academics caverns comparison autopsied auspiciously civil balcony championship's blockaded bulldozed blankly challengers confounds albeit berliners best atomizes allegretto awkward cathode's adoptive amps arm codifications changeable consequence's cranberries amenable blustered burnishing aspirators acoustic buries breadboard consumptions bedazzling causeways cousins bathrobe borneo carry crazily climbs crackled conspirator beautifier arbitrating concession cookery adultery conundrum's acquisition's blasphemed coops connoted communist's codeword's complainer authentically aerosols buckwheat abysses agitate bedside behoove absented continuances affronted ambulances ballast's cleanse blunted bend cautionings averse commissioning assembly belligerence commanded briton's abjectly console cookie contracts algaecide contractor bitch appointee avocation's complying asks coherently abodes croaking consolidates blasphemously braided atomize continuations broth crag booster anesthetic assessor convenes broods canoes cleaner's causeway's anthropological chirped bargaining bees centimeter aerobics clothed closures astronauts allows bridegroom circumlocution advisor's bloodhounds bogus besieged calculates agers bloodshed chain beachhead's attend bushel's booboo aspirations allot bent concentric aphasia burglarproofed christmas cooperator's construct balkanizing creature's cavalry backyard bestowed bruised bedspread bewails cohered bluebirds aggrieving berates addict conveyances civilian availability abbe captors antics acquired colorless barbarity attendance brilliance accessibility brotherliness bride's closeted bedridden annoyer conceptualizing abolitionists consented adopted convinced bathrobe's benediction's circumstances accumulations accurateness assumes bribing criticisms bra atheists anesthetizes concatenations brigadier cheapened anchoritism contemplated bushes bootlegged blackmailer ruby-bdb-0.6.6/examples/zeroc.rb000066400000000000000000000015041154714021300165140ustar00rootroot00000000000000#!/usr/bin/ruby require './clean.rb' BDB::Env.cleanup("tmp", true) module ZeroC def bdb_fetch_value(a) a.sub(/\0$/, '') end def bdb_store_value(a) a + "\0" end alias bdb_fetch_key bdb_fetch_value alias bdb_store_key bdb_store_value end module BDB class A < Btree include ZeroC end end $option = {"set_pagesize" => 1024, "set_cachesize" => [0, 32 * 1024, 0]} db = BDB::A.open "tmp/basic", nil, "w", $option File.foreach("wordlist") do |line| line.chomp! db[line] = line.reverse end db.each do |k, v| if k != v.reverse || /\0/ =~ k || /\0/ =~ v print "ERROR : #{k.inspect} -- #{v.inspect}\n" end end db.close db = BDB::Btree.open "tmp/basic", $option db.each do |k, v| if k[-1] != 0 || v[-1] != 0 print "ERROR : #{k.inspect} -- #{v.inspect}\n" end end ruby-bdb-0.6.6/extconf.rb000066400000000000000000000033421154714021300152240ustar00rootroot00000000000000#!/usr/bin/ruby require 'mkmf' def rule(target, clean = nil) wr = "#{target}: \t@for subdir in $(SUBDIRS); do \\ \t\t(cd $${subdir} && $(MAKE) #{target}); \\ \tdone; " if clean != nil wr << "\t@-rm tmp/* tests/tmp/* 2> /dev/null\n" wr << "\t@rm Makefile\n" if clean end wr end subdirs = if $configure_args.has_key?("--make") [] else Dir["*"].select do |subdir| /\Abdbxml/ !~ subdir && File.file?(subdir + "/extconf.rb") end end begin make = open("Makefile", "w") make.print <<-EOF SUBDIRS = #{subdirs.join(' ')} #{rule('all')} #{rule('static')} #{rule('clean', false)} #{rule('distclean', true)} #{rule('realclean', true)} #{rule('install')} #{rule('site-install')} #{rule('unknown')} %.html: %.rd \trd2 $< > ${<:%.rd=%.html} EOF make.print "HTML = bdb.html" docs = Dir['docs/*.rd'] docs.each {|x| make.print " \\\n\t#{x.sub(/\.rd$/, '.html')}" } make.print "\n\nRDOC = bdb.rd" docs.each {|x| make.print " \\\n\t#{x}" } make.puts make.print <<-EOF rdoc: docs/doc/index.html docs/doc/index.html: $(RDOC) \t@-(cd docs; rdoc .) ri: \t@-(rdoc -r docs/*rb) ri-site: \t@-(rdoc -R docs/*rb) rd2: html html: $(HTML) test: $(DLLIB) EOF Dir.foreach('tests') do |x| next if /^\./ =~ x || /(_\.rb|~)$/ =~ x next if FileTest.directory?(x) make.print "\t-#{CONFIG['RUBY_INSTALL_NAME']} tests/#{x}\n" end ensure make.close end subdirs.each do |subdir| STDERR.puts("#{$0}: Entering directory `#{subdir}'") Dir.chdir(subdir) system("#{CONFIG['RUBY_INSTALL_NAME']} extconf.rb " + ARGV.join(" ")) Dir.chdir("..") STDERR.puts("#{$0}: Leaving directory `#{subdir}'") end $makefile_created = true ruby-bdb-0.6.6/src/000077500000000000000000000000001154714021300140165ustar00rootroot00000000000000ruby-bdb-0.6.6/src/bdb.c000066400000000000000000000771111154714021300147200ustar00rootroot00000000000000#include "bdb.h" VALUE bdb_cEnv; VALUE bdb_eFatal; VALUE bdb_eLock, bdb_eLockDead, bdb_eLockHeld, bdb_eLockGranted; #if HAVE_CONST_DB_REP_UNAVAIL VALUE bdb_eRepUnavail; #endif VALUE bdb_mDb; VALUE bdb_cCommon, bdb_cBtree, bdb_cRecnum, bdb_cHash, bdb_cRecno, bdb_cUnknown; VALUE bdb_cDelegate; #if HAVE_TYPE_DB_KEY_RANGE VALUE bdb_sKeyrange; #endif #if HAVE_CONST_DB_QUEUE VALUE bdb_cQueue; #endif VALUE bdb_cTxn, bdb_cTxnCatch; VALUE bdb_cCursor; VALUE bdb_cLock, bdb_cLockid; VALUE bdb_cLsn; VALUE bdb_mMarshal; ID bdb_id_dump, bdb_id_load; ID bdb_id_current_db; VALUE bdb_errstr; int bdb_errcall = 0; #if ! HAVE_DB_STRERROR char * db_strerror(int err) { if (err == 0) return "" ; if (err > 0) return strerror(err) ; switch (err) { #if HAVE_CONST_DB_INCOMPLETE case DB_INCOMPLETE: return ("DB_INCOMPLETE: Sync was unable to complete"); #endif #if HAVE_CONST_DB_KEYEMPTY case DB_KEYEMPTY: return ("DB_KEYEMPTY: Non-existent key/data pair"); #endif #if HAVE_CONST_DB_KEYEXIST case DB_KEYEXIST: return ("DB_KEYEXIST: Key/data pair already exists"); #endif #if HAVE_CONST_DB_LOCK_DEADLOCK case DB_LOCK_DEADLOCK: return ("DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock"); #endif #if HAVE_CONST_DB_LOCK_NOTGRANTED case DB_LOCK_NOTGRANTED: return ("DB_LOCK_NOTGRANTED: Lock not granted"); #endif #if HAVE_CONST_DB_LOCK_NOTHELD case DB_LOCK_NOTHELD: return ("DB_LOCK_NOTHELD: Lock not held by locker"); #endif #if HAVE_CONST_DB_NOTFOUND case DB_NOTFOUND: return ("DB_NOTFOUND: No matching key/data pair found"); #endif #if HAVE_CONST_DB_RUNRECOVERY case DB_RUNRECOVERY: return ("DB_RUNRECOVERY: Fatal error, run database recovery"); #endif #if HAVE_CONST_DB_OLD_VERSION case DB_OLD_VERSION: return ("DB_OLD_VERSION: The database cannot be opened without being first upgraded"); #endif default: return "Unknown Error" ; } } #endif int bdb_test_error(int comm) { VALUE error; switch (comm) { case 0: #if HAVE_CONST_DB_NOTFOUND case DB_NOTFOUND: #endif #if HAVE_CONST_DB_KEYEMPTY case DB_KEYEMPTY: #endif #if HAVE_CONST_DB_KEYEXIST case DB_KEYEXIST: #endif return comm; break; #if HAVE_CONST_DB_INCOMPLETE case DB_INCOMPLETE: comm = 0; return comm; break; #endif #if HAVE_CONST_DB_REP_UNAVAIL case DB_REP_UNAVAIL: error = bdb_eRepUnavail; break; #endif #if HAVE_CONST_DB_LOCK_DEADLOCK case DB_LOCK_DEADLOCK: #endif case EAGAIN: error = bdb_eLockDead; break; #if HAVE_CONST_DB_LOCK_NOTGRANTED case DB_LOCK_NOTGRANTED: error = bdb_eLockGranted; break; #endif #if HAVE_CONST_DB_LOCK_NOTHELD case DB_LOCK_NOTHELD: error = bdb_eLockHeld; break; #endif #if HAVE_ST_DB_ASSOCIATE case BDB_ERROR_PRIVATE: error = bdb_eFatal; bdb_errcall = 1; bdb_errstr = rb_inspect(rb_gv_get("$!")); comm = 0; break; #endif default: error = bdb_eFatal; break; } if (bdb_errcall) { bdb_errcall = 0; if (comm) { rb_raise(error, "%s -- %s", StringValuePtr(bdb_errstr), db_strerror(comm)); } else { rb_raise(error, "%s", StringValuePtr(bdb_errstr)); } } else rb_raise(error, "%s", db_strerror(comm)); } void Init_bdb() { int major, minor, patch; VALUE version; if (rb_const_defined_at(rb_cObject, rb_intern("BDB"))) { rb_raise(rb_eNameError, "module already defined"); } version = rb_tainted_str_new2(db_version(&major, &minor, &patch)); if (major != DB_VERSION_MAJOR || minor != DB_VERSION_MINOR || patch != DB_VERSION_PATCH) { rb_raise(rb_eNotImpError, "\nBDB needs compatible versions of libdb & db.h\n\tyou have db.h version %d.%d.%d and libdb version %d.%d.%d\n", DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH, major, minor, patch); } bdb_mMarshal = rb_const_get(rb_cObject, rb_intern("Marshal")); bdb_id_current_db = rb_intern("__bdb_current_db__"); bdb_id_dump = rb_intern("dump"); bdb_id_load = rb_intern("load"); bdb_mDb = rb_define_module("BDB"); bdb_eFatal = rb_define_class_under(bdb_mDb, "Fatal", rb_eStandardError); bdb_eLock = rb_define_class_under(bdb_mDb, "LockError", bdb_eFatal); bdb_eLockDead = rb_define_class_under(bdb_mDb, "LockDead", bdb_eLock); bdb_eLockHeld = rb_define_class_under(bdb_mDb, "LockHeld", bdb_eLock); bdb_eLockGranted = rb_define_class_under(bdb_mDb, "LockGranted", bdb_eLock); #if HAVE_CONST_DB_REP_UNAVAIL bdb_eRepUnavail = rb_define_class_under(bdb_mDb, "RepUnavail", bdb_eFatal); #endif /* CONSTANT */ rb_define_const(bdb_mDb, "VERSION", version); rb_define_const(bdb_mDb, "VERSION_MAJOR", INT2FIX(major)); rb_define_const(bdb_mDb, "VERSION_MINOR", INT2FIX(minor)); rb_define_const(bdb_mDb, "VERSION_PATCH", INT2FIX(patch)); rb_define_const(bdb_mDb, "VERSION_NUMBER", INT2NUM(BDB_VERSION)); #if HAVE_CONST_DB_BTREE rb_define_const(bdb_mDb, "BTREE", INT2FIX(DB_BTREE)); #endif #if HAVE_CONST_DB_HASH rb_define_const(bdb_mDb, "HASH", INT2FIX(DB_HASH)); #endif #if HAVE_CONST_DB_RECNO rb_define_const(bdb_mDb, "RECNO", INT2FIX(DB_RECNO)); #endif #if HAVE_CONST_DB_QUEUE rb_define_const(bdb_mDb, "QUEUE", INT2FIX(DB_QUEUE)); #else rb_define_const(bdb_mDb, "QUEUE", INT2FIX(0)); #endif #if HAVE_CONST_DB_UNKNOWN rb_define_const(bdb_mDb, "UNKNOWN", INT2FIX(DB_UNKNOWN)); #endif #if HAVE_CONST_DB_AFTER rb_define_const(bdb_mDb, "AFTER", INT2FIX(DB_AFTER)); #endif #if HAVE_CONST_DB_AGGRESSIVE rb_define_const(bdb_mDb, "AGGRESSIVE", INT2FIX(DB_AGGRESSIVE)); #endif #if HAVE_CONST_DB_APPEND rb_define_const(bdb_mDb, "APPEND", INT2FIX(DB_APPEND)); #endif #if HAVE_CONST_DB_ARCH_ABS rb_define_const(bdb_mDb, "ARCH_ABS", INT2FIX(DB_ARCH_ABS)); #endif #if HAVE_CONST_DB_ARCH_DATA rb_define_const(bdb_mDb, "ARCH_DATA", INT2FIX(DB_ARCH_DATA)); #endif #if HAVE_CONST_DB_ARCH_LOG rb_define_const(bdb_mDb, "ARCH_LOG", INT2FIX(DB_ARCH_LOG)); #endif #if HAVE_CONST_DB_BEFORE rb_define_const(bdb_mDb, "BEFORE", INT2FIX(DB_BEFORE)); #endif #if HAVE_CONST_DB_CACHED_COUNTS rb_define_const(bdb_mDb, "CACHED_COUNTS", INT2FIX(DB_CACHED_COUNTS)); #endif #if HAVE_CONST_DB_CDB_ALLDB rb_define_const(bdb_mDb, "CDB_ALLDB", INT2FIX(DB_CDB_ALLDB)); #endif #if HAVE_CONST_DB_CHECKPOINT rb_define_const(bdb_mDb, "CHECKPOINT", INT2FIX(DB_CHECKPOINT)); #endif #if HAVE_CONST_DB_CLIENT rb_define_const(bdb_mDb, "CLIENT", INT2FIX(DB_CLIENT)); #endif #if HAVE_CONST_DB_RPCCLIENT rb_define_const(bdb_mDb, "RPCCLIENT", INT2FIX(DB_RPCCLIENT)); #endif #if HAVE_CONST_DB_CONFIG rb_define_const(bdb_mDb, "CONFIG", INT2FIX(DB_CONFIG)); #endif #if ! HAVE_CONST_DB_CONSUME rb_define_const(bdb_mDb, "CONSUME", INT2FIX(0)); #else rb_define_const(bdb_mDb, "CONSUME", INT2FIX(DB_CONSUME)); #endif #if HAVE_CONST_DB_CONSUME_WAIT rb_define_const(bdb_mDb, "CONSUME_WAIT", INT2FIX(DB_CONSUME_WAIT)); #endif #if HAVE_CONST_DB_CREATE rb_define_const(bdb_mDb, "CREATE", INT2FIX(DB_CREATE)); #endif #if HAVE_CONST_DB_CURLSN rb_define_const(bdb_mDb, "CURLSN", INT2FIX(DB_CURLSN)); #endif #if HAVE_CONST_DB_CURRENT rb_define_const(bdb_mDb, "CURRENT", INT2FIX(DB_CURRENT)); #endif #if HAVE_CONST_DB_DIRTY_READ rb_define_const(bdb_mDb, "DIRTY_READ", INT2FIX(DB_DIRTY_READ)); #else rb_define_const(bdb_mDb, "DIRTY_READ", INT2FIX(0)); #endif #if HAVE_CONST_DB_READ_COMMITTED rb_define_const(bdb_mDb, "READ_COMMITTED", INT2FIX(DB_READ_COMMITTED)); #endif #if HAVE_CONST_DB_READ_UNCOMMITTED rb_define_const(bdb_mDb, "READ_UNCOMMITTED", INT2FIX(DB_READ_UNCOMMITTED)); #endif #if HAVE_CONST_DB_STAT_ALL rb_define_const(bdb_mDb, "STAT_ALL", INT2FIX(DB_STAT_ALL)); #endif #if HAVE_CONST_DB_STAT_SUBSYSTEM rb_define_const(bdb_mDb, "STAT_SUBSYSTEM", INT2FIX(DB_STAT_SUBSYSTEM)); #endif #if HAVE_CONST_DB_DBT_MALLOC rb_define_const(bdb_mDb, "DBT_MALLOC", INT2FIX(DB_DBT_MALLOC)); #endif #if HAVE_CONST_DB_DBT_PARTIAL rb_define_const(bdb_mDb, "DBT_PARTIAL", INT2FIX(DB_DBT_PARTIAL)); #endif #if ! HAVE_CONST_DB_DBT_REALLOC rb_define_const(bdb_mDb, "DBT_REALLOC", INT2FIX(0)); #else rb_define_const(bdb_mDb, "DBT_REALLOC", INT2FIX(DB_DBT_REALLOC)); #endif #if HAVE_CONST_DB_DBT_USERMEM rb_define_const(bdb_mDb, "DBT_USERMEM", INT2FIX(DB_DBT_USERMEM)); #endif #if HAVE_CONST_DB_DONOTINDEX rb_define_const(bdb_mDb, "DONOTINDEX", INT2FIX(DB_DONOTINDEX)); #endif #if HAVE_CONST_DB_DUP rb_define_const(bdb_mDb, "DUP", INT2FIX(DB_DUP)); #endif #if HAVE_CONST_DB_DUPSORT rb_define_const(bdb_mDb, "DUPSORT", INT2FIX(DB_DUPSORT)); #endif #if HAVE_CONST_DB_EXCL rb_define_const(bdb_mDb, "EXCL", INT2FIX(DB_EXCL)); #endif #if HAVE_CONST_DB_MULTIVERSION rb_define_const(bdb_mDb, "MULTIVERSION", INT2FIX(DB_MULTIVERSION)); #endif #if HAVE_CONST_DB_FAST_STAT rb_define_const(bdb_mDb, "FAST_STAT", INT2FIX(DB_FAST_STAT)); #endif #if HAVE_CONST_DB_FIRST rb_define_const(bdb_mDb, "FIRST", INT2FIX(DB_FIRST)); #endif #if HAVE_CONST_DB_FIXEDLEN rb_define_const(bdb_mDb, "FIXEDLEN", INT2FIX(DB_FIXEDLEN)); #endif #if HAVE_CONST_DB_FLUSH rb_define_const(bdb_mDb, "FLUSH", INT2FIX(DB_FLUSH)); #endif #if ! HAVE_CONST_DB_FORCE rb_define_const(bdb_mDb, "FORCE", INT2FIX(1)); #else rb_define_const(bdb_mDb, "FORCE", INT2FIX(DB_FORCE)); #endif #if ! HAVE_CONST_DB_GET_BOTH rb_define_const(bdb_mDb, "GET_BOTH", INT2FIX(9)); #else rb_define_const(bdb_mDb, "GET_BOTH", INT2FIX(DB_GET_BOTH)); #endif #if HAVE_CONST_DB_GET_RECNO rb_define_const(bdb_mDb, "GET_RECNO", INT2FIX(DB_GET_RECNO)); #endif #if HAVE_CONST_DB_HOME rb_define_const(bdb_mDb, "HOME", INT2FIX(DB_HOME)); #endif #if HAVE_CONST_DB_INCOMPLETE rb_define_const(bdb_mDb, "INCOMPLETE", INT2FIX(DB_INCOMPLETE)); #endif #if HAVE_CONST_DB_INIT_CDB rb_define_const(bdb_mDb, "INIT_CDB", INT2FIX(DB_INIT_CDB)); #endif #if HAVE_CONST_DB_INIT_LOCK rb_define_const(bdb_mDb, "INIT_LOCK", INT2FIX(DB_INIT_LOCK)); #endif #if HAVE_CONST_DB_INIT_LOG rb_define_const(bdb_mDb, "INIT_LOG", INT2FIX(DB_INIT_LOG)); #endif #if HAVE_CONST_DB_INIT_MPOOL rb_define_const(bdb_mDb, "INIT_MPOOL", INT2FIX(DB_INIT_MPOOL)); #endif #if HAVE_CONST_DB_INIT_TXN rb_define_const(bdb_mDb, "INIT_TXN", INT2FIX(DB_INIT_TXN)); #endif rb_define_const(bdb_mDb, "INIT_TRANSACTION", INT2FIX(BDB_INIT_TRANSACTION)); rb_define_const(bdb_mDb, "INIT_LOMP", INT2FIX(BDB_INIT_LOMP)); #if HAVE_CONST_DB_JOINENV rb_define_const(bdb_mDb, "JOINENV", INT2FIX(DB_JOINENV)); #endif #if HAVE_CONST_DB_JOIN_ITEM rb_define_const(bdb_mDb, "JOIN_ITEM", INT2FIX(DB_JOIN_ITEM)); #endif #if HAVE_CONST_DB_JOIN_NOSORT rb_define_const(bdb_mDb, "JOIN_NOSORT", INT2FIX(DB_JOIN_NOSORT)); #endif #if HAVE_CONST_DB_KEYFIRST rb_define_const(bdb_mDb, "KEYFIRST", INT2FIX(DB_KEYFIRST)); #endif #if HAVE_CONST_DB_KEYLAST rb_define_const(bdb_mDb, "KEYLAST", INT2FIX(DB_KEYLAST)); #endif #if HAVE_CONST_DB_LAST rb_define_const(bdb_mDb, "LAST", INT2FIX(DB_LAST)); #endif #if HAVE_CONST_DB_LOCK_CONFLICT rb_define_const(bdb_mDb, "LOCK_CONFLICT", INT2FIX(DB_LOCK_CONFLICT)); #else rb_define_const(bdb_mDb, "LOCK_CONFLICT", INT2FIX(0)); #endif #if HAVE_CONST_DB_LOCK_DEADLOCK rb_define_const(bdb_mDb, "LOCK_DEADLOCK", INT2FIX(DB_LOCK_DEADLOCK)); #endif #if HAVE_CONST_DB_LOCK_DEFAULT rb_define_const(bdb_mDb, "LOCK_DEFAULT", INT2FIX(DB_LOCK_DEFAULT)); #endif #if HAVE_CONST_DB_LOCK_GET rb_define_const(bdb_mDb, "LOCK_GET", INT2FIX(DB_LOCK_GET)); #endif #if HAVE_CONST_DB_LOCK_NOTGRANTED rb_define_const(bdb_mDb, "LOCK_NOTGRANTED", INT2FIX(DB_LOCK_NOTGRANTED)); #endif #if HAVE_CONST_DB_LOCK_NOWAIT rb_define_const(bdb_mDb, "LOCK_NOWAIT", INT2FIX(DB_LOCK_NOWAIT)); #endif #if HAVE_CONST_DB_LOCK_OLDEST rb_define_const(bdb_mDb, "LOCK_OLDEST", INT2FIX(DB_LOCK_OLDEST)); #endif #if HAVE_CONST_DB_LOCK_PUT rb_define_const(bdb_mDb, "LOCK_PUT", INT2FIX(DB_LOCK_PUT)); #endif #if HAVE_CONST_DB_LOCK_PUT_ALL rb_define_const(bdb_mDb, "LOCK_PUT_ALL", INT2FIX(DB_LOCK_PUT_ALL)); #endif #if HAVE_CONST_DB_LOCK_PUT_OBJ rb_define_const(bdb_mDb, "LOCK_PUT_OBJ", INT2FIX(DB_LOCK_PUT_OBJ)); #endif #if HAVE_CONST_DB_LOCK_RANDOM rb_define_const(bdb_mDb, "LOCK_RANDOM", INT2FIX(DB_LOCK_RANDOM)); #endif #if HAVE_CONST_DB_LOCK_YOUNGEST rb_define_const(bdb_mDb, "LOCK_YOUNGEST", INT2FIX(DB_LOCK_YOUNGEST)); #endif #if HAVE_CONST_DB_LOCK_NG rb_define_const(bdb_mDb, "LOCK_NG", INT2FIX(DB_LOCK_NG)); #endif #if HAVE_CONST_DB_LOCK_READ rb_define_const(bdb_mDb, "LOCK_READ", INT2FIX(DB_LOCK_READ)); #endif #if HAVE_CONST_DB_LOCK_WRITE rb_define_const(bdb_mDb, "LOCK_WRITE", INT2FIX(DB_LOCK_WRITE)); #endif #if HAVE_CONST_DB_LOCK_IWRITE rb_define_const(bdb_mDb, "LOCK_IWRITE", INT2FIX(DB_LOCK_IWRITE)); #endif #if HAVE_CONST_DB_LOCK_IREAD rb_define_const(bdb_mDb, "LOCK_IREAD", INT2FIX(DB_LOCK_IREAD)); #endif #if HAVE_CONST_DB_LOCK_IWR rb_define_const(bdb_mDb, "LOCK_IWR", INT2FIX(DB_LOCK_IWR)); #endif #if HAVE_CONST_DB_LOCKDOWN rb_define_const(bdb_mDb, "LOCKDOWN", INT2FIX(DB_LOCKDOWN)); #else rb_define_const(bdb_mDb, "LOCKDOWN", INT2FIX(0)); #endif #if HAVE_CONST_DB_LOCK_EXPIRE rb_define_const(bdb_mDb, "LOCK_EXPIRE", INT2FIX(DB_LOCK_EXPIRE)); #endif #if HAVE_CONST_DB_LOCK_MAXLOCKS rb_define_const(bdb_mDb, "LOCK_MAXLOCKS", INT2FIX(DB_LOCK_MAXLOCKS)); #endif #if HAVE_CONST_DB_LOCK_MINLOCKS rb_define_const(bdb_mDb, "LOCK_MINLOCKS", INT2FIX(DB_LOCK_MINLOCKS)); #endif #if HAVE_CONST_DB_LOCK_MINWRITE rb_define_const(bdb_mDb, "LOCK_MINWRITE", INT2FIX(DB_LOCK_MINWRITE)); #endif #if HAVE_CONST_DB_MPOOL_CLEAN rb_define_const(bdb_mDb, "MPOOL_CLEAN", INT2FIX(DB_MPOOL_CLEAN)); #endif #if HAVE_CONST_DB_MPOOL_CREATE rb_define_const(bdb_mDb, "MPOOL_CREATE", INT2FIX(DB_MPOOL_CREATE)); #endif #if HAVE_CONST_DB_MPOOL_DIRTY rb_define_const(bdb_mDb, "MPOOL_DIRTY", INT2FIX(DB_MPOOL_DIRTY)); #endif #if HAVE_CONST_DB_MPOOL_DISCARD rb_define_const(bdb_mDb, "MPOOL_DISCARD", INT2FIX(DB_MPOOL_DISCARD)); #endif #if HAVE_CONST_DB_MPOOL_LAST rb_define_const(bdb_mDb, "MPOOL_LAST", INT2FIX(DB_MPOOL_LAST)); #endif #if HAVE_CONST_DB_MPOOL_NEW rb_define_const(bdb_mDb, "MPOOL_NEW", INT2FIX(DB_MPOOL_NEW)); #endif #if HAVE_CONST_DB_MPOOL_PRIVATE rb_define_const(bdb_mDb, "MPOOL_PRIVATE", INT2FIX(DB_MPOOL_PRIVATE)); #endif #if HAVE_CONST_DB_OVERWRITE rb_define_const(bdb_mDb, "OVERWRITE", INT2FIX(DB_OVERWRITE)); #endif #if HAVE_CONST_DB_PRINTABLE rb_define_const(bdb_mDb, "PRINTABLE", INT2FIX(DB_PRINTABLE)); #endif rb_define_const(bdb_mDb, "NEXT", INT2FIX(DB_NEXT)); #if DB_NEXT_DUP rb_define_const(bdb_mDb, "NEXT_DUP", INT2FIX(DB_NEXT_DUP)); #endif #if HAVE_CONST_DB_NEXT_NODUP rb_define_const(bdb_mDb, "NEXT_NODUP", INT2FIX(DB_NEXT_NODUP)); #endif #if HAVE_CONST_DB_PREV_DUP rb_define_const(bdb_mDb, "PREV_DUP", INT2FIX(DB_PREV_DUP)); #endif #if HAVE_CONST_DB_PREV_NODUP rb_define_const(bdb_mDb, "PREV_NODUP", INT2FIX(DB_PREV_NODUP)); #endif #if HAVE_CONST_DB_NODUPDATA rb_define_const(bdb_mDb, "NODUPDATA", INT2FIX(DB_NODUPDATA)); #endif rb_define_const(bdb_mDb, "NOMMAP", INT2FIX(DB_NOMMAP)); #if HAVE_CONST_DB_NOORDERCHK rb_define_const(bdb_mDb, "NOORDERCHK", INT2FIX(DB_NOORDERCHK)); #endif rb_define_const(bdb_mDb, "NOOVERWRITE", INT2FIX(DB_NOOVERWRITE)); #if HAVE_CONST_DB_NOSERVER rb_define_const(bdb_mDb, "NOSERVER", INT2FIX(DB_NOSERVER)); #endif #if HAVE_CONST_DB_NOSERVER_HOME rb_define_const(bdb_mDb, "NOSERVER_HOME", INT2FIX(DB_NOSERVER_HOME)); #endif #if HAVE_CONST_DB_NOSERVER_ID rb_define_const(bdb_mDb, "NOSERVER_ID", INT2FIX(DB_NOSERVER_ID)); #endif rb_define_const(bdb_mDb, "NOSYNC", INT2FIX(DB_NOSYNC)); #if HAVE_CONST_DB_OLD_VERSION rb_define_const(bdb_mDb, "OLD_VERSION", INT2FIX(DB_OLD_VERSION)); #endif #if HAVE_CONST_DB_ORDERCHKONLY rb_define_const(bdb_mDb, "ORDERCHKONLY", INT2FIX(DB_ORDERCHKONLY)); #endif #if HAVE_CONST_DB_PAD rb_define_const(bdb_mDb, "PAD", INT2FIX(DB_PAD)); #endif #if ! HAVE_CONST_DB_POSITION rb_define_const(bdb_mDb, "POSITION", INT2FIX(0)); #else rb_define_const(bdb_mDb, "POSITION", INT2FIX(DB_POSITION)); #endif rb_define_const(bdb_mDb, "PREV", INT2FIX(DB_PREV)); #if ! HAVE_CONST_DB_PRIVATE rb_define_const(bdb_mDb, "PRIVATE", INT2FIX(0)); #else rb_define_const(bdb_mDb, "PRIVATE", INT2FIX(DB_PRIVATE)); #endif #if HAVE_CONST_DB_RDONLY rb_define_const(bdb_mDb, "RDONLY", INT2FIX(DB_RDONLY)); #endif #if HAVE_CONST_DB_RECNUM rb_define_const(bdb_mDb, "RECNUM", INT2FIX(DB_RECNUM)); #endif #if HAVE_CONST_DB_RECORDCOUNT rb_define_const(bdb_mDb, "RECORDCOUNT", INT2FIX(DB_RECORDCOUNT)); #endif #if HAVE_CONST_DB_RECOVER rb_define_const(bdb_mDb, "RECOVER", INT2FIX(DB_RECOVER)); #endif #if HAVE_CONST_DB_RECOVER_FATAL rb_define_const(bdb_mDb, "RECOVER_FATAL", INT2FIX(DB_RECOVER_FATAL)); #endif #if HAVE_CONST_DB_RENUMBER rb_define_const(bdb_mDb, "RENUMBER", INT2FIX(DB_RENUMBER)); #endif #if HAVE_CONST_DB_RMW rb_define_const(bdb_mDb, "RMW", INT2NUM(DB_RMW)); #else rb_define_const(bdb_mDb, "RMW", INT2NUM(0)); #endif #if HAVE_CONST_DB_SALVAGE rb_define_const(bdb_mDb, "SALVAGE", INT2FIX(DB_SALVAGE)); #endif #if HAVE_CONST_DB_SECONDARY_BAD rb_define_const(bdb_mDb, "SECONDARY_BAD", INT2FIX(DB_SECONDARY_BAD)); #else rb_define_const(bdb_mDb, "SECONDARY_BAD", INT2FIX(0)); #endif #if HAVE_CONST_DB_SET rb_define_const(bdb_mDb, "SET", INT2FIX(DB_SET)); #endif #if HAVE_CONST_DB_SET_RANGE rb_define_const(bdb_mDb, "SET_RANGE", INT2FIX(DB_SET_RANGE)); #endif #if HAVE_CONST_DB_SET_RECNO rb_define_const(bdb_mDb, "SET_RECNO", INT2FIX(DB_SET_RECNO)); #endif #if HAVE_CONST_DB_SNAPSHOT rb_define_const(bdb_mDb, "SNAPSHOT", INT2FIX(DB_SNAPSHOT)); #endif #if HAVE_CONST_DB_STAT_CLEAR rb_define_const(bdb_mDb, "STAT_CLEAR", INT2FIX(DB_STAT_CLEAR)); #endif #if ! HAVE_CONST_DB_SYSTEM_MEM rb_define_const(bdb_mDb, "SYSTEM_MEM", INT2FIX(0)); #else rb_define_const(bdb_mDb, "SYSTEM_MEM", INT2FIX(DB_SYSTEM_MEM)); #endif #if HAVE_CONST_DB_THREAD rb_define_const(bdb_mDb, "THREAD", INT2FIX(DB_THREAD)); #endif #if HAVE_CONST_DB_ENV_THREAD rb_define_const(bdb_mDb, "ENV_THREAD", INT2FIX(DB_ENV_THREAD)); #endif #if HAVE_CONST_DB_TRUNCATE rb_define_const(bdb_mDb, "TRUNCATE", INT2FIX(DB_TRUNCATE)); #endif #if HAVE_CONST_DB_TXN_ABORT rb_define_const(bdb_mDb, "TXN_ABORT", INT2FIX(DB_TXN_ABORT)); #endif #if HAVE_CONST_DB_TXN_BACKWARD_ROLL rb_define_const(bdb_mDb, "TXN_BACKWARD_ROLL", INT2FIX(DB_TXN_BACKWARD_ROLL)); #endif #if HAVE_CONST_DB_TXN_FORWARD_ROLL rb_define_const(bdb_mDb, "TXN_FORWARD_ROLL", INT2FIX(DB_TXN_FORWARD_ROLL)); #endif #if HAVE_CONST_DB_TXN_NOSYNC rb_define_const(bdb_mDb, "TXN_NOSYNC", INT2FIX(DB_TXN_NOSYNC)); #endif #if HAVE_CONST_DB_TXN_NOT_DURABLE rb_define_const(bdb_mDb, "TXN_NOT_DURABLE", INT2FIX(DB_TXN_NOT_DURABLE)); #endif #if HAVE_CONST_DB_TXN_APPLY rb_define_const(bdb_mDb, "TXN_APPLY", INT2FIX(DB_TXN_APPLY)); #endif #if HAVE_CONST_DB_TXN_PRINT rb_define_const(bdb_mDb, "TXN_PRINT", INT2FIX(DB_TXN_PRINT)); #endif #if HAVE_CONST_DB_TXN_WRITE_NOSYNC rb_define_const(bdb_mDb, "TXN_WRITE_NOSYNC", INT2FIX(DB_TXN_WRITE_NOSYNC)); #endif #if HAVE_CONST_DB_TXN_SNAPSHOT rb_define_const(bdb_mDb, "TXN_SNAPSHOT", INT2FIX(DB_TXN_SNAPSHOT)); #endif #if HAVE_CONST_DB_UPGRADE rb_define_const(bdb_mDb, "UPGRADE", INT2FIX(DB_UPGRADE)); #endif #if HAVE_CONST_DB_USE_ENVIRON rb_define_const(bdb_mDb, "USE_ENVIRON", INT2FIX(DB_USE_ENVIRON)); #endif #if HAVE_CONST_DB_USE_ENVIRON_ROOT rb_define_const(bdb_mDb, "USE_ENVIRON_ROOT", INT2FIX(DB_USE_ENVIRON_ROOT)); #endif #if HAVE_CONST_DB_TXN_NOWAIT rb_define_const(bdb_mDb, "TXN_NOWAIT", INT2FIX(DB_TXN_NOWAIT)); #else rb_define_const(bdb_mDb, "TXN_NOWAIT", INT2FIX(0)); #endif #if HAVE_CONST_DB_TXN_SYNC rb_define_const(bdb_mDb, "TXN_SYNC", INT2FIX(DB_TXN_SYNC)); #else rb_define_const(bdb_mDb, "TXN_SYNC", INT2FIX(0)); #endif #if HAVE_CONST_DB_VERB_CHKPOINT rb_define_const(bdb_mDb, "VERB_CHKPOINT", INT2FIX(DB_VERB_CHKPOINT)); #else rb_define_const(bdb_mDb, "VERB_CHKPOINT", INT2FIX(1)); #endif #if HAVE_CONST_DB_VERB_DEADLOCK rb_define_const(bdb_mDb, "VERB_DEADLOCK", INT2FIX(DB_VERB_DEADLOCK)); #else rb_define_const(bdb_mDb, "VERB_DEADLOCK", INT2FIX(1)); #endif #if HAVE_CONST_DB_VERB_RECOVERY rb_define_const(bdb_mDb, "VERB_RECOVERY", INT2FIX(DB_VERB_RECOVERY)); #else rb_define_const(bdb_mDb, "VERB_RECOVERY", INT2FIX(1)); #endif #if HAVE_CONST_DB_VERB_WAITSFOR rb_define_const(bdb_mDb, "VERB_WAITSFOR", INT2FIX(DB_VERB_WAITSFOR)); #else rb_define_const(bdb_mDb, "VERB_WAITSFOR", INT2FIX(1)); #endif #if HAVE_CONST_DB_WRITECURSOR rb_define_const(bdb_mDb, "WRITECURSOR", INT2FIX(DB_WRITECURSOR)); #else rb_define_const(bdb_mDb, "WRITECURSOR", INT2NUM(DB_RMW)); #endif #if HAVE_CONST_DB_VERB_REPLICATION rb_define_const(bdb_mDb, "VERB_REPLICATION", INT2FIX(DB_VERB_REPLICATION)); #endif #if HAVE_CONST_DB_VERIFY rb_define_const(bdb_mDb, "VERIFY", INT2FIX(DB_VERIFY)); #endif #if HAVE_CONST_DB_XA_CREATE rb_define_const(bdb_mDb, "XA_CREATE", INT2FIX(DB_XA_CREATE)); #endif #if HAVE_CONST_DB_XIDDATASIZE rb_define_const(bdb_mDb, "XIDDATASIZE", INT2FIX(DB_XIDDATASIZE)); #endif #if HAVE_CONST_BDB_TXN_COMMIT rb_define_const(bdb_mDb, "TXN_COMMIT", INT2FIX(BDB_TXN_COMMIT)); #endif #if HAVE_CONST_DB_REGION_INIT rb_define_const(bdb_mDb, "REGION_INIT", INT2FIX(DB_REGION_INIT)); #endif #if HAVE_CONST_DB_AUTO_COMMIT rb_define_const(bdb_mDb, "AUTO_COMMIT", INT2FIX(DB_AUTO_COMMIT)); #endif #if HAVE_CONST_DB_REP_CONF_LEASE rb_define_const(bdb_mDb, "REP_CONF_LEASE", INT2FIX(DB_REP_CONF_LEASE)); #endif #if HAVE_CONST_DB_REP_HEARTBEAT_MONITOR rb_define_const(bdb_mDb, "DB_REP_HEARTBEAT_MONITOR", INT2FIX(DB_REP_HEARTBEAT_MONITOR)); #endif #if HAVE_CONST_DB_REP_HEARTBEAT_SEND rb_define_const(bdb_mDb, "DB_REP_HEARTBEAT_SEND", INT2FIX(DB_REP_HEARTBEAT_SEND)); #endif #if HAVE_CONST_DB_REP_CLIENT rb_define_const(bdb_mDb, "REP_CLIENT", INT2FIX(DB_REP_CLIENT)); #endif #if HAVE_CONST_DB_REP_DUPMASTER rb_define_const(bdb_mDb, "REP_DUPMASTER", INT2FIX(DB_REP_DUPMASTER)); #endif #if HAVE_CONST_DB_REP_HOLDELECTION rb_define_const(bdb_mDb, "REP_HOLDELECTION", INT2FIX(DB_REP_HOLDELECTION)); #endif #if HAVE_CONST_DB_REP_MASTER rb_define_const(bdb_mDb, "REP_MASTER", INT2FIX(DB_REP_MASTER)); #endif #if HAVE_CONST_DB_REP_NEWMASTER rb_define_const(bdb_mDb, "REP_NEWMASTER", INT2FIX(DB_REP_NEWMASTER)); #endif #if HAVE_CONST_DB_REP_NEWSITE rb_define_const(bdb_mDb, "REP_NEWSITE", INT2FIX(DB_REP_NEWSITE)); #endif #if HAVE_CONST_DB_REP_LOGSONLY rb_define_const(bdb_mDb, "REP_LOGSONLY", INT2FIX(DB_REP_LOGSONLY)); #endif #if HAVE_CONST_DB_REP_OUTDATED rb_define_const(bdb_mDb, "REP_OUTDATED", INT2FIX(DB_REP_OUTDATED)); #endif #if HAVE_CONST_DB_REP_PERMANENT rb_define_const(bdb_mDb, "REP_PERMANENT", INT2FIX(DB_REP_PERMANENT)); #endif #if HAVE_CONST_DB_REP_UNAVAIL rb_define_const(bdb_mDb, "REP_UNAVAIL", INT2FIX(DB_REP_UNAVAIL)); #endif #if HAVE_CONST_DB_REP_ISPERM rb_define_const(bdb_mDb, "REP_ISPERM", INT2FIX(DB_REP_ISPERM)); #endif #if HAVE_CONST_DB_REP_NOTPERM rb_define_const(bdb_mDb, "REP_NOTPERM", INT2FIX(DB_REP_NOTPERM)); #endif #if HAVE_CONST_DB_REP_IGNORE rb_define_const(bdb_mDb, "REP_IGNORE", INT2FIX(DB_REP_IGNORE)); #endif #if HAVE_CONST_DB_REP_JOIN_FAILURE rb_define_const(bdb_mDb, "REP_JOIN_FAILURE", INT2FIX(DB_REP_JOIN_FAILURE)); #endif #if HAVE_CONST_DB_EID_BROADCAST rb_define_const(bdb_mDb, "EID_BROADCAST", INT2FIX(DB_EID_BROADCAST)); #endif #if HAVE_CONST_DB_EID_INVALID rb_define_const(bdb_mDb, "EID_INVALID", INT2FIX(DB_EID_INVALID)); #endif #if HAVE_CONST_DB_SET_LOCK_TIMEOUT rb_define_const(bdb_mDb, "SET_LOCK_TIMEOUT", INT2FIX(DB_SET_LOCK_TIMEOUT)); #endif #if HAVE_CONST_DB_SET_TXN_TIMEOUT rb_define_const(bdb_mDb, "SET_TXN_TIMEOUT", INT2FIX(DB_SET_TXN_TIMEOUT)); #endif #if HAVE_CONST_DB_LOCK_GET_TIMEOUT rb_define_const(bdb_mDb, "LOCK_GET_TIMEOUT", INT2FIX(DB_LOCK_GET_TIMEOUT)); #endif #if HAVE_CONST_DB_LOCK_TIMEOUT rb_define_const(bdb_mDb, "LOCK_TIMEOUT", INT2FIX(DB_LOCK_TIMEOUT)); #endif #if HAVE_CONST_DB_ENCRYPT_AES rb_define_const(bdb_mDb, "ENCRYPT_AES", INT2FIX(DB_ENCRYPT_AES)); #endif #if HAVE_CONST_DB_ENCRYPT rb_define_const(bdb_mDb, "ENCRYPT", INT2FIX(DB_ENCRYPT)); #endif #if HAVE_CONST_DB_CHKSUM_SHA1 rb_define_const(bdb_mDb, "CHKSUM_SHA1", INT2FIX(DB_CHKSUM_SHA1)); #endif #if HAVE_CONST_DB_CHKSUM rb_define_const(bdb_mDb, "CHKSUM", INT2FIX(DB_CHKSUM)); #if ! HAVE_CONST_DB_CHKSUM_SHA1 rb_define_const(bdb_mDb, "CHKSUM_SHA1", INT2FIX(DB_CHKSUM)); #endif #endif #if HAVE_CONST_DB_DIRECT_DB rb_define_const(bdb_mDb, "DIRECT_DB", INT2FIX(DB_DIRECT_DB)); #endif #if HAVE_CONST_DB_DIRECT_LOG rb_define_const(bdb_mDb, "DIRECT_LOG", INT2FIX(DB_DIRECT_LOG)); #endif #if HAVE_CONST_DB_DSYNC_LOG rb_define_const(bdb_mDb, "DSYNC_LOG", INT2FIX(DB_DSYNC_LOG)); #endif #if HAVE_CONST_DB_LOG_INMEMORY rb_define_const(bdb_mDb, "LOG_INMEMORY", INT2FIX(DB_LOG_INMEMORY)); #endif #if HAVE_CONST_DB_LOG_IN_MEMORY rb_define_const(bdb_mDb, "LOG_IN_MEMORY", INT2FIX(DB_LOG_IN_MEMORY)); #endif #if HAVE_CONST_DB_LOG_AUTOREMOVE rb_define_const(bdb_mDb, "LOG_AUTOREMOVE", INT2FIX(DB_LOG_AUTOREMOVE)); #endif #if HAVE_CONST_DB_LOG_AUTO_REMOVE rb_define_const(bdb_mDb, "LOG_AUTO_REMOVE", INT2FIX(DB_LOG_AUTO_REMOVE)); #endif #if HAVE_CONST_DB_GET_BOTH_RANGE rb_define_const(bdb_mDb, "GET_BOTH_RANGE", INT2FIX(DB_GET_BOTH_RANGE)); #endif #if HAVE_CONST_DB_INIT_REP rb_define_const(bdb_mDb, "INIT_REP", INT2FIX(DB_INIT_REP)); #endif #if HAVE_CONST_DB_REP_NOBUFFER rb_define_const(bdb_mDb, "REP_NOBUFFER", INT2FIX(DB_REP_NOBUFFER)); #endif #if HAVE_CONST_DB_MUTEX_PROCESS_ONLY rb_define_const(bdb_mDb, "MUTEX_PROCESS_ONLY", INT2FIX(DB_MUTEX_PROCESS_ONLY)); #endif #if HAVE_CONST_DB_EVENT_PANIC rb_define_const(bdb_mDb, "EVENT_PANIC", INT2FIX(DB_EVENT_PANIC)); #endif #if HAVE_CONST_DB_EVENT_REP_STARTUPDONE rb_define_const(bdb_mDb, "EVENT_REP_STARTUPDONE", INT2FIX(DB_EVENT_REP_STARTUPDONE)); #endif #if HAVE_CONST_DB_EVENT_REP_CLIENT rb_define_const(bdb_mDb, "EVENT_REP_CLIENT", INT2FIX(DB_EVENT_REP_CLIENT)); #endif #if HAVE_CONST_DB_EVENT_REP_ELECTED rb_define_const(bdb_mDb, "EVENT_REP_ELECTED", INT2FIX(DB_EVENT_REP_ELECTED)); #endif #if HAVE_CONST_DB_EVENT_REP_MASTER rb_define_const(bdb_mDb, "EVENT_REP_MASTER", INT2FIX(DB_EVENT_REP_MASTER)); #endif #if HAVE_CONST_DB_EVENT_REP_NEWMASTER rb_define_const(bdb_mDb, "EVENT_REP_NEWMASTER", INT2FIX(DB_EVENT_REP_NEWMASTER)); #endif #if HAVE_CONST_DB_EVENT_REP_PERM_FAILED rb_define_const(bdb_mDb, "EVENT_REP_PERM_FAILED", INT2FIX(DB_EVENT_REP_PERM_FAILED)); #endif #if HAVE_CONST_DB_EVENT_WRITE_FAILED rb_define_const(bdb_mDb, "EVENT_WRITE_FAILED", INT2FIX(DB_EVENT_WRITE_FAILED)); #endif #if HAVE_CONST_DB_REP_CONF_BULK rb_define_const(bdb_mDb, "REP_CONF_BULK", INT2FIX(DB_REP_CONF_BULK)); #endif #if HAVE_CONST_DB_REP_CONF_DELAYCLIENT rb_define_const(bdb_mDb, "REP_CONF_DELAYCLIENT", INT2FIX(DB_REP_CONF_DELAYCLIENT)); #endif #if HAVE_CONST_DB_REP_CONF_NOAUTOINIT rb_define_const(bdb_mDb, "REP_CONF_NOAUTOINIT", INT2FIX(DB_REP_CONF_NOAUTOINIT)); #endif #if HAVE_CONST_DB_REP_CONF_NOWAIT rb_define_const(bdb_mDb, "REP_CONF_NOWAIT", INT2FIX(DB_REP_CONF_NOWAIT)); #endif #if HAVE_CONST_DB_REP_ACK_TIMEOUT rb_define_const(bdb_mDb, "REP_ACK_TIMEOUT", INT2FIX(DB_REP_ACK_TIMEOUT)); #endif #if HAVE_CONST_DB_REP_ANYWHERE rb_define_const(bdb_mDb, "REP_ANYWHERE", INT2FIX(DB_REP_ANYWHERE)); #endif #if HAVE_CONST_DB_REP_BULKOVF rb_define_const(bdb_mDb, "REP_BULKOVF", INT2FIX(DB_REP_BULKOVF)); #endif #if HAVE_CONST_DB_REP_DEFAULT_PRIORITY rb_define_const(bdb_mDb, "REP_DEFAULT_PRIORITY", INT2FIX(DB_REP_DEFAULT_PRIORITY)); #endif #if HAVE_CONST_DB_REP_EGENCHG rb_define_const(bdb_mDb, "REP_EGENCHG", INT2FIX(DB_REP_EGENCHG)); #endif #if HAVE_CONST_DB_REPFLAGS_MASK rb_define_const(bdb_mDb, "REPFLAGS_MASK", INT2FIX(DB_REPFLAGS_MASK)); #endif #if HAVE_CONST_DB_REP_FULL_ELECTION_TIMEOUT rb_define_const(bdb_mDb, "REP_FULL_ELECTION_TIMEOUT", INT2FIX(DB_REP_FULL_ELECTION_TIMEOUT)); #endif #if HAVE_CONST_DB_REP_HANDLE_DEAD rb_define_const(bdb_mDb, "REP_HANDLE_DEAD", INT2FIX(DB_REP_HANDLE_DEAD)); #endif #if HAVE_CONST_DB_REP_LEASE_EXPIRED rb_define_const(bdb_mDb, "REP_LEASE_EXPIRED", INT2FIX(DB_REP_LEASE_EXPIRED)); #endif #if HAVE_CONST_DB_REP_LEASE_TIMEOUT rb_define_const(bdb_mDb, "REP_LEASE_TIMEOUT", INT2FIX(DB_REP_LEASE_TIMEOUT)); #endif #if HAVE_CONST_DB_REP_LOCKOUT rb_define_const(bdb_mDb, "REP_LOCKOUT", INT2FIX(DB_REP_LOCKOUT)); #endif #if HAVE_CONST_DB_REP_LOGREADY rb_define_const(bdb_mDb, "REP_LOGREADY", INT2FIX(DB_REP_LOGREADY)); #endif #if HAVE_CONST_DB_REPMGR_CONNECTED rb_define_const(bdb_mDb, "REPMGR_CONNECTED", INT2FIX(DB_REPMGR_CONNECTED)); #endif #if HAVE_CONST_DB_REPMGR_DISCONNECTED rb_define_const(bdb_mDb, "REPMGR_DISCONNECTED", INT2FIX(DB_REPMGR_DISCONNECTED)); #endif #if HAVE_CONST_DB_REPMGR_PEER rb_define_const(bdb_mDb, "REPMGR_PEER", INT2FIX(DB_REPMGR_PEER)); #endif #if HAVE_CONST_DB_REP_PAGEDONE rb_define_const(bdb_mDb, "REP_PAGEDONE", INT2FIX(DB_REP_PAGEDONE)); #endif #if HAVE_CONST_DB_REP_REREQUEST rb_define_const(bdb_mDb, "REP_REREQUEST", INT2FIX(DB_REP_REREQUEST)); #endif #if HAVE_CONST_DB_REPMGR_ACKS_ALL rb_define_const(bdb_mDb, "REPMGR_ACKS_ALL", INT2FIX(DB_REPMGR_ACKS_ALL)); #endif #if HAVE_CONST_DB_REPMGR_ACKS_ALL_PEERS rb_define_const(bdb_mDb, "REPMGR_ACKS_ALL_PEERS", INT2FIX(DB_REPMGR_ACKS_ALL_PEERS)); #endif #if HAVE_CONST_DB_REPMGR_ACKS_NONE rb_define_const(bdb_mDb, "REPMGR_ACKS_NONE", INT2FIX(DB_REPMGR_ACKS_NONE)); #endif #if HAVE_CONST_DB_REPMGR_ACKS_ONE rb_define_const(bdb_mDb, "REPMGR_ACKS_ONE", INT2FIX(DB_REPMGR_ACKS_ONE)); #endif #if HAVE_CONST_DB_REPMGR_ACKS_ONE_PEER rb_define_const(bdb_mDb, "REPMGR_ACKS_ONE_PEER", INT2FIX(DB_REPMGR_ACKS_ONE_PEER)); #endif #if HAVE_CONST_DB_REPMGR_ACKS_QUORUM rb_define_const(bdb_mDb, "REPMGR_ACKS_QUORUM", INT2FIX(DB_REPMGR_ACKS_QUORUM)); #endif #if HAVE_CONST_DB_REP_ELECTION rb_define_const(bdb_mDb, "REP_ELECTION", INT2FIX(DB_REP_ELECTION)); #endif #if HAVE_CONST_DB_REP_FULL_ELECTION rb_define_const(bdb_mDb, "REP_FULL_ELECTION", INT2FIX(DB_REP_FULL_ELECTION)); #endif #if HAVE_CONST_DB_REP_ELECTION_TIMEOUT rb_define_const(bdb_mDb, "REP_ELECTION_TIMEOUT", INT2FIX(DB_REP_ELECTION_TIMEOUT)); #endif #if HAVE_CONST_DB_REP_ELECTION_RETRY rb_define_const(bdb_mDb, "REP_ELECTION_RETRY", INT2FIX(DB_REP_ELECTION_RETRY)); #endif #if HAVE_CONST_DB_REP_CONNECTION_RETRY rb_define_const(bdb_mDb, "REP_CONNECTION_RETRY", INT2FIX(DB_REP_CONNECTION_RETRY)); #endif #if HAVE_CONST_DB_REP_CHECKPOINT_DELAY rb_define_const(bdb_mDb, "REP_CHECKPOINT_DELAY", INT2FIX(DB_REP_CHECKPOINT_DELAY)); #endif #if HAVE_CONST_DB_IGNORE_LEASE rb_define_const(bdb_mDb, "IGNORE_LEASE", INT2FIX(DB_IGNORE_LEASE)); #endif #if HAVE_CONST_DB_PRIORITY_VERY_LOW rb_define_const(bdb_mDb, "PRIORITY_VERY_LOW", INT2FIX(DB_PRIORITY_VERY_LOW)); #endif #if HAVE_CONST_DB_PRIORITY_LOW rb_define_const(bdb_mDb, "PRIORITY_LOW", INT2FIX(DB_PRIORITY_LOW)); #endif #if HAVE_CONST_DB_PRIORITY_DEFAULT rb_define_const(bdb_mDb, "PRIORITY_DEFAULT", INT2FIX(DB_PRIORITY_DEFAULT)); #endif #if HAVE_CONST_DB_PRIORITY_HIGH rb_define_const(bdb_mDb, "PRIORITY_HIGH", INT2FIX(DB_PRIORITY_HIGH)); #endif #if HAVE_CONST_DB_PRIORITY_VERY_HIGH rb_define_const(bdb_mDb, "PRIORITY_VERY_HIGH", INT2FIX(DB_PRIORITY_VERY_HIGH)); #endif #if HAVE_CONST_DB_LOG_DIRECT rb_define_const(bdb_mDb, "LOG_DIRECT", INT2FIX(DB_LOG_DIRECT)); #endif #if HAVE_CONST_DB_LOG_DSYNC rb_define_const(bdb_mDb, "LOG_DSYNC", INT2FIX(DB_LOG_DSYNC)); #endif #if HAVE_CONST_DB_LOG_ZERO rb_define_const(bdb_mDb, "LOG_ZERO", INT2FIX(DB_LOG_ZERO)); #endif bdb_init_env(); bdb_init_common(); bdb_init_recnum(); bdb_init_transaction(); bdb_init_cursor(); bdb_init_lock(); bdb_init_log(); bdb_init_delegator(); bdb_init_sequence(); bdb_errstr = rb_tainted_str_new(0, 0); rb_global_variable(&bdb_errstr); } ruby-bdb-0.6.6/src/bdb.h000066400000000000000000000352101154714021300147170ustar00rootroot00000000000000#include #include #include #ifdef HAVE_RUBY_IO_H #include #else #include #include #endif #include "bdb_features.h" #ifndef StringValue #define StringValue(x) do { \ if (TYPE(x) != T_STRING) x = rb_str_to_str(x); \ } while (0) #endif #ifndef StringValuePtr #define StringValuePtr(x) STR2CSTR(x) #endif #ifndef SafeStringValue #define SafeStringValue(x) Check_SafeStr(x) #endif #ifndef RSTRING_PTR # define RSTRING_PTR(x_) RSTRING(x_)->ptr # define RSTRING_LEN(x_) RSTRING(x_)->len #endif #ifndef RARRAY_PTR # define RARRAY_PTR(x_) RARRAY(x_)->ptr # define RARRAY_LEN(x_) RARRAY(x_)->len #endif #ifndef RCLASS_SUPER #define RCLASS_SUPER(c) (RCLASS(c)->super) #endif #ifdef close #undef close #endif #ifdef stat #undef stat #endif #ifdef rename #undef rename #endif #if defined(__cplusplus) extern "C" { #endif #if (DB_VERSION_MAJOR == 2) || (DB_VERSION_MAJOR == 3 && DB_VERSION_MINOR < 2) #define BDB_OLD_FUNCTION_PROTO 1 #else #define BDB_OLD_FUNCTION_PROTO 0 #endif #if ! HAVE_CONST_DB_AUTO_COMMIT #define DB_AUTO_COMMIT 0 #endif #if ! HAVE_CONST_DB_NEXT_DUP #define DB_NEXT_DUP 0 #endif #define BDB_VERSION (10000*DB_VERSION_MAJOR+100*DB_VERSION_MINOR+DB_VERSION_PATCH) #define BDB_MARSHAL (1<<0) #define BDB_NOT_OPEN (1<<1) #define BDB_RE_SOURCE (1<<2) #define BDB_BT_COMPARE (1<<3) #define BDB_BT_PREFIX (1<<4) #define BDB_DUP_COMPARE (1<<5) #define BDB_H_HASH (1<<6) #define BDB_APPEND_RECNO (1<<7) #define BDB_H_COMPARE (1<<13) #define BDB_FEEDBACK (1<<8) #define BDB_AUTO_COMMIT (1<<9) #define BDB_NO_THREAD (1<<10) #define BDB_INIT_LOCK (1<<11) #define BDB_NIL (1<<12) #define BDB_TXN_COMMIT (1<<0) #define BDB_APP_DISPATCH (1<<0) #define BDB_REP_TRANSPORT (1<<1) #define BDB_ENV_ENCRYPT (1<<2) #define BDB_ENV_NOT_OPEN (1<<3) #if HAVE_ST_DB_ASSOCIATE #define BDB_ERROR_PRIVATE 44444 #endif #define HAVE_DB_STAT_4_TXN 0 #if HAVE_DB_STAT_4 #if HAVE_ST_DB_OPEN #if HAVE_DB_OPEN_7 #undef HAVE_DB_STAT_4_TXN #define HAVE_DB_STAT_4_TXN 1 #endif #endif #endif #define BDB_INIT_TRANSACTION (DB_INIT_LOCK | DB_INIT_MPOOL | DB_INIT_TXN | DB_INIT_LOG) #define BDB_INIT_LOMP (DB_INIT_LOCK | DB_INIT_MPOOL | DB_INIT_LOG) #define BDB_NEED_CURRENT (BDB_MARSHAL | BDB_BT_COMPARE | BDB_BT_PREFIX | BDB_DUP_COMPARE | BDB_H_HASH | BDB_H_COMPARE | BDB_APPEND_RECNO | BDB_FEEDBACK) #if HAVE_ST_DB_ENV_SET_FEEDBACK || HAVE_ST_DB_ENV_REP_SET_TRANSPORT || \ HAVE_ST_DB_ENV_SET_REP_TRANSPORT || HAVE_ST_DB_ENV_SET_APP_DISPATCH #define BDB_NEED_ENV_CURRENT (BDB_FEEDBACK | BDB_APP_DISPATCH | BDB_REP_TRANSPORT) #else #define BDB_NEED_ENV_CURRENT 0 #endif #if ! HAVE_CONST_DB_RMW #define DB_RMW 0 #endif extern VALUE bdb_cEnv; extern VALUE bdb_eFatal; extern VALUE bdb_eLock, bdb_eLockDead, bdb_eLockHeld, bdb_eLockGranted; extern VALUE bdb_mDb; extern VALUE bdb_cCommon, bdb_cBtree, bdb_cRecnum, bdb_cHash, bdb_cRecno, bdb_cUnknown; extern VALUE bdb_cDelegate; #if HAVE_TYPE_DB_KEY_RANGE extern VALUE bdb_sKeyrange; #endif #if HAVE_CONST_DB_QUEUE extern VALUE bdb_cQueue; #else #define DB_QUEUE DB_RECNO #endif extern VALUE bdb_cTxn, bdb_cTxnCatch; extern VALUE bdb_cCursor; extern VALUE bdb_cLock, bdb_cLockid; extern VALUE bdb_cLsn; extern VALUE bdb_mMarshal; extern ID bdb_id_dump, bdb_id_load; extern ID bdb_id_current_db, bdb_id_current_env; extern VALUE bdb_deleg_to_orig _((VALUE)); struct ary_st { int len, total, mark; VALUE *ptr; }; typedef struct { int options; VALUE marshal; struct ary_st db_ary; VALUE home; DB_ENV *envp; #if HAVE_DB_LOG_REGISTER_4 || HAVE_ST_DB_ENV_LG_INFO u_int32_t fidp; #endif #if HAVE_ST_DB_ENV_REP_SET_TRANSPORT || HAVE_ST_DB_ENV_SET_REP_TRANSPORT VALUE rep_transport; #endif #if HAVE_ST_DB_ENV_SET_FEEDBACK VALUE feedback; #endif #if HAVE_ST_DB_ENV_SET_APP_DISPATCH VALUE app_dispatch; #endif #if HAVE_ST_DB_ENV_SET_MSGCALL VALUE msgcall; #endif #if HAVE_ST_DB_ENV_SET_THREAD_ID VALUE thread_id; #endif #if HAVE_ST_DB_ENV_SET_THREAD_ID_STRING VALUE thread_id_string; #endif #if HAVE_ST_DB_ENV_SET_ISALIVE VALUE isalive; #endif #if HAVE_ST_DB_ENV_SET_EVENT_NOTIFY VALUE event_notify; #endif } bdb_ENV; #if HAVE_DBXML_INTERFACE struct txn_rslbl { DB_TXN *txn; void *txn_cxx; VALUE man; void (*txn_cxx_free) (void **); int (*txn_cxx_abort) (void *); int (*txn_cxx_commit) (void *, u_int32_t ); int (*txn_cxx_discard) (void *, u_int32_t ); }; extern VALUE bdb_env_s_rslbl _((int, VALUE *,VALUE, DB_ENV *)); #endif typedef struct { int status, options; VALUE marshal, mutex; struct ary_st db_ary; struct ary_st db_assoc; VALUE env; DB_TXN *txnid; DB_TXN *parent; #if HAVE_DBXML_INTERFACE void *txn_cxx; VALUE man; void (*txn_cxx_free) (void **); int (*txn_cxx_abort) (void *); int (*txn_cxx_commit) (void *, u_int32_t ); int (*txn_cxx_discard) (void *, u_int32_t ); #endif } bdb_TXN; #define FILTER_KEY 0 #define FILTER_VALUE 1 #define FILTER_FREE 2 typedef struct { int options; VALUE marshal; DBTYPE type; VALUE env, orig, secondary, txn; VALUE filename, database; VALUE bt_compare, bt_prefix, h_hash; #if HAVE_CONST_DB_DUPSORT VALUE dup_compare; #endif #if HAVE_ST_DB_SET_H_COMPARE VALUE h_compare; #endif VALUE filter[4]; VALUE ori_val; DB *dbp; long len; u_int32_t flags; u_int32_t partial; u_int32_t dlen; u_int32_t doff; int array_base; #if HAVE_TYPE_DB_INFO DB_INFO *dbinfo; #else int re_len; char re_pad; VALUE feedback; #endif #if HAVE_ST_DB_SET_APPEND_RECNO VALUE append_recno; #endif #if HAVE_ST_DB_SET_CACHE_PRIORITY int priority; #endif } bdb_DB; #if HAVE_TYPE_DB_SEQUENCE typedef struct { DB_SEQUENCE *seqp; VALUE db, txn, orig; DB_TXN *txnid; } bdb_SEQ; #define GetSEQ(obj_,seq_) do { \ Data_Get_Struct(obj_, bdb_SEQ, seq_); \ if (seq_->seqp == 0) { \ rb_raise(bdb_eFatal, "closed sequence"); \ } \ } while (0) #endif typedef struct { DBC *dbc; VALUE db; } bdb_DBC; typedef struct { unsigned int lock; VALUE env, self; } bdb_LOCKID; typedef struct { #if HAVE_TYPE_DB_INFO DB_LOCK lock; #else DB_LOCK *lock; #endif VALUE env; } bdb_LOCK; typedef struct { bdb_DB *dbst; DBT *key; VALUE value; } bdb_VALUE; struct deleg_class { int type; VALUE db; VALUE obj; VALUE key; }; struct dblsnst { VALUE env, self; DB_LSN *lsn; #if HAVE_TYPE_DB_LOGC DB_LOGC *cursor; int flags; #endif }; #define RECNUM_TYPE(dbst) ((dbst->type == DB_RECNO || dbst->type == DB_QUEUE) || (dbst->type == DB_BTREE && (dbst->flags & DB_RECNUM))) #define GetCursorDB(obj, dbcst, dbst) \ { \ Data_Get_Struct(obj, bdb_DBC, dbcst); \ if (dbcst->db == 0) \ rb_raise(bdb_eFatal, "closed cursor"); \ GetDB(dbcst->db, dbst); \ } #define GetEnvDBErr(obj, envst, id_c, eErr) \ { \ Data_Get_Struct(obj, bdb_ENV, envst); \ if (envst->envp == 0) \ rb_raise(eErr, "closed environment"); \ if (envst->options & BDB_NEED_ENV_CURRENT) { \ VALUE th = rb_thread_current(); \ \ if (!RTEST(th) || !RBASIC(th)->flags) { \ rb_raise(eErr, "invalid thread object"); \ } \ rb_thread_local_aset(th, id_c, obj); \ } \ } #define GetEnvDB(obj, envst) GetEnvDBErr(obj, envst, bdb_id_current_env, bdb_eFatal) #define GetDB(obj, dbst) \ { \ Data_Get_Struct(obj, bdb_DB, dbst); \ if (dbst->dbp == 0) { \ rb_raise(bdb_eFatal, "closed DB"); \ } \ if (dbst->options & BDB_NEED_CURRENT) { \ VALUE th = rb_thread_current(); \ \ if (!RTEST(th) || !RBASIC(th)->flags) { \ rb_raise(bdb_eFatal, "invalid thread object"); \ } \ rb_thread_local_aset(th, bdb_id_current_db, obj); \ } \ } #if BDB_VERSION < 20600 #define HAVE_CURSOR_C_GET_KEY_MALLOC 1 #define INIT_RECNO(dbst, key, recno) \ { \ recno = 1; \ if (RECNUM_TYPE(dbst)) { \ key.data = &recno; \ key.size = sizeof(db_recno_t); \ key.flags |= DB_DBT_MALLOC; \ } \ else { \ key.flags |= DB_DBT_MALLOC; \ } \ } #define FREE_KEY(dbst, key) \ { \ if (((key).flags & DB_DBT_MALLOC) && !RECNUM_TYPE(dbst)) { \ free((key).data); \ } \ } #else #define HAVE_CURSOR_C_GET_KEY_MALLOC 0 #define INIT_RECNO(dbst, key, recno) \ { \ recno = 1; \ if (RECNUM_TYPE(dbst)) { \ key.data = &recno; \ key.size = sizeof(db_recno_t); \ } \ else { \ key.flags |= DB_DBT_MALLOC; \ } \ } #define FREE_KEY(dbst, key) \ { \ if ((key).flags & DB_DBT_MALLOC) { \ free((key).data); \ } \ } #endif #define INIT_TXN(txnid, obj, dbst) { \ txnid = NULL; \ GetDB(obj, dbst); \ if (RTEST(dbst->txn)) { \ bdb_TXN *txnst; \ Data_Get_Struct(dbst->txn, bdb_TXN, txnst); \ if (txnst->txnid == 0) \ rb_warning("using a db handle associated with a closed transaction"); \ txnid = txnst->txnid; \ } \ } #define SET_PARTIAL(db, data) \ (data).flags |= db->partial; \ (data).dlen = db->dlen; \ (data).doff = db->doff; #define GetTxnDBErr(obj, txnst, error) \ { \ Data_Get_Struct(obj, bdb_TXN, txnst); \ if (txnst->txnid == 0) \ rb_raise(error, "closed transaction"); \ } #define GetTxnDB(obj, txnst) GetTxnDBErr(obj, txnst, bdb_eFatal) #define BDB_VALID(obj, type) (RTEST(obj) && BUILTIN_TYPE(obj) == (type)) #if HAVE_TYPE_DB_INFO #define TEST_INIT_LOCK(dbst) (((dbst)->options & BDB_INIT_LOCK)?DB_RMW:0) #else #define TEST_INIT_LOCK(dbst) (0) #endif #define BDB_ST_KEY 1 #define BDB_ST_VALUE 2 #define BDB_ST_KV 3 #define BDB_ST_DELETE 4 #define BDB_ST_DUPU (5 | BDB_ST_DUP) #define BDB_ST_DUPKV (6 | BDB_ST_DUP) #define BDB_ST_DUPVAL (7 | BDB_ST_DUP) #define BDB_ST_REJECT 8 #define BDB_ST_DUP 32 #define BDB_ST_ONE 64 #define BDB_ST_SELECT 128 #define BDB_ST_PREFIX 256 extern VALUE bdb_errstr; extern int bdb_errcall; extern int bdb_test_error _((int)); #if HAVE_CONST_DB_INCOMPLETE #define bdb_cache_error(commande_, correction_, result_) do { \ result_ = commande_; \ \ switch (result_) { \ case 0: \ case DB_NOTFOUND: \ case DB_KEYEMPTY: \ case DB_KEYEXIST: \ break; \ case DB_INCOMPLETE: \ result_ = 0; \ break; \ default: \ correction_; \ bdb_test_error(result_); \ } \ } while (0); #else #define bdb_cache_error(commande_, correction_, result_) do { \ result_ = commande_; \ \ switch (result_) { \ case 0: \ case DB_NOTFOUND: \ case DB_KEYEMPTY: \ case DB_KEYEXIST: \ break; \ default: \ correction_; \ bdb_test_error(result_); \ } \ } while (0); #endif extern VALUE bdb_obj_init _((int, VALUE *, VALUE)); extern ID bdb_id_call; #if ! HAVE_DB_STRERROR extern char *db_strerror _((int)); #endif extern VALUE bdb_local_aref _(()); extern VALUE bdb_test_recno _((VALUE, DBT *, db_recno_t *, VALUE)); extern VALUE bdb_test_dump _((VALUE, DBT *, VALUE, int)); extern VALUE bdb_test_ret _((VALUE, VALUE, VALUE, int)); extern VALUE bdb_test_load_key _((VALUE, DBT *)); extern VALUE bdb_assoc _((VALUE, DBT *, DBT *)); extern VALUE bdb_assoc3 _((VALUE, DBT *, DBT *, DBT *)); extern VALUE bdb_assoc_dyna _((VALUE, DBT *, DBT *)); extern VALUE bdb_clear _((int, VALUE *, VALUE)); extern VALUE bdb_del _((VALUE, VALUE)); extern void bdb_deleg_mark _((struct deleg_class *)); extern VALUE bdb_each_eulav _((int, VALUE *, VALUE)); extern VALUE bdb_each_key _((int, VALUE *, VALUE)); extern VALUE bdb_each_value _((int, VALUE *, VALUE)); extern VALUE bdb_each_valuec _((int, VALUE *, VALUE, int, VALUE)); extern VALUE bdb_each_kvc _((int, VALUE *, VALUE, int, VALUE, int)); #if HAVE_DB_ENV_ERRCALL_3 extern void bdb_env_errcall _((const DB_ENV *, const char *, const char *)); #else extern void bdb_env_errcall _((const char *, char *)); #endif extern VALUE bdb_env_init _((int, VALUE *, VALUE)); extern VALUE bdb_protect_close _((VALUE)); extern VALUE bdb_env_open_db _((int, VALUE *, VALUE)); extern VALUE bdb_get _((int, VALUE *, VALUE)); extern VALUE bdb_env_p _((VALUE)); extern VALUE bdb_has_value _((VALUE, VALUE)); extern VALUE bdb_index _((VALUE, VALUE)); extern VALUE bdb_internal_value _((VALUE, VALUE, VALUE, int)); extern VALUE bdb_put _((int, VALUE *, VALUE)); extern VALUE bdb_test_load _((VALUE, DBT *, int)); extern VALUE bdb_to_type _((VALUE, VALUE, VALUE)); extern VALUE bdb_tree_stat _((int, VALUE *, VALUE)); extern VALUE bdb_init _((int, VALUE *, VALUE)); extern void bdb_init_env _((void)); extern void bdb_init_common _((void)); extern void bdb_init_recnum _((void)); extern void bdb_init_transaction _((void)); extern void bdb_init_cursor _((void)); extern void bdb_init_lock _((void)); extern void bdb_init_log _((void)); extern void bdb_init_delegator _((void)); extern void bdb_init_sequence _((void)); extern void bdb_clean_env _((VALUE, VALUE)); extern VALUE bdb_makelsn _((VALUE)); extern VALUE bdb_env_rslbl_begin _((VALUE, int, VALUE *, VALUE)); extern VALUE bdb_return_err _((void)); extern void bdb_ary_push _((struct ary_st *, VALUE)); extern void bdb_ary_unshift _((struct ary_st *, VALUE)); extern VALUE bdb_ary_delete _((struct ary_st *, VALUE)); extern void bdb_ary_mark _((struct ary_st *)); extern VALUE bdb_respond_to _((VALUE, ID)); #if ! HAVE_ST_DBC_C_CLOSE && HAVE_ST_DBC_CLOSE #define c_close close #undef HAVE_ST_DBC_C_CLOSE #define HAVE_ST_DBC_C_CLOSE 1 #endif #if ! HAVE_ST_DBC_C_COUNT && HAVE_ST_DBC_COUNT #define c_count count #undef HAVE_ST_DBC_C_COUNT #define HAVE_ST_DBC_C_COUNT 1 #endif #if ! HAVE_ST_DBC_C_DEL && HAVE_ST_DBC_DEL #define c_del del #undef HAVE_ST_DBC_C_DEL #define HAVE_ST_DBC_C_DEL 1 #endif #if ! HAVE_ST_DBC_C_DUP && HAVE_ST_DBC_DUP #define c_dup dup #undef HAVE_ST_DBC_C_DUP #define HAVE_ST_DBC_C_DUP 1 #endif #if ! HAVE_ST_DBC_C_GET && HAVE_ST_DBC_GET #define c_get get #undef HAVE_ST_DBC_C_GET #define HAVE_ST_DBC_C_GET 1 #endif #if ! HAVE_ST_DBC_C_PGET && HAVE_ST_DBC_PGET #define c_pget pget #undef HAVE_ST_DBC_C_PGET #define HAVE_ST_DBC_C_PGET 1 #endif #if ! HAVE_ST_DBC_C_PUT && HAVE_ST_DBC_PUT #define c_put put #undef HAVE_ST_DBC_C_PUT #define HAVE_ST_DBC_C_PUT 1 #endif #if defined(__cplusplus) } #endif ruby-bdb-0.6.6/src/common.c000066400000000000000000003546111154714021300154640ustar00rootroot00000000000000#include "bdb.h" #if ! HAVE_CONST_DB_GET_BOTH #define DB_GET_BOTH 9 #endif static ID id_bt_compare, id_bt_prefix, id_h_hash; #if HAVE_CONST_DB_DUPSORT static ID id_dup_compare; #endif #if HAVE_ST_DB_SET_APPEND_RECNO static ID id_append_recno; #endif #if HAVE_ST_DB_SET_H_COMPARE static ID id_h_compare; #endif #if HAVE_ST_DB_SET_FEEDBACK static ID id_feedback; #endif static void bdb_mark _((bdb_DB *)); #define GetIdDb(obj_, dbst_) do { \ VALUE th = rb_thread_current(); \ \ if (!RTEST(th) || !RBASIC(th)->flags) { \ rb_raise(bdb_eFatal, "invalid thread object"); \ } \ (obj_) = rb_thread_local_aref(th, bdb_id_current_db); \ if (TYPE(obj_) != T_DATA || \ RDATA(obj_)->dmark != (RUBY_DATA_FUNC)bdb_mark) { \ rb_raise(bdb_eFatal, "BUG : current_db not set"); \ } \ Data_Get_Struct(obj_, bdb_DB, dbst_); \ } while (0) #if HAVE_ST_DB_APP_PRIVATE #define GetIdDbSec(obj_, dbst_, dbbd_) do { \ (obj_) = (VALUE)dbbd_->app_private; \ if (!obj) { \ GetIdDb(obj_, dbst_); \ } \ else { \ Data_Get_Struct(obj_, bdb_DB, dbst_); \ } \ } while (0) #else #define GetIdDbSec(obj_, dbst_, dbbd_) do { \ GetIdDb(obj_, dbst_); \ if (dbbd_ != NULL && dbst_->dbp != dbbd_) { \ if (TYPE(dbst_->secondary) == T_ARRAY) { \ int i_; \ VALUE tmp_; \ \ for (i_ = 0; i_ < RARRAY_LEN(dbst_->secondary); i_++) { \ tmp_ = RARRAY_PTR(dbst_->secondary)[i_]; \ if (TYPE(tmp_) == T_ARRAY && RARRAY_LEN(tmp_) >= 1) { \ VALUE tmp_db = RARRAY_PTR(tmp_)[0]; \ if (TYPE(tmp_db) == T_DATA && \ RDATA(tmp_db)->dmark == (RUBY_DATA_FUNC)bdb_mark) { \ Data_Get_Struct(tmp_db, bdb_DB, dbst_); \ if (dbst_->dbp == dbbd_) { \ (obj_) = tmp_db; \ goto found; \ } \ } \ } \ } \ } \ rb_raise(bdb_eFatal, "Invalid reference"); \ found: \ Data_Get_Struct(obj_, bdb_DB, dbst_); \ } \ } while (0) #endif VALUE bdb_respond_to(VALUE obj, ID meth) { return rb_funcall(obj, rb_intern("respond_to?"), 2, ID2SYM(meth), Qtrue); } void bdb_ary_push(struct ary_st *db_ary, VALUE obj) { if (db_ary->mark) { rb_warning("db_ary in mark phase"); return; } if (db_ary->len == db_ary->total) { if (db_ary->total) { REALLOC_N(db_ary->ptr, VALUE, db_ary->total + 5); } else { db_ary->ptr = ALLOC_N(VALUE, 5); } db_ary->total += 5; } db_ary->ptr[db_ary->len] = obj; db_ary->len++; } void bdb_ary_unshift(struct ary_st *db_ary, VALUE obj) { if (db_ary->mark) { rb_warning("db_ary in mark phase"); return; } if (db_ary->len == db_ary->total) { if (db_ary->total) { REALLOC_N(db_ary->ptr, VALUE, db_ary->total + 5); } else { db_ary->ptr = ALLOC_N(VALUE, 5); } db_ary->total += 5; } if (db_ary->len) { MEMMOVE(db_ary->ptr + 1, db_ary->ptr, VALUE, db_ary->len); } db_ary->len++; db_ary->ptr[0] = obj; } VALUE bdb_ary_delete(struct ary_st *db_ary, VALUE val) { int i, pos; if (!db_ary->ptr || db_ary->mark) return Qfalse; for (pos = 0; pos < db_ary->len; pos++) { if (db_ary->ptr[pos] == val) { for (i = pos + 1; i < db_ary->len; i++, pos++) { db_ary->ptr[pos] = db_ary->ptr[i]; } db_ary->len = pos; return Qtrue; } } return Qfalse; } void bdb_ary_mark(struct ary_st *db_ary) { int i; for (i = 0; i < db_ary->len; i++) { rb_gc_mark(db_ary->ptr[i]); } } VALUE bdb_test_dump(VALUE obj, DBT *key, VALUE a, int type_kv) { bdb_DB *dbst; int is_nil = 0; VALUE tmp = a; Data_Get_Struct(obj, bdb_DB, dbst); if (dbst->filter[type_kv]) { if (FIXNUM_P(dbst->filter[type_kv])) { tmp = rb_funcall(obj, NUM2INT(dbst->filter[type_kv]), 1, a); } else { tmp = rb_funcall(dbst->filter[type_kv], bdb_id_call, 1, a); } } if (dbst->marshal) { if (rb_obj_is_kind_of(tmp, bdb_cDelegate)) { tmp = bdb_deleg_to_orig(tmp); } tmp = rb_funcall(dbst->marshal, bdb_id_dump, 1, tmp); if (TYPE(tmp) != T_STRING) { rb_raise(rb_eTypeError, "dump() must return String"); } } else { tmp = rb_obj_as_string(tmp); if ((dbst->options & BDB_NIL) && a == Qnil) { is_nil = 1; } } key->data = StringValuePtr(tmp); key->flags &= ~DB_DBT_MALLOC; key->size = RSTRING_LEN(tmp) + is_nil; return tmp; } VALUE bdb_test_ret(VALUE obj, VALUE tmp, VALUE a, int type_kv) { bdb_DB *dbst; Data_Get_Struct(obj, bdb_DB, dbst); if (dbst->marshal || a == Qnil) { return a; } else { if (dbst->filter[type_kv]) { return rb_obj_as_string(a); } else { return tmp; } } } VALUE bdb_test_recno(VALUE obj, DBT *key, db_recno_t *recno, VALUE a) { bdb_DB *dbst; Data_Get_Struct(obj, bdb_DB, dbst); if (RECNUM_TYPE(dbst)) { *recno = NUM2INT(a) + dbst->array_base; key->data = recno; key->size = sizeof(db_recno_t); return a; } else { return bdb_test_dump(obj, key, a, FILTER_KEY); } } VALUE bdb_test_load(VALUE obj, DBT *a, int type_kv) { VALUE res; int posi; bdb_DB *dbst; posi = type_kv & ~FILTER_FREE; Data_Get_Struct(obj, bdb_DB, dbst); if (dbst->marshal) { res = rb_str_new(a->data, a->size); if (dbst->filter[2 + posi]) { if (FIXNUM_P(dbst->filter[2 + posi])) { res = rb_funcall(obj, NUM2INT(dbst->filter[2 + posi]), 1, res); } else { res = rb_funcall(dbst->filter[2 + posi], bdb_id_call, 1, res); } } res = rb_funcall(dbst->marshal, bdb_id_load, 1, res); } else { #if HAVE_CONST_DB_QUEUE int i; if (dbst->type == DB_QUEUE) { for (i = a->size - 1; i >= 0; i--) { if (((char *)a->data)[i] != dbst->re_pad) break; } a->size = i + 1; } #endif if ((dbst->options & BDB_NIL) && a->size == 1 && ((char *)a->data)[0] == '\000') { res = Qnil; } else { if (a->size == 0 && !(dbst->options & BDB_NIL)) { res = Qnil; } else { res = rb_tainted_str_new(a->data, a->size); if (dbst->filter[2 + posi]) { if (FIXNUM_P(dbst->filter[2 + posi])) { res = rb_funcall(obj, NUM2INT(dbst->filter[2 + posi]), 1, res); } else { res = rb_funcall(dbst->filter[2 + posi], bdb_id_call, 1, res); } } } } } if ((a->flags & DB_DBT_MALLOC) && !(type_kv & FILTER_FREE)) { free(a->data); a->data = 0; a->flags &= ~DB_DBT_MALLOC; } return res; } static VALUE test_load_dyna1(VALUE obj, DBT *key, DBT *val) { bdb_DB *dbst; VALUE del, res, tmp; struct deleg_class *delegst; Data_Get_Struct(obj, bdb_DB, dbst); res = bdb_test_load(obj, val, FILTER_VALUE); if (dbst->marshal && !SPECIAL_CONST_P(res)) { del = Data_Make_Struct(bdb_cDelegate, struct deleg_class, bdb_deleg_mark, free, delegst); delegst->db = obj; if (RECNUM_TYPE(dbst)) { tmp = INT2NUM((*(db_recno_t *)key->data) - dbst->array_base); } else { tmp = rb_str_new(key->data, key->size); if (dbst->filter[2 + FILTER_VALUE]) { if (FIXNUM_P(dbst->filter[2 + FILTER_VALUE])) { tmp = rb_funcall(obj, NUM2INT(dbst->filter[2 + FILTER_VALUE]), 1, tmp); } else { tmp = rb_funcall(dbst->filter[2 + FILTER_VALUE], bdb_id_call, 1, tmp); } } tmp = rb_funcall(dbst->marshal, bdb_id_load, 1, tmp); } delegst->key = tmp; delegst->obj = res; res = del; } return res; } static VALUE test_load_dyna(VALUE obj, DBT *key, DBT *val) { VALUE res = test_load_dyna1(obj, key, val); if (key->flags & DB_DBT_MALLOC) { free(key->data); key->data = 0; key->flags &= ~DB_DBT_MALLOC; } return res; } #define INT_COMPAR 1 #define NUM_COMPAR 2 #define STR_COMPAR 3 #define COMPAR_INT 5 #define COMPAR_NUM 6 #define COMPAR_STR 7 static int compar_funcall(VALUE av, VALUE bv, int compar) { long ai, bi; double ad, bd; switch (compar) { case INT_COMPAR: ai = NUM2INT(rb_Integer(av)); bi = NUM2INT(rb_Integer(bv)); if (ai == bi) return 0; if (ai > bi) return 1; return -1; case NUM_COMPAR: ad = NUM2DBL(rb_Float(av)); bd = NUM2DBL(rb_Float(bv)); if (ad == bd) return 0; if (ad > bd) return 1; return -1; case STR_COMPAR: av = rb_obj_as_string(av); bv = rb_obj_as_string(bv); return strcmp(StringValuePtr(av), StringValuePtr(bv)); case COMPAR_INT: ai = NUM2INT(rb_Integer(av)); bi = NUM2INT(rb_Integer(bv)); if (bi == ai) return 0; if (bi > ai) return 1; return -1; case COMPAR_NUM: ad = NUM2DBL(rb_Float(av)); bd = NUM2DBL(rb_Float(bv)); if (bd == ad) return 0; if (bd > ad) return 1; return -1; case COMPAR_STR: av = rb_obj_as_string(av); bv = rb_obj_as_string(bv); return strcmp(StringValuePtr(bv), StringValuePtr(av)); default: rb_raise(bdb_eFatal, "Invalid comparison function"); } return 0; } static int #if BDB_OLD_FUNCTION_PROTO bdb_bt_compare(const DBT *a, const DBT *b) #else bdb_bt_compare(DB *dbbd, const DBT *a, const DBT *b) #endif { VALUE obj, av, bv, res; bdb_DB *dbst; #if BDB_OLD_FUNCTION_PROTO DB *dbbd = NULL; #endif GetIdDbSec(obj, dbst, dbbd); av = bdb_test_load(obj, (DBT *)a, FILTER_VALUE|FILTER_FREE); bv = bdb_test_load(obj, (DBT *)b, FILTER_VALUE|FILTER_FREE); if (dbst->bt_compare == 0) { res = rb_funcall(obj, id_bt_compare, 2, av, bv); } else { if (FIXNUM_P(dbst->bt_compare)) { return compar_funcall(av, bv, NUM2INT(dbst->bt_compare)); } res = rb_funcall(dbst->bt_compare, bdb_id_call, 2, av, bv); } return NUM2INT(res); } static size_t #if BDB_OLD_FUNCTION_PROTO bdb_bt_prefix(const DBT *a, const DBT *b) #else bdb_bt_prefix(DB *dbbd, const DBT *a, const DBT *b) #endif { VALUE obj, av, bv, res; bdb_DB *dbst; #if BDB_OLD_FUNCTION_PROTO DB *dbbd = NULL; #endif GetIdDbSec(obj, dbst, dbbd); av = bdb_test_load(obj, (DBT *)a, FILTER_VALUE|FILTER_FREE); bv = bdb_test_load(obj, (DBT *)b, FILTER_VALUE|FILTER_FREE); if (dbst->bt_prefix == 0) res = rb_funcall(obj, id_bt_prefix, 2, av, bv); else res = rb_funcall(dbst->bt_prefix, bdb_id_call, 2, av, bv); return NUM2INT(res); } #if HAVE_CONST_DB_DUPSORT static int #if BDB_OLD_FUNCTION_PROTO bdb_dup_compare(const DBT *a, const DBT *b) #else bdb_dup_compare(DB *dbbd, const DBT *a, const DBT *b) #endif { VALUE obj, av, bv, res; bdb_DB *dbst; #if BDB_OLD_FUNCTION_PROTO DB *dbbd = NULL; #endif GetIdDbSec(obj, dbst, dbbd); av = bdb_test_load(obj, (DBT *)a, FILTER_VALUE|FILTER_FREE); bv = bdb_test_load(obj, (DBT *)b, FILTER_VALUE|FILTER_FREE); if (dbst->dup_compare == 0) { res = rb_funcall(obj, id_dup_compare, 2, av, bv); } else { if (FIXNUM_P(dbst->dup_compare)) { return compar_funcall(av, bv, NUM2INT(dbst->dup_compare)); } res = rb_funcall(dbst->dup_compare, bdb_id_call, 2, av, bv); } return NUM2INT(res); } #endif static u_int32_t #if BDB_OLD_FUNCTION_PROTO bdb_h_hash(const void *bytes, u_int32_t length) #else bdb_h_hash(DB *dbbd, const void *bytes, u_int32_t length) #endif { VALUE obj, st, res; bdb_DB *dbst; #if BDB_OLD_FUNCTION_PROTO DB *dbbd = NULL; #endif GetIdDbSec(obj, dbst, dbbd); st = rb_tainted_str_new((char *)bytes, length); if (dbst->h_hash == 0) res = rb_funcall(obj, id_h_hash, 1, st); else res = rb_funcall(dbst->h_hash, bdb_id_call, 1, st); return NUM2UINT(res); } #if HAVE_ST_DB_SET_H_COMPARE static int bdb_h_compare(DB *dbbd, const DBT *a, const DBT *b) { VALUE obj, av, bv, res; bdb_DB *dbst; GetIdDbSec(obj, dbst, dbbd); av = bdb_test_load(obj, (DBT *)a, FILTER_VALUE|FILTER_FREE); bv = bdb_test_load(obj, (DBT *)b, FILTER_VALUE|FILTER_FREE); if (dbst->h_compare == 0) { res = rb_funcall(obj, id_h_compare, 2, av, bv); } else { if (FIXNUM_P(dbst->h_compare)) { return compar_funcall(av, bv, NUM2INT(dbst->h_compare)); } res = rb_funcall(dbst->h_compare, bdb_id_call, 2, av, bv); } return NUM2INT(res); } #endif #if HAVE_ST_DB_SET_APPEND_RECNO static int bdb_append_recno(DB *dbp, DBT *data, db_recno_t recno) { VALUE res, obj, av, rec; bdb_DB *dbst; GetIdDbSec(obj, dbst, dbp); av = bdb_test_load(obj, data, FILTER_VALUE|FILTER_FREE); rec = INT2NUM(recno - dbst->array_base); if (dbst->append_recno == 0) res = rb_funcall(obj, id_append_recno, 2, rec, av); else res = rb_funcall(dbst->append_recno, bdb_id_call, 2, rec, av); if (!NIL_P(res)) { bdb_test_dump(obj, data, res, FILTER_VALUE); } return 0; } #endif #if HAVE_ST_DB_SET_FEEDBACK static void bdb_feedback(DB *dbp, int opcode, int pct) { VALUE obj; bdb_DB *dbst; GetIdDbSec(obj, dbst, dbp); if (NIL_P(dbst->feedback)) { return; } if (dbst->feedback == 0) { rb_funcall(obj, id_feedback, 2, INT2NUM(opcode), INT2NUM(pct)); } else { rb_funcall(dbst->feedback, bdb_id_call, 2, INT2NUM(opcode), INT2NUM(pct)); } } #endif static VALUE compar_func(VALUE value) { value = rb_obj_as_string(value); char *compar = StringValuePtr(value); if (strcmp(compar, "int_compare") == 0) { value = INT2NUM(INT_COMPAR); } else if (strcmp(compar, "int_compare_desc") == 0) { value = INT2NUM(COMPAR_INT); } else if (strcmp(compar, "numeric_compare") == 0) { value = INT2NUM(NUM_COMPAR); } else if (strcmp(compar, "numeric_compare_desc") == 0) { value = INT2NUM(COMPAR_NUM); } else if (strcmp(compar, "string_compare") == 0) { value = INT2NUM(STR_COMPAR); } else if (strcmp(compar, "string_compare_desc") == 0) { value = INT2NUM(STR_COMPAR); } else { rb_raise(bdb_eFatal, "arg must respond to #call"); } return value; } static VALUE bdb_i_options(VALUE obj, VALUE dbstobj) { VALUE key, value; char *options, *str; DB *dbp; bdb_DB *dbst; Data_Get_Struct(dbstobj, bdb_DB, dbst); key = rb_ary_entry(obj, 0); value = rb_ary_entry(obj, 1); dbp = dbst->dbp; key = rb_obj_as_string(key); options = StringValuePtr(key); if (strcmp(options, "set_bt_minkey") == 0) { #if HAVE_TYPE_DB_INFO dbst->dbinfo->bt_minkey = NUM2INT(value); #else bdb_test_error(dbp->set_bt_minkey(dbp, NUM2INT(value))); #endif } else if (strcmp(options, "set_bt_compare") == 0) { if (!rb_respond_to(value, bdb_id_call)) { value = compar_func(value); } dbst->options |= BDB_BT_COMPARE; dbst->bt_compare = value; #if HAVE_TYPE_DB_INFO dbst->dbinfo->bt_compare = bdb_bt_compare; #else bdb_test_error(dbp->set_bt_compare(dbp, bdb_bt_compare)); #endif } else if (strcmp(options, "set_bt_prefix") == 0) { if (!rb_respond_to(value, bdb_id_call)) { rb_raise(bdb_eFatal, "arg must respond to #call"); } dbst->options |= BDB_BT_PREFIX; dbst->bt_prefix = value; #if HAVE_TYPE_DB_INFO dbst->dbinfo->bt_prefix = bdb_bt_prefix; #else bdb_test_error(dbp->set_bt_prefix(dbp, bdb_bt_prefix)); #endif } else if (strcmp(options, "set_dup_compare") == 0) { #if HAVE_CONST_DB_DUPSORT if (!rb_respond_to(value, bdb_id_call)) { value = compar_func(value); } dbst->options |= BDB_DUP_COMPARE; dbst->dup_compare = value; #if HAVE_TYPE_DB_INFO dbst->dbinfo->dup_compare = bdb_dup_compare; #else bdb_test_error(dbp->set_dup_compare(dbp, bdb_dup_compare)); #endif #else rb_warning("dup_compare need db >= 2.5.9"); #endif } else if (strcmp(options, "set_h_hash") == 0) { if (!rb_respond_to(value, bdb_id_call)) { rb_raise(bdb_eFatal, "arg must respond to #call"); } dbst->options |= BDB_H_HASH; dbst->h_hash = value; #if HAVE_TYPE_DB_INFO dbst->dbinfo->h_hash = bdb_h_hash; #else bdb_test_error(dbp->set_h_hash(dbp, bdb_h_hash)); #endif } #if HAVE_ST_DB_SET_H_COMPARE else if (strcmp(options, "set_h_compare") == 0) { if (!rb_respond_to(value, bdb_id_call)) { value = compar_func(value); } dbst->options |= BDB_H_COMPARE; dbst->h_compare = value; bdb_test_error(dbp->set_h_compare(dbp, bdb_h_compare)); } #endif #if HAVE_ST_DB_SET_APPEND_RECNO else if (strcmp(options, "set_append_recno") == 0) { if (!rb_respond_to(value, bdb_id_call)) { rb_raise(bdb_eFatal, "arg must respond to #call"); } dbst->options |= BDB_APPEND_RECNO; dbst->append_recno = value; bdb_test_error(dbp->set_append_recno(dbp, bdb_append_recno)); } #endif else if (strcmp(options, "set_cachesize") == 0) { switch (TYPE(value)) { case T_FIXNUM: case T_FLOAT: case T_BIGNUM: #if HAVE_TYPE_DB_INFO dbst->dbinfo->db_cachesize = NUM2INT(value); #else bdb_test_error(dbp->set_cachesize(dbp, 0, NUM2UINT(value), 0)); #endif break; default: Check_Type(value, T_ARRAY); if (RARRAY_LEN(value) < 3) { rb_raise(bdb_eFatal, "expected 3 values for cachesize"); } #if HAVE_TYPE_DB_INFO dbst->dbinfo->db_cachesize = NUM2INT(RARRAY_PTR(value)[1]); #else bdb_test_error(dbp->set_cachesize(dbp, NUM2INT(RARRAY_PTR(value)[0]), NUM2INT(RARRAY_PTR(value)[1]), NUM2INT(RARRAY_PTR(value)[2]))); #endif break; } } else if (strcmp(options, "set_flags") == 0) { #if HAVE_TYPE_DB_INFO dbst->dbinfo->flags = NUM2UINT(value); #else bdb_test_error(dbp->set_flags(dbp, NUM2UINT(value))); #endif dbst->flags |= NUM2UINT(value); } else if (strcmp(options, "set_h_ffactor") == 0) { #if HAVE_TYPE_DB_INFO dbst->dbinfo->h_ffactor = NUM2INT(value); #else bdb_test_error(dbp->set_h_ffactor(dbp, NUM2INT(value))); #endif } else if (strcmp(options, "set_h_nelem") == 0) { #if HAVE_TYPE_DB_INFO dbst->dbinfo->h_nelem = NUM2INT(value); #else bdb_test_error(dbp->set_h_nelem(dbp, NUM2INT(value))); #endif } else if (strcmp(options, "set_lorder") == 0) { #if HAVE_TYPE_DB_INFO dbst->dbinfo->db_lorder = NUM2INT(value); #else bdb_test_error(dbp->set_lorder(dbp, NUM2INT(value))); #endif } else if (strcmp(options, "set_pagesize") == 0) { #if HAVE_TYPE_DB_INFO dbst->dbinfo->db_pagesize = NUM2INT(value); #else bdb_test_error(dbp->set_pagesize(dbp, NUM2INT(value))); #endif } else if (strcmp(options, "set_re_delim") == 0) { int ch; if (TYPE(value) == T_STRING) { str = StringValuePtr(value); ch = str[0]; } else { ch = NUM2INT(value); } #if HAVE_TYPE_DB_INFO dbst->dbinfo->re_delim = ch; dbst->dbinfo->flags |= DB_DELIMITER; #else bdb_test_error(dbp->set_re_delim(dbp, ch)); #endif } else if (strcmp(options, "set_re_len") == 0) { #if HAVE_TYPE_DB_INFO dbst->dbinfo->re_len = NUM2INT(value); dbst->dbinfo->flags |= DB_FIXEDLEN; #else bdb_test_error(dbp->set_re_len(dbp, NUM2INT(value))); #endif } else if (strcmp(options, "set_re_pad") == 0) { int ch; if (TYPE(value) == T_STRING) { str = StringValuePtr(value); ch = str[0]; } else { ch = NUM2INT(value); } #if HAVE_TYPE_DB_INFO dbst->dbinfo->re_pad = ch; dbst->dbinfo->flags |= DB_PAD; #else bdb_test_error(dbp->set_re_pad(dbp, ch)); #endif } else if (strcmp(options, "set_re_source") == 0) { if (TYPE(value) != T_STRING) rb_raise(bdb_eFatal, "re_source must be a filename"); #if HAVE_TYPE_DB_INFO dbst->dbinfo->re_source = StringValuePtr(value); #else bdb_test_error(dbp->set_re_source(dbp, StringValuePtr(value))); #endif dbst->options |= BDB_RE_SOURCE; } #if HAVE_ST_DB_SET_Q_EXTENTSIZE else if (strcmp(options, "set_q_extentsize") == 0) { bdb_test_error(dbp->set_q_extentsize(dbp, NUM2INT(value))); } #endif else if (strcmp(options, "marshal") == 0) { switch (value) { case Qtrue: dbst->marshal = bdb_mMarshal; dbst->options |= BDB_MARSHAL; break; case Qfalse: dbst->marshal = Qfalse; dbst->options &= ~BDB_MARSHAL; break; default: if (!bdb_respond_to(value, bdb_id_load) || !bdb_respond_to(value, bdb_id_dump)) { rb_raise(bdb_eFatal, "marshal value must be true or false"); } dbst->marshal = value; dbst->options |= BDB_MARSHAL; break; } } else if (strcmp(options, "set_array_base") == 0 || strcmp(options, "array_base") == 0) { int ary_base = NUM2INT(value); switch (ary_base) { case 0: dbst->array_base = 1; break; case 1: dbst->array_base = 0; break; default: rb_raise(bdb_eFatal, "array base must be 0 or 1"); } } else if (strcmp(options, "thread") == 0) { if (RTEST(value)) { dbst->options &= ~BDB_NO_THREAD; } else { dbst->options |= BDB_NO_THREAD; } } else if (strcmp(options, "set_store_key") == 0) { if (!rb_respond_to(value, bdb_id_call)) { rb_raise(bdb_eFatal, "arg must respond to #call"); } dbst->filter[FILTER_KEY] = value; } else if (strcmp(options, "set_fetch_key") == 0) { if (!rb_respond_to(value, bdb_id_call)) { rb_raise(bdb_eFatal, "arg must respond to #call"); } dbst->filter[2 + FILTER_KEY] = value; } else if (strcmp(options, "set_store_value") == 0) { if (!rb_respond_to(value, bdb_id_call)) { rb_raise(bdb_eFatal, "arg must respond to #call"); } dbst->filter[FILTER_VALUE] = value; } else if (strcmp(options, "set_fetch_value") == 0) { if (!rb_respond_to(value, bdb_id_call)) { rb_raise(bdb_eFatal, "arg must respond to #call"); } dbst->filter[2 + FILTER_VALUE] = value; } #if HAVE_ST_DB_SET_ENCRYPT else if (strcmp(options, "set_encrypt") == 0) { char *passwd; int flags = DB_ENCRYPT_AES; if (TYPE(value) == T_ARRAY) { if (RARRAY_LEN(value) != 2) { rb_raise(bdb_eFatal, "Expected an Array with 2 values"); } passwd = StringValuePtr(RARRAY_PTR(value)[0]); flags = NUM2INT(RARRAY_PTR(value)[1]); } else { passwd = StringValuePtr(value); } bdb_test_error(dbp->set_encrypt(dbp, passwd, flags)); } #endif #if HAVE_ST_DB_SET_FEEDBACK else if (strcmp(options, "set_feedback") == 0) { if (!rb_respond_to(value, bdb_id_call)) { rb_raise(bdb_eFatal, "arg must respond to #call"); } dbst->options |= BDB_FEEDBACK; dbst->feedback = value; dbp->set_feedback(dbp, bdb_feedback); } #endif else if (strcmp(options, "store_nil_as_null") == 0) { if (RTEST(value)) { dbst->options |= BDB_NIL; } else { dbst->options &= ~BDB_NIL; } } return Qnil; } struct bdb_eiv { VALUE bdb; bdb_DB *dbst; }; static void bdb_i_close(bdb_DB *dbst, int flags) { bdb_ENV *envst; if (dbst->dbp) { if (RTEST(dbst->txn) && RBASIC(dbst->txn)->flags) { bdb_TXN *txnst; int opened = 0; Data_Get_Struct(dbst->txn, bdb_TXN, txnst); opened = bdb_ary_delete(&txnst->db_ary, dbst->ori_val); if (!opened) { opened = bdb_ary_delete(&txnst->db_assoc, dbst->ori_val); } if (opened) { if (txnst->options & BDB_TXN_COMMIT) { rb_funcall2(dbst->txn, rb_intern("commit"), 0, 0); } else { rb_funcall2(dbst->txn, rb_intern("abort"), 0, 0); } } if (!(dbst->options & BDB_NOT_OPEN)) { dbst->dbp->close(dbst->dbp, flags); } } else { if (dbst->env && RBASIC(dbst->env)->flags) { Data_Get_Struct(dbst->env, bdb_ENV, envst); bdb_ary_delete(&envst->db_ary, dbst->ori_val); } if (!(dbst->options & BDB_NOT_OPEN)) { dbst->dbp->close(dbst->dbp, flags); } } } dbst->dbp = NULL; } VALUE bdb_local_aref() { bdb_DB *dbst; VALUE obj; GetIdDb(obj, dbst); return obj; } static VALUE i_close(bdb_DB *dbst) { bdb_i_close(dbst, 0); return Qnil; } static VALUE bdb_final_aref(bdb_DB *dbst) { VALUE obj, th; th = rb_thread_current(); if (RTEST(th) && RBASIC(th)->flags) { obj = rb_thread_local_aref(th, bdb_id_current_db); if (!NIL_P(obj) && RDATA(obj)->dmark == (RUBY_DATA_FUNC)bdb_mark && DATA_PTR(obj) == dbst) { rb_thread_local_aset(th, bdb_id_current_db, Qnil); } } return Qnil; } static void bdb_free(bdb_DB *dbst) { if (dbst->dbp && !(dbst->options & BDB_NOT_OPEN)) { i_close(dbst); bdb_final_aref(dbst); } free(dbst); } static void bdb_mark(bdb_DB *dbst) { int i; rb_gc_mark(dbst->marshal); rb_gc_mark(dbst->env); rb_gc_mark(dbst->txn); rb_gc_mark(dbst->orig); rb_gc_mark(dbst->secondary); rb_gc_mark(dbst->bt_compare); rb_gc_mark(dbst->bt_prefix); #if HAVE_CONST_DB_DUPSORT rb_gc_mark(dbst->dup_compare); #endif for (i = 0; i < 4; i++) { rb_gc_mark(dbst->filter[i]); } rb_gc_mark(dbst->h_hash); #if HAVE_ST_DB_SET_H_COMPARE rb_gc_mark(dbst->h_compare); #endif rb_gc_mark(dbst->filename); rb_gc_mark(dbst->database); #if HAVE_ST_DB_SET_APPEND_RECNO rb_gc_mark(dbst->append_recno); #endif #if HAVE_ST_DB_SET_FEEDBACK rb_gc_mark(dbst->feedback); #endif } static VALUE bdb_env(VALUE obj) { bdb_DB *dbst; GetDB(obj, dbst); if (RTEST(dbst->env)) { return dbst->env; } return Qnil; } VALUE bdb_env_p(VALUE obj) { bdb_DB *dbst; GetDB(obj, dbst); return (RTEST(dbst->env)?Qtrue:Qfalse); } static VALUE bdb_txn(VALUE obj) { bdb_DB *dbst; GetDB(obj, dbst); if (RTEST(dbst->txn)) { return dbst->txn; } return Qnil; } VALUE bdb_txn_p(VALUE obj) { bdb_DB *dbst; GetDB(obj, dbst); return (RTEST(dbst->txn)?Qtrue:Qfalse); } static VALUE bdb_close(int argc, VALUE *argv, VALUE obj) { VALUE opt; bdb_DB *dbst; int flags = 0; if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4) { rb_raise(rb_eSecurityError, "Insecure: can't close the database"); } Data_Get_Struct(obj, bdb_DB, dbst); if (dbst->dbp != NULL) { if (rb_scan_args(argc, argv, "01", &opt)) { flags = NUM2INT(opt); } bdb_i_close(dbst, flags); } if (RDATA(obj)->dfree != free) { dbst->options |= BDB_NOT_OPEN; bdb_final_aref(dbst); RDATA(obj)->dfree = free; } return Qnil; } #if ! HAVE_ST_DB_BTREE_STAT_BT_NKEYS static long bdb_hard_count(dbp) DB *dbp; { DBC *dbcp; DBT key, data; db_recno_t recno; long count = 0; int ret; MEMZERO(&key, DBT, 1); key.data = &recno; key.size = sizeof(db_recno_t); #if HAVE_DB_CURSOR_4 bdb_test_error(dbp->cursor(dbp, 0, &dbcp, 0)); #else key.flags |= DB_DBT_MALLOC; bdb_test_error(dbp->cursor(dbp, 0, &dbcp)); #endif do { MEMZERO(&data, DBT, 1); data.flags = DB_DBT_MALLOC; bdb_cache_error(dbcp->c_get(dbcp, &key, &data, DB_NEXT), dbcp->c_close(dbcp), ret); if (ret == DB_NOTFOUND) { dbcp->c_close(dbcp); return count; } if (ret == DB_KEYEMPTY) { dbcp->c_close(dbcp); return -1; } free(data.data); count++; } while (1); return count; } #endif static long bdb_is_recnum(dbp) DB *dbp; { DB_BTREE_STAT *bdb_stat; long count; #if ! HAVE_ST_DB_BTREE_STAT_BT_NKEYS long hard; #endif #if HAVE_ST_DB_BTREE_STAT_BT_NKEYS #if HAVE_DB_STAT_4 #if HAVE_DB_STAT_4_TXN bdb_test_error(dbp->stat(dbp, NULL, &bdb_stat, 0)); #else bdb_test_error(dbp->stat(dbp, &bdb_stat, 0, 0)); #endif #else bdb_test_error(dbp->stat(dbp, &bdb_stat, 0)); #endif count = (bdb_stat->bt_nkeys == bdb_stat->bt_ndata)?bdb_stat->bt_nkeys:-1; free(bdb_stat); #else bdb_test_error(dbp->stat(dbp, &bdb_stat, 0, DB_RECORDCOUNT)); count = bdb_stat->bt_nrecs; free(bdb_stat); hard = bdb_hard_count(dbp); count = (count == hard)?count:-1; #endif return count; } static VALUE bdb_recno_length(obj) VALUE obj; { bdb_DB *dbst; DB_BTREE_STAT *bdb_stat; VALUE hash; #if HAVE_DB_STAT_4 && HAVE_CONST_DB_FAST_STAT DB_TXN *txnid = NULL; #endif GetDB(obj, dbst); #if HAVE_CONST_DB_FAST_STAT #if HAVE_DB_STAT_4 if (RTEST(dbst->txn)) { bdb_TXN *txnst; GetTxnDB(dbst->txn, txnst); txnid = txnst->txnid; } bdb_test_error(dbst->dbp->stat(dbst->dbp, txnid, &bdb_stat, DB_FAST_STAT)); #else bdb_test_error(dbst->dbp->stat(dbst->dbp, &bdb_stat, DB_FAST_STAT)); #endif #else #if HAVE_DB_STAT_4 bdb_test_error(dbst->dbp->stat(dbst->dbp, &bdb_stat, 0, DB_RECORDCOUNT)); #else bdb_test_error(dbst->dbp->stat(dbst->dbp, &bdb_stat, DB_RECORDCOUNT)); #endif #endif #if HAVE_ST_DB_BTREE_STAT_BT_NKEYS hash = INT2NUM(bdb_stat->bt_nkeys); #else hash = INT2NUM(bdb_stat->bt_nrecs); #endif free(bdb_stat); return hash; } static VALUE bdb_s_new(int argc, VALUE *argv, VALUE obj) { VALUE res; bdb_TXN *txnst = NULL; bdb_ENV *envst = NULL; bdb_DB *dbst; DB_ENV *envp = 0; #ifdef HAVE_RB_DEFINE_ALLOC_FUNC res = rb_obj_alloc(obj); #else res = rb_funcall2(obj, rb_intern("allocate"), 0, 0); #endif Data_Get_Struct(res, bdb_DB, dbst); if (argc && TYPE(argv[argc - 1]) == T_HASH) { VALUE v, f = argv[argc - 1]; if ((v = rb_hash_aref(f, rb_str_new2("txn"))) != RHASH(f)->ifnone) { if (!rb_obj_is_kind_of(v, bdb_cTxn)) { rb_raise(bdb_eFatal, "argument of txn must be a transaction"); } Data_Get_Struct(v, bdb_TXN, txnst); dbst->txn = v; dbst->env = txnst->env; Data_Get_Struct(txnst->env, bdb_ENV, envst); envp = envst->envp; dbst->options |= envst->options & BDB_NO_THREAD; dbst->marshal = txnst->marshal; } else if ((v = rb_hash_aref(f, rb_str_new2("env"))) != RHASH(f)->ifnone) { if (!rb_obj_is_kind_of(v, bdb_cEnv)) { rb_raise(bdb_eFatal, "argument of env must be an environnement"); } Data_Get_Struct(v, bdb_ENV, envst); dbst->env = v; envp = envst->envp; dbst->options |= envst->options & BDB_NO_THREAD; dbst->marshal = envst->marshal; } #if HAVE_CONST_DB_ENCRYPT if (envst && (envst->options & BDB_ENV_ENCRYPT)) { VALUE tmp = rb_str_new2("set_flags"); if ((v = rb_hash_aref(f, rb_intern("set_flags"))) != RHASH(f)->ifnone) { rb_hash_aset(f, rb_intern("set_flags"), INT2NUM(NUM2INT(v) | DB_ENCRYPT)); } else if ((v = rb_hash_aref(f, tmp)) != RHASH(f)->ifnone) { rb_hash_aset(f, tmp, INT2NUM(NUM2INT(v) | DB_ENCRYPT)); } else { rb_hash_aset(f, tmp, INT2NUM(DB_ENCRYPT)); } } #endif } #if HAVE_ST_DB_SET_ERRCALL bdb_test_error(db_create(&(dbst->dbp), envp, 0)); dbst->dbp->set_errpfx(dbst->dbp, "BDB::"); dbst->dbp->set_errcall(dbst->dbp, bdb_env_errcall); #endif if (bdb_respond_to(obj, bdb_id_load) == Qtrue && bdb_respond_to(obj, bdb_id_dump) == Qtrue) { dbst->marshal = obj; dbst->options |= BDB_MARSHAL; } if (rb_method_boundp(obj, rb_intern("bdb_store_key"), 0) == Qtrue) { dbst->filter[FILTER_KEY] = INT2FIX(rb_intern("bdb_store_key")); } if (rb_method_boundp(obj, rb_intern("bdb_fetch_key"), 0) == Qtrue) { dbst->filter[2 + FILTER_KEY] = INT2FIX(rb_intern("bdb_fetch_key")); } if (rb_method_boundp(obj, rb_intern("bdb_store_value"), 0) == Qtrue) { dbst->filter[FILTER_VALUE] = INT2FIX(rb_intern("bdb_store_value")); } if (rb_method_boundp(obj, rb_intern("bdb_fetch_value"), 0) == Qtrue) { dbst->filter[2 + FILTER_VALUE] = INT2FIX(rb_intern("bdb_fetch_value")); } rb_obj_call_init(res, argc, argv); if (txnst) { bdb_ary_push(&txnst->db_ary, res); } else if (envst) { bdb_ary_push(&envst->db_ary, res); } return res; } VALUE bdb_init(int argc, VALUE *argv, VALUE obj) { bdb_DB *dbst; DB *dbp; int flags, mode, ret, nb; char *name, *subname; VALUE a, b, d, e; VALUE hash_arg = Qnil; #if HAVE_TYPE_DB_INFO DB_INFO dbinfo; MEMZERO(&dbinfo, DB_INFO, 1); #endif Data_Get_Struct(obj, bdb_DB, dbst); dbp = dbst->dbp; #if HAVE_TYPE_DB_INFO dbst->dbinfo = &dbinfo; #endif #if HAVE_ST_DB_SET_ENCRYPT if (rb_const_defined(CLASS_OF(obj), rb_intern("BDB_ENCRYPT"))) { char *passwd; int flags = DB_ENCRYPT_AES; VALUE value = rb_const_get(CLASS_OF(obj), rb_intern("BDB_ENCRYPT")); if (TYPE(value) == T_ARRAY) { if (RARRAY_LEN(value) != 2) { rb_raise(bdb_eFatal, "Expected an Array with 2 values"); } passwd = StringValuePtr(RARRAY_PTR(value)[0]); flags = NUM2INT(RARRAY_PTR(value)[1]); } else { passwd = StringValuePtr(value); } bdb_test_error(dbp->set_encrypt(dbp, passwd, flags)); } #endif if (argc && TYPE(argv[argc - 1]) == T_HASH) { hash_arg = argv[argc - 1]; rb_iterate(rb_each, argv[argc - 1], bdb_i_options, obj); argc--; } mode = flags = 0; if (argc) { flags = DB_RDONLY; } a = b = d = e = Qnil; switch(nb = rb_scan_args(argc, argv, "04", &a, &b, &d, &e)) { case 4: mode = NUM2INT(e); case 3: if (TYPE(d) == T_STRING) { if (strcmp(StringValuePtr(d), "r") == 0) flags = DB_RDONLY; else if (strcmp(StringValuePtr(d), "r+") == 0) flags = 0; else if (strcmp(StringValuePtr(d), "w") == 0 || strcmp(StringValuePtr(d), "w+") == 0) flags = DB_CREATE | DB_TRUNCATE; else if (strcmp(StringValuePtr(d), "a") == 0 || strcmp(StringValuePtr(d), "a+") == 0) flags = DB_CREATE; else { rb_raise(bdb_eFatal, "flags must be r, r+, w, w+, a or a+"); } } else if (d == Qnil) flags = DB_RDONLY; else flags = NUM2INT(d); } name = subname = NULL; if (!NIL_P(a)) { SafeStringValue(a); name = StringValuePtr(a); } if (!NIL_P(b)) { SafeStringValue(b); subname = StringValuePtr(b); } if (dbst->bt_compare == 0 && rb_respond_to(obj, id_bt_compare) == Qtrue) { dbst->options |= BDB_BT_COMPARE; #if HAVE_TYPE_DB_INFO dbst->dbinfo->bt_compare = bdb_bt_compare; #else bdb_test_error(dbp->set_bt_compare(dbp, bdb_bt_compare)); #endif } if (dbst->bt_prefix == 0 && rb_respond_to(obj, id_bt_prefix) == Qtrue) { dbst->options |= BDB_BT_PREFIX; #if HAVE_TYPE_DB_INFO dbst->dbinfo->bt_prefix = bdb_bt_prefix; #else bdb_test_error(dbp->set_bt_prefix(dbp, bdb_bt_prefix)); #endif } #if HAVE_CONST_DB_DUPSORT if (dbst->dup_compare == 0 && rb_respond_to(obj, id_dup_compare) == Qtrue) { dbst->options |= BDB_DUP_COMPARE; #if HAVE_TYPE_DB_INFO dbst->dbinfo->dup_compare = bdb_dup_compare; #else bdb_test_error(dbp->set_dup_compare(dbp, bdb_dup_compare)); #endif } #endif if (dbst->h_hash == 0 && rb_respond_to(obj, id_h_hash) == Qtrue) { dbst->options |= BDB_H_HASH; #if HAVE_TYPE_DB_INFO dbst->dbinfo->h_hash = bdb_h_hash; #else bdb_test_error(dbp->set_h_hash(dbp, bdb_h_hash)); #endif } #if HAVE_ST_DB_SET_H_COMPARE if (dbst->h_compare == 0 && rb_respond_to(obj, id_h_compare) == Qtrue) { dbst->options |= BDB_H_COMPARE; bdb_test_error(dbp->set_h_compare(dbp, bdb_h_compare)); } #endif #if HAVE_ST_DB_SET_APPEND_RECNO if (dbst->append_recno == 0 && rb_respond_to(obj, id_append_recno) == Qtrue) { dbst->options |= BDB_APPEND_RECNO; bdb_test_error(dbp->set_append_recno(dbp, bdb_append_recno)); } #endif #if HAVE_ST_DB_SET_FEEDBACK if (dbst->feedback == 0 && rb_respond_to(obj, id_feedback) == Qtrue) { dbp->set_feedback(dbp, bdb_feedback); dbst->options |= BDB_FEEDBACK; } #endif if (flags & DB_TRUNCATE) { rb_secure(2); } if (flags & DB_CREATE) { rb_secure(4); } if (rb_safe_level() >= 4) { flags |= DB_RDONLY; } #if HAVE_CONST_DB_DUPSORT if (dbst->options & BDB_DUP_COMPARE) { #if HAVE_TYPE_DB_INFO dbst->dbinfo->flags = DB_DUP | DB_DUPSORT; #else bdb_test_error(dbp->set_flags(dbp, DB_DUP | DB_DUPSORT)); #endif } #endif #ifndef BDB_NO_THREAD_COMPILE if (!(dbst->options & (BDB_RE_SOURCE | BDB_NO_THREAD))) { flags |= DB_THREAD; } #endif if (dbst->options & BDB_NEED_CURRENT) { rb_thread_local_aset(rb_thread_current(), bdb_id_current_db, obj); } #if ! HAVE_ST_DB_OPEN { bdb_ENV *envst; DB_ENV *envp = NULL; if (dbst->env) { Data_Get_Struct(dbst->env, bdb_ENV, envst); envp = envst->envp; } if (name == NULL && (flags & DB_RDONLY)) { flags &= ~DB_RDONLY; } if ((ret = db_open(name, dbst->type, flags, mode, envp, dbst->dbinfo, &dbp)) != 0) { if (bdb_errcall) { bdb_errcall = 0; rb_raise(bdb_eFatal, "%s -- %s", StringValuePtr(bdb_errstr), db_strerror(ret)); } else rb_raise(bdb_eFatal, "%s", db_strerror(ret)); } dbst->dbp = dbp; } #else { #if HAVE_DB_OPEN_7 DB_TXN *txnid = NULL; #endif if (name == NULL && subname == NULL) { if (flags & DB_RDONLY) { flags &= ~DB_RDONLY; } #if HAVE_DB_OPEN_7 #if HAVE_DB_OPEN_7_DB_CREATE flags |= DB_CREATE; #endif #endif } #if HAVE_DB_OPEN_7 if (RTEST(dbst->txn)) { bdb_TXN *txnst; GetTxnDB(dbst->txn, txnst); txnid = txnst->txnid; } else if (RTEST(dbst->env)) { bdb_ENV *envst; GetEnvDB(dbst->env, envst); #if HAVE_CONST_DB_AUTO_COMMIT if (envst->options & BDB_AUTO_COMMIT) { flags |= DB_AUTO_COMMIT; dbst->options |= BDB_AUTO_COMMIT; } } #endif ret = dbp->open(dbp, txnid, name, subname, dbst->type, flags, mode); #else ret = dbp->open(dbp, name, subname, dbst->type, flags, mode); #endif if (ret != 0) { dbp->close(dbp, 0); if (bdb_errcall) { bdb_errcall = 0; rb_raise(bdb_eFatal, "%s -- %s", StringValuePtr(bdb_errstr), db_strerror(ret)); } else { rb_raise(bdb_eFatal, "%s", db_strerror(ret)); } } } #endif dbst->options &= ~BDB_NOT_OPEN; if (dbst->env) { bdb_ENV *envst; Data_Get_Struct(dbst->env, bdb_ENV, envst); dbst->options |= envst->options & BDB_INIT_LOCK; } dbst->filename = dbst->database = Qnil; if (name) { dbst->filename = rb_tainted_str_new2(name); OBJ_FREEZE(dbst->filename); } #if HAVE_ST_DB_OPEN if (subname) { dbst->database = rb_tainted_str_new2(subname); OBJ_FREEZE(dbst->database); } #endif dbst->len = -2; if (dbst->type == DB_UNKNOWN) { #if ! HAVE_ST_DB_GET_TYPE dbst->type = dbst->dbp->type; #else #if HAVE_TYPE_DBTYPE { DBTYPE new_type; #if HAVE_DB_GET_TYPE_2 bdb_test_error(dbst->dbp->get_type(dbst->dbp, &new_type)); #else new_type = dbst->dbp->get_type(dbst->dbp); #endif dbst->type = (int)new_type; } #else dbst->type = dbst->dbp->get_type(dbst->dbp); #endif #endif switch(dbst->type) { case DB_BTREE: RBASIC(obj)->klass = bdb_cBtree; break; case DB_HASH: RBASIC(obj)->klass = bdb_cHash; break; case DB_RECNO: { long count; rb_warning("It's hard to distinguish Recnum with Recno for all versions of Berkeley DB"); if ((count = bdb_is_recnum(dbst->dbp)) != -1) { RBASIC(obj)->klass = bdb_cRecnum; dbst->len = count; } else { RBASIC(obj)->klass = bdb_cRecno; } break; } #if HAVE_CONST_DB_QUEUE case DB_QUEUE: RBASIC(obj)->klass = bdb_cQueue; break; #endif default: dbst->dbp->close(dbst->dbp, 0); dbst->dbp = NULL; rb_raise(bdb_eFatal, "Unknown DB type"); } } if (dbst->len == -2 && rb_obj_is_kind_of(obj, bdb_cRecnum)) { long count; if ((count = bdb_is_recnum(dbst->dbp)) != -1) { VALUE len = bdb_recno_length(obj); dbst->len = NUM2LONG(len); } else { if (flags & DB_TRUNCATE) { dbst->len = 0; } else { dbst->dbp->close(dbst->dbp, 0); dbst->dbp = NULL; rb_raise(bdb_eFatal, "database is not a Recnum"); } } } #if HAVE_ST_DB_APP_PRIVATE dbst->dbp->app_private = (void *)obj; #endif return obj; } static VALUE bdb_s_alloc(obj) VALUE obj; { VALUE res, cl; bdb_DB *dbst; res = Data_Make_Struct(obj, bdb_DB, bdb_mark, bdb_free, dbst); dbst->options = BDB_NOT_OPEN; cl = obj; while (cl) { if (cl == bdb_cBtree || RCLASS(cl)->m_tbl == RCLASS(bdb_cBtree)->m_tbl) { dbst->type = DB_BTREE; break; } if (cl == bdb_cRecnum || RCLASS(cl)->m_tbl == RCLASS(bdb_cRecnum)->m_tbl) { dbst->type = DB_RECNO; break; } else if (cl == bdb_cHash || RCLASS(cl)->m_tbl == RCLASS(bdb_cHash)->m_tbl) { dbst->type = DB_HASH; break; } else if (cl == bdb_cRecno || RCLASS(cl)->m_tbl == RCLASS(bdb_cRecno)->m_tbl) { dbst->type = DB_RECNO; break; } #if HAVE_CONST_DB_QUEUE else if (cl == bdb_cQueue || RCLASS(cl)->m_tbl == RCLASS(bdb_cQueue)->m_tbl) { dbst->type = DB_QUEUE; break; } #endif else if (cl == bdb_cUnknown || RCLASS(cl)->m_tbl == RCLASS(bdb_cUnknown)->m_tbl) { dbst->type = DB_UNKNOWN; break; } cl = RCLASS_SUPER(cl); } if (!cl) { rb_raise(bdb_eFatal, "unknown database type"); } dbst->ori_val = res; return res; } static VALUE bdb_i_s_create(obj, db) VALUE obj, db; { VALUE tmp[2]; tmp[0] = rb_ary_entry(obj, 0); tmp[1] = rb_ary_entry(obj, 1); bdb_put(2, tmp, db); return Qnil; } static VALUE bdb_s_create(int argc, VALUE *argv, VALUE obj) { VALUE res; int i; res = rb_funcall2(obj, rb_intern("new"), 0, 0); if (argc == 1 && TYPE(argv[0]) == T_HASH) { rb_iterate(rb_each, argv[0], bdb_i_s_create, res); return res; } if (argc % 2 != 0) { rb_raise(rb_eArgError, "odd number args for %s", rb_class2name(obj)); } for (i = 0; i < argc; i += 2) { bdb_put(2, argv + i, res); } return res; } static VALUE bdb_s_open(int argc, VALUE *argv, VALUE obj) { VALUE res = rb_funcall2(obj, rb_intern("new"), argc, argv); if (rb_block_given_p()) { return rb_ensure(rb_yield, res, bdb_protect_close, res); } return res; } #if HAVE_CONST_DB_QUEUE struct re { int re_len, re_pad; }; static VALUE bdb_queue_i_search_re_len(obj, restobj) VALUE obj, restobj; { VALUE key, value; char *str; struct re *rest; Data_Get_Struct(restobj, struct re, rest); key = rb_ary_entry(obj, 0); value = rb_ary_entry(obj, 1); key = rb_obj_as_string(key); if (strcmp(StringValuePtr(key), "set_re_len") == 0) { rest->re_len = NUM2INT(value); } else if (strcmp(StringValuePtr(key), "set_re_pad") == 0) { int ch; if (TYPE(value) == T_STRING) { str = StringValuePtr(value); ch = str[0]; } else { ch = NUM2INT(value); } rest->re_pad = ch; } return Qnil; } #define DEFAULT_RECORD_LENGTH 132 #define DEFAULT_RECORD_PAD 0x20 static VALUE bdb_queue_s_new(int argc, VALUE *argv, VALUE obj) { VALUE *nargv, ret, restobj; struct re *rest; bdb_DB *dbst; restobj = Data_Make_Struct(obj, struct re, 0, free, rest); rest->re_len = -1; rest->re_pad = -1; if (argc && TYPE(argv[argc - 1]) == T_HASH) { rb_iterate(rb_each, argv[argc - 1], bdb_queue_i_search_re_len, restobj); if (rest->re_len <= 0) { rest->re_len = DEFAULT_RECORD_LENGTH; rb_hash_aset(argv[argc - 1], rb_tainted_str_new2("set_re_len"), INT2NUM(rest->re_len)); } if (rest->re_pad < 0) { rest->re_pad = DEFAULT_RECORD_PAD; rb_hash_aset(argv[argc - 1], rb_tainted_str_new2("set_re_pad"), INT2NUM(rest->re_pad)); } nargv = argv; } else { nargv = ALLOCA_N(VALUE, argc + 1); MEMCPY(nargv, argv, VALUE, argc); nargv[argc] = rb_hash_new(); rest->re_len = DEFAULT_RECORD_LENGTH; rest->re_pad = DEFAULT_RECORD_PAD; rb_hash_aset(nargv[argc], rb_tainted_str_new2("set_re_len"), INT2NUM(DEFAULT_RECORD_LENGTH)); rb_hash_aset(nargv[argc], rb_tainted_str_new2("set_re_pad"), INT2NUM(DEFAULT_RECORD_PAD)); argc += 1; } ret = bdb_s_new(argc, nargv, obj); Data_Get_Struct(ret, bdb_DB, dbst); dbst->re_len = rest->re_len; dbst->re_pad = rest->re_pad; return ret; } #endif static VALUE bdb_append_internal(argc, argv, obj, flag, retval) int argc, flag; VALUE *argv, obj; { bdb_DB *dbst; DB_TXN *txnid; DBT key, data; db_recno_t recno; int i; VALUE *a, ary = Qnil; volatile VALUE res = Qnil; rb_secure(4); if (argc < 1) return obj; INIT_TXN(txnid, obj, dbst); #if HAVE_CONST_DB_AUTO_COMMIT if (txnid == NULL && (dbst->options & BDB_AUTO_COMMIT)) { flag |= DB_AUTO_COMMIT; } #endif MEMZERO(&key, DBT, 1); recno = 1; key.data = &recno; key.size = sizeof(db_recno_t); #if DB_APPEND if (flag & DB_APPEND) { key.flags |= DB_DBT_MALLOC; } #endif if (retval) { ary = rb_ary_new(); } for (i = 0, a = argv; i < argc; i++, a++) { MEMZERO(&data, DBT, 1); res = bdb_test_dump(obj, &data, *a, FILTER_VALUE); SET_PARTIAL(dbst, data); #if HAVE_CONST_DB_QUEUE if (dbst->type == DB_QUEUE && dbst->re_len < data.size) { rb_raise(bdb_eFatal, "size > re_len for Queue"); } #endif bdb_test_error(dbst->dbp->put(dbst->dbp, txnid, &key, &data, flag)); if (retval) { rb_ary_push(ary, INT2NUM(*(db_recno_t *)key.data)); } } if (retval) { return ary; } return obj; } static VALUE bdb_append_m(int argc, VALUE *argv, VALUE obj) { return bdb_append_internal(argc, argv, obj, DB_APPEND, Qtrue); } static VALUE bdb_append(obj, val) VALUE val, obj; { return bdb_append_internal(1, &val, obj, DB_APPEND, Qfalse); } static VALUE bdb_unshift(int argc, VALUE *argv, VALUE obj) { bdb_DB *dbst; DB_TXN *txnid; int flag; INIT_TXN(txnid, obj, dbst); if (dbst->flags & DB_RENUMBER) { flag = 0; } else { flag = DB_NOOVERWRITE; } return bdb_append_internal(argc, argv, obj, flag, Qtrue); } VALUE bdb_put(int argc, VALUE *argv, VALUE obj) { volatile VALUE a0 = Qnil; volatile VALUE b0 = Qnil; VALUE a, b, c; bdb_DB *dbst; DB_TXN *txnid; DBT key, data; int ret, flags; db_recno_t recno; rb_secure(4); INIT_TXN(txnid, obj, dbst); flags = 0; a = b = c = Qnil; MEMZERO(&key, DBT, 1); MEMZERO(&data, DBT, 1); if (rb_scan_args(argc, argv, "21", &a, &b, &c) == 3) { flags = NUM2INT(c); } a0 = bdb_test_recno(obj, &key, &recno, a); b0 = bdb_test_dump(obj, &data, b, FILTER_VALUE); SET_PARTIAL(dbst, data); #if HAVE_CONST_DB_QUEUE if (dbst->type == DB_QUEUE && dbst->re_len < data.size) { rb_raise(bdb_eFatal, "size > re_len for Queue"); } #endif #if HAVE_CONST_DB_AUTO_COMMIT if (txnid == NULL && (dbst->options & BDB_AUTO_COMMIT)) { flags |= DB_AUTO_COMMIT; } #endif ret = bdb_test_error(dbst->dbp->put(dbst->dbp, txnid, &key, &data, flags)); if (ret == DB_KEYEXIST) return Qfalse; else { if (dbst->partial) { if (flags & DB_APPEND) { a = INT2NUM((long)key.data); } return bdb_get(1, &a, obj); } else { return bdb_test_ret(obj, b0, b, FILTER_VALUE); } } } static VALUE bdb_aset(obj, a, b) VALUE obj, a, b; { VALUE tmp[2]; tmp[0] = a; tmp[1] = b; bdb_put(2, tmp, obj); return b; } VALUE bdb_test_load_key(obj, key) VALUE obj; DBT *key; { bdb_DB *dbst; Data_Get_Struct(obj, bdb_DB, dbst); if (RECNUM_TYPE(dbst)) return INT2NUM((*(db_recno_t *)key->data) - dbst->array_base); return bdb_test_load(obj, key, FILTER_KEY); } VALUE bdb_assoc(obj, key, data) VALUE obj; DBT *key, *data; { return rb_assoc_new(bdb_test_load_key(obj, key), bdb_test_load(obj, data, FILTER_VALUE)); } VALUE bdb_assoc_dyna(obj, key, data) VALUE obj; DBT *key, *data; { VALUE k, v; int to_free = key->flags & DB_DBT_MALLOC; key->flags &= ~DB_DBT_MALLOC; k = bdb_test_load_key(obj, key); v = test_load_dyna1(obj, key, data); if (to_free) { free(key->data); key->data = 0; } return rb_assoc_new(k, v); } #if HAVE_ST_DB_PGET static VALUE bdb_assoc2(obj, skey, pkey, data) VALUE obj; DBT *skey, *pkey, *data; { return rb_assoc_new( rb_assoc_new(bdb_test_load_key(obj, skey), bdb_test_load_key(obj, pkey)), bdb_test_load(obj, data, FILTER_VALUE)); } #endif VALUE bdb_assoc3(obj, skey, pkey, data) VALUE obj; DBT *skey, *pkey, *data; { return rb_ary_new3(3, bdb_test_load_key(obj, skey), bdb_test_load_key(obj, pkey), bdb_test_load(obj, data, FILTER_VALUE)); } static VALUE bdb_has_both _((VALUE, VALUE, VALUE)); #if (BDB_VERSION < 30100) || ! HAVE_CONST_DB_GET_BOTH #define CANT_DB_CURSOR_GET_BOTH 1 static VALUE bdb_has_both_internal _((VALUE, VALUE, VALUE, VALUE)); #else #define CANT_DB_CURSOR_GET_BOTH 0 #endif static VALUE bdb_get_internal(argc, argv, obj, notfound, dyna) int argc; VALUE *argv; VALUE obj; VALUE notfound; int dyna; { VALUE a = Qnil; VALUE b = Qnil; VALUE c; bdb_DB *dbst; DB_TXN *txnid; DBT key, data; int flagss; int ret, flags; db_recno_t recno; void *tmp_data = 0; INIT_TXN(txnid, obj, dbst); flagss = flags = 0; MEMZERO(&key, DBT, 1); MEMZERO(&data, DBT, 1); data.flags |= DB_DBT_MALLOC; switch(rb_scan_args(argc, argv, "12", &a, &b, &c)) { case 3: flags = NUM2INT(c); if ((flags & ~DB_RMW) == DB_GET_BOTH) { #if ! HAVE_CONST_DB_GET_BOTH return bdb_has_both_internal(obj, a, b, Qtrue); #else b = bdb_test_dump(obj, &data, b, FILTER_VALUE); data.flags |= DB_DBT_MALLOC; tmp_data = data.data; #endif } break; case 2: flagss = flags = NUM2INT(b); break; } a = bdb_test_recno(obj, &key, &recno, a); SET_PARTIAL(dbst, data); flags |= TEST_INIT_LOCK(dbst); #if HAVE_ST_DB_OPEN #if HAVE_DB_KEY_DBT_MALLOC { void *tmp_key = key.data; key.flags |= DB_DBT_MALLOC; #endif #endif ret = bdb_test_error(dbst->dbp->get(dbst->dbp, txnid, &key, &data, flags)); if (ret == DB_NOTFOUND || ret == DB_KEYEMPTY) return notfound; #if HAVE_ST_DB_OPEN #if HAVE_DB_KEY_DBT_MALLOC if (tmp_key == key.data) { key.flags &= ~DB_DBT_MALLOC; } } #endif #endif if (((flags & ~DB_RMW) == DB_GET_BOTH) || ((flags & ~DB_RMW) == DB_SET_RECNO)) { if (tmp_data == data.data) { data.flags &= ~DB_DBT_MALLOC; } return bdb_assoc(obj, &key, &data); } if (dyna) { return test_load_dyna(obj, &key, &data); } else { return bdb_test_load(obj, &data, FILTER_VALUE); } } VALUE bdb_get(int argc, VALUE *argv, VALUE obj) { return bdb_get_internal(argc, argv, obj, Qnil, 0); } static VALUE bdb_get_dyna(int argc, VALUE *argv, VALUE obj) { return bdb_get_internal(argc, argv, obj, Qnil, 1); } static VALUE bdb_fetch(int argc, VALUE *argv, VALUE obj) { VALUE key, if_none; VALUE val; rb_scan_args(argc, argv, "11", &key, &if_none); val = bdb_get_internal(1, argv, obj, Qundef, 1); if (val == Qundef) { if (rb_block_given_p()) { if (argc > 1) { rb_raise(rb_eArgError, "wrong # of arguments"); } return rb_yield(key); } if (argc == 1) { rb_raise(rb_eIndexError, "key not found"); } return if_none; } return val; } #if HAVE_ST_DB_PGET static VALUE bdb_pget(int argc, VALUE *argv, VALUE obj) { VALUE a = Qnil; VALUE b = Qnil; VALUE c; bdb_DB *dbst; DB_TXN *txnid; DBT pkey, data, skey; int flagss; int ret, flags; db_recno_t srecno; void *tmp_data = 0; INIT_TXN(txnid, obj, dbst); flagss = flags = 0; MEMZERO(&skey, DBT, 1); MEMZERO(&pkey, DBT, 1); MEMZERO(&data, DBT, 1); data.flags |= DB_DBT_MALLOC; pkey.flags |= DB_DBT_MALLOC; switch(rb_scan_args(argc, argv, "12", &a, &b, &c)) { case 3: flags = NUM2INT(c); if ((flags & ~DB_RMW) == DB_GET_BOTH) { b = bdb_test_dump(obj, &data, b, FILTER_VALUE); data.flags |= DB_DBT_MALLOC; tmp_data = data.data; } break; case 2: flagss = flags = NUM2INT(b); break; } a = bdb_test_recno(obj, &skey, &srecno, a); SET_PARTIAL(dbst, data); flags |= TEST_INIT_LOCK(dbst); ret = bdb_test_error(dbst->dbp->pget(dbst->dbp, txnid, &skey, &pkey, &data, flags)); if (ret == DB_NOTFOUND || ret == DB_KEYEMPTY) return Qnil; if (((flags & ~DB_RMW) == DB_GET_BOTH) || ((flags & ~DB_RMW) == DB_SET_RECNO)) { if ((data.flags & DB_DBT_MALLOC) && tmp_data == data.data) { data.flags &= ~DB_DBT_MALLOC; } return bdb_assoc2(obj, &skey, &pkey, &data); } return bdb_assoc(obj, &pkey, &data); } #endif #if HAVE_TYPE_DB_KEY_RANGE static VALUE bdb_btree_key_range(obj, a) VALUE obj, a; { bdb_DB *dbst; DB_TXN *txnid; DBT key; db_recno_t recno; DB_KEY_RANGE key_range; volatile VALUE b = Qnil; INIT_TXN(txnid, obj, dbst); MEMZERO(&key, DBT, 1); b = bdb_test_recno(obj, &key, &recno, a); bdb_test_error(dbst->dbp->key_range(dbst->dbp, txnid, &key, &key_range, 0)); return rb_struct_new(bdb_sKeyrange, rb_float_new(key_range.less), rb_float_new(key_range.equal), rb_float_new(key_range.greater)); } #endif #if HAVE_TYPE_DB_COMPACT struct data_flags { DB_COMPACT *cdata; int flags; }; static VALUE bdb_compact_i(obj, dataobj) VALUE obj, dataobj; { VALUE key, value; char *str; struct data_flags *dtf; Data_Get_Struct(dataobj, struct data_flags, dtf); key = rb_ary_entry(obj, 0); value = rb_ary_entry(obj, 1); key = rb_obj_as_string(key); str = StringValuePtr(key); if (strcmp(str, "compact_timeout") == 0) { dtf->cdata->compact_timeout = NUM2LONG(value); } else if (strcmp(str, "compact_fillpercent") == 0) { dtf->cdata->compact_fillpercent = NUM2INT(value); } else if (strcmp(str, "flags") == 0) { dtf->flags = NUM2INT(value); } else { rb_warning("Unknown option %s", str); } return Qnil; } static VALUE bdb_treerec_compact(int argc, VALUE *argv, VALUE obj) { bdb_DB *dbst; DB_TXN *txnid; DBT start, stop, end; DBT *pstart, *pstop; DB_COMPACT cdata; db_recno_t recno_start, recno_stop; int flags; VALUE a, b, c, result; pstop = pstart = NULL; MEMZERO(&cdata, DB_COMPACT, 1); flags = 0; INIT_TXN(txnid, obj, dbst); switch (rb_scan_args(argc, argv, "03", &a, &b, &c)) { case 3: if (FIXNUM_P(c)) { flags = NUM2INT(c); } else { struct data_flags *dtf; VALUE dtobj; dtobj = Data_Make_Struct(rb_cData, struct data_flags, 0, free, dtf); dtf->cdata = &cdata; dtf->flags = 0; rb_iterate(rb_each, c, bdb_compact_i, dtobj); flags = dtf->flags; } /* ... */ case 2: if (!NIL_P(b)) { MEMZERO(&stop, DBT, 1); b = bdb_test_recno(obj, &start, &recno_stop, b); pstop = &stop; } /* ... */ case 1: if (!NIL_P(a)) { MEMZERO(&start, DBT, 1); a = bdb_test_recno(obj, &start, &recno_start, a); pstart = &start; } } MEMZERO(&end, DBT, 1); bdb_test_error(dbst->dbp->compact(dbst->dbp, txnid, pstart, pstop, &cdata, flags, &end)); result = rb_hash_new(); rb_hash_aset(result, rb_tainted_str_new2("end"), bdb_test_load_key(obj, &end)); rb_hash_aset(result, rb_tainted_str_new2("compact_deadlock"), INT2NUM(cdata.compact_deadlock)); rb_hash_aset(result, rb_tainted_str_new2("compact_levels"), INT2NUM(cdata.compact_levels)); rb_hash_aset(result, rb_tainted_str_new2("compact_pages_free"), INT2NUM(cdata.compact_pages_free)); rb_hash_aset(result, rb_tainted_str_new2("compact_pages_examine"), INT2NUM(cdata.compact_pages_examine)); rb_hash_aset(result, rb_tainted_str_new2("compact_pages_truncated"), INT2NUM(cdata.compact_pages_truncated)); return result; } #endif #if HAVE_ST_DBC_C_GET #if HAVE_CONST_DB_NEXT_DUP static VALUE bdb_count(obj, a) VALUE obj, a; { bdb_DB *dbst; DB_TXN *txnid; DBC *dbcp; DBT key, data; int ret, flags27; db_recno_t recno; db_recno_t count; volatile VALUE b = Qnil; INIT_TXN(txnid, obj, dbst); MEMZERO(&key, DBT, 1); b = bdb_test_recno(obj, &key, &recno, a); MEMZERO(&data, DBT, 1); data.flags |= DB_DBT_MALLOC; SET_PARTIAL(dbst, data); #if HAVE_DB_CURSOR_4 bdb_test_error(dbst->dbp->cursor(dbst->dbp, txnid, &dbcp, 0)); #else bdb_test_error(dbst->dbp->cursor(dbst->dbp, txnid, &dbcp)); #endif flags27 = TEST_INIT_LOCK(dbst); bdb_cache_error(dbcp->c_get(dbcp, &key, &data, DB_SET | flags27), dbcp->c_close(dbcp), ret); if (ret == DB_NOTFOUND) { dbcp->c_close(dbcp); return INT2NUM(0); } #if HAVE_ST_DBC_C_COUNT bdb_cache_error(dbcp->c_count(dbcp, &count, 0), dbcp->c_close(dbcp), ret); dbcp->c_close(dbcp); return INT2NUM(count); #else count = 1; while (1) { MEMZERO(&data, DBT, 1); data.flags |= DB_DBT_MALLOC; SET_PARTIAL(dbst, data); bdb_cache_error(dbcp->c_get(dbcp, &key, &data, DB_NEXT_DUP | flags27), dbcp->c_close(dbcp), ret); if (ret == DB_NOTFOUND) { dbcp->c_close(dbcp); return INT2NUM(count); } if (ret == DB_KEYEMPTY) continue; FREE_KEY(dbst, key); if (data.flags & DB_DBT_MALLOC) { free(data.data); data.data = 0; } count++; } return INT2NUM(-1); #endif } #endif #if HAVE_CONST_DB_CONSUME static VALUE bdb_consume(obj) VALUE obj; { bdb_DB *dbst; DB_TXN *txnid; DBT key, data; DBC *dbcp; int ret; db_recno_t recno; rb_secure(4); INIT_TXN(txnid, obj, dbst); MEMZERO(&key, DBT, 1); MEMZERO(&data, DBT, 1); recno = 1; key.data = &recno; key.size = sizeof(db_recno_t); bdb_test_error(dbst->dbp->cursor(dbst->dbp, txnid, &dbcp, 0)); bdb_cache_error(dbcp->c_get(dbcp, &key, &data, DB_CONSUME), dbcp->c_close(dbcp), ret); dbcp->c_close(dbcp); if (ret == DB_NOTFOUND) { return Qnil; } return bdb_assoc(obj, &key, &data); } #endif #endif static VALUE bdb_has_key(obj, key) VALUE obj, key; { return (bdb_get_internal(1, &key, obj, Qundef, 0) == Qundef)?Qfalse:Qtrue; } #if CANT_DB_CURSOR_GET_BOTH static VALUE bdb_has_both_internal(obj, a, b, flag) VALUE obj, a, b, flag; { bdb_DB *dbst; DB_TXN *txnid; DBC *dbcp; DBT key, data; DBT datas; int flagss; int ret, flags; db_recno_t recno; volatile VALUE c = Qnil; volatile VALUE d = Qnil; INIT_TXN(txnid, obj, dbst); flagss = flags = 0; MEMZERO(&key, DBT, 1); MEMZERO(&data, DBT, 1); MEMZERO(&datas, DBT, 1); c = bdb_test_recno(obj, &key, &recno, a); d = bdb_test_dump(obj, &datas, b, FILTER_VALUE); data.flags |= DB_DBT_MALLOC; SET_PARTIAL(dbst, data); flags |= TEST_INIT_LOCK(dbst); #if HAVE_DB_CURSOR_4 bdb_test_error(dbst->dbp->cursor(dbst->dbp, txnid, &dbcp, 0)); #else bdb_test_error(dbst->dbp->cursor(dbst->dbp, txnid, &dbcp)); #endif bdb_cache_error(dbcp->c_get(dbcp, &key, &data, DB_SET), dbcp->c_close(dbcp), ret); if (ret == DB_NOTFOUND || ret == DB_KEYEMPTY) { dbcp->c_close(dbcp); return (flag == Qtrue)?Qnil:Qfalse; } if (datas.size == data.size && memcmp(datas.data, data.data, data.size) == 0) { dbcp->c_close(dbcp); if (flag == Qtrue) { return bdb_assoc(obj, &key, &data); } else { FREE_KEY(dbst, key); free(data.data); return Qtrue; } } #if ! HAVE_CONST_DB_NEXT_DUP FREE_KEY(dbst, key); free(data.data); dbcp->c_close(dbcp); return (flag == Qtrue)?Qnil:Qfalse; #else #if CANT_DB_CURSOR_GET_BOTH if (RECNUM_TYPE(dbst)) { free(data.data); dbcp->c_close(dbcp); return Qfalse; } #endif while (1) { FREE_KEY(dbst, key); free(data.data); MEMZERO(&data, DBT, 1); data.flags |= DB_DBT_MALLOC; bdb_cache_error(dbcp->c_get(dbcp, &key, &data, DB_NEXT_DUP), dbcp->c_close(dbcp), ret); if (ret == DB_NOTFOUND || ret == DB_KEYEMPTY) { dbcp->c_close(dbcp); return Qfalse; } if (datas.size == data.size && memcmp(datas.data, data.data, data.size) == 0) { FREE_KEY(dbst, key); free(data.data); dbcp->c_close(dbcp); return Qtrue; } } return Qfalse; #endif } #endif static VALUE bdb_has_both(obj, a, b) VALUE obj, a, b; { #if ! HAVE_CONST_DB_GET_BOTH return bdb_has_both_internal(obj, a, b, Qfalse); #else bdb_DB *dbst; DB_TXN *txnid; DBT key, data; int ret, flags; db_recno_t recno; volatile VALUE c = Qnil; volatile VALUE d = Qnil; void *tmp_key, *tmp_data; INIT_TXN(txnid, obj, dbst); #if CANT_DB_CURSOR_GET_BOTH if (RECNUM_TYPE(dbst)) { return bdb_has_both_internal(obj, a, b, Qfalse); } #endif MEMZERO(&key, DBT, 1); MEMZERO(&data, DBT, 1); c = bdb_test_recno(obj, &key, &recno, a); d = bdb_test_dump(obj, &data, b, FILTER_VALUE); data.flags |= DB_DBT_MALLOC; SET_PARTIAL(dbst, data); flags = DB_GET_BOTH | TEST_INIT_LOCK(dbst); tmp_key = key.data; tmp_data = data.data; #if HAVE_ST_DB_OPEN #if HAVE_DB_KEY_DBT_MALLOC key.flags |= DB_DBT_MALLOC; #endif #endif ret = bdb_test_error(dbst->dbp->get(dbst->dbp, txnid, &key, &data, flags)); if (ret == DB_NOTFOUND || ret == DB_KEYEMPTY) return Qfalse; if (tmp_data != data.data) { free(data.data); } if ((key.flags & DB_DBT_MALLOC) && tmp_key != key.data) { free(key.data); } return Qtrue; #endif } VALUE bdb_del(obj, a) VALUE a, obj; { bdb_DB *dbst; DB_TXN *txnid; int flag = 0; DBT key; int ret; db_recno_t recno; volatile VALUE b = Qnil; rb_secure(4); INIT_TXN(txnid, obj, dbst); #if HAVE_CONST_DB_AUTO_COMMIT if (txnid == NULL && (dbst->options & BDB_AUTO_COMMIT)) { flag |= DB_AUTO_COMMIT; } #endif MEMZERO(&key, DBT, 1); b = bdb_test_recno(obj, &key, &recno, a); ret = bdb_test_error(dbst->dbp->del(dbst->dbp, txnid, &key, flag)); if (ret == DB_NOTFOUND || ret == DB_KEYEMPTY) return Qnil; else return obj; } static VALUE bdb_empty(obj) VALUE obj; { bdb_DB *dbst; DB_TXN *txnid; DBC *dbcp; DBT key, data; int ret, flags; db_recno_t recno; INIT_TXN(txnid, obj, dbst); MEMZERO(&key, DBT, 1); INIT_RECNO(dbst, key, recno); MEMZERO(&data, DBT, 1); data.flags = DB_DBT_MALLOC; #if HAVE_DB_CURSOR_4 bdb_test_error(dbst->dbp->cursor(dbst->dbp, txnid, &dbcp, 0)); #else bdb_test_error(dbst->dbp->cursor(dbst->dbp, txnid, &dbcp)); #endif SET_PARTIAL(dbst, data); flags = TEST_INIT_LOCK(dbst); bdb_cache_error(dbcp->c_get(dbcp, &key, &data, DB_FIRST | flags), dbcp->c_close(dbcp), ret); if (ret == DB_NOTFOUND) { dbcp->c_close(dbcp); return Qtrue; } FREE_KEY(dbst, key); free(data.data); dbcp->c_close(dbcp); return Qfalse; } static VALUE bdb_lgth_intern(obj, delete) VALUE obj, delete; { bdb_DB *dbst; DB_TXN *txnid; DBC *dbcp; DBT key, data; int ret, value, flags; db_recno_t recno; INIT_TXN(txnid, obj, dbst); value = 0; #if HAVE_DB_CURSOR_4 bdb_test_error(dbst->dbp->cursor(dbst->dbp, txnid, &dbcp, 0)); #else bdb_test_error(dbst->dbp->cursor(dbst->dbp, txnid, &dbcp)); #endif SET_PARTIAL(dbst, data); flags = TEST_INIT_LOCK(dbst); do { MEMZERO(&key, DBT, 1); INIT_RECNO(dbst, key, recno); MEMZERO(&data, DBT, 1); data.flags = DB_DBT_MALLOC; SET_PARTIAL(dbst, data); bdb_cache_error(dbcp->c_get(dbcp, &key, &data, DB_NEXT | flags), dbcp->c_close(dbcp), ret); if (ret == DB_NOTFOUND) { dbcp->c_close(dbcp); return INT2NUM(value); } if (ret == DB_KEYEMPTY) continue; FREE_KEY(dbst, key); free(data.data); value++; if (delete == Qtrue) { bdb_test_error(dbcp->c_del(dbcp, 0)); } } while (1); return INT2NUM(-1); } static VALUE bdb_length(obj) VALUE obj; { return bdb_lgth_intern(obj, Qfalse); } typedef struct { int sens; VALUE replace; VALUE db; VALUE set; DBC *dbcp; #if HAVE_CONST_DB_MULTIPLE_KEY void *data; int len; #endif int primary; int type; } eachst; static VALUE bdb_each_ensure(st) eachst *st; { #if HAVE_CONST_DB_MULTIPLE_KEY if (st->len && st->data) { free(st->data); } #endif st->dbcp->c_close(st->dbcp); return Qnil; } static void bdb_treat(st, pkey, key, data) eachst *st; DBT *pkey, *key, *data; { bdb_DB *dbst; DBC *dbcp; VALUE res = Qnil; GetDB(st->db, dbst); dbcp = st->dbcp; switch (st->type) { case BDB_ST_DUPU: FREE_KEY(dbst, *key); res = bdb_test_load(st->db, data, FILTER_VALUE); if (TYPE(st->replace) == T_ARRAY) { rb_ary_push(st->replace, res); } else { rb_yield(res); } break; case BDB_ST_DUPKV: res = bdb_assoc_dyna(st->db, key, data); if (TYPE(st->replace) == T_ARRAY) { rb_ary_push(st->replace, res); } else { rb_yield(res); } break; case BDB_ST_DUPVAL: res = test_load_dyna(st->db, key, data); if (TYPE(st->replace) == T_ARRAY) { rb_ary_push(st->replace, res); } else { rb_yield(res); } break; case BDB_ST_KEY: if (data->flags & DB_DBT_MALLOC) { free(data->data); data->flags &= ~DB_DBT_MALLOC; data->data = 0; } rb_yield(bdb_test_load_key(st->db, key)); break; case BDB_ST_VALUE: FREE_KEY(dbst, *key); res = rb_yield(bdb_test_load(st->db, data, FILTER_VALUE)); if (st->replace == Qtrue) { MEMZERO(data, DBT, 1); res = bdb_test_dump(st->db, data, res, FILTER_VALUE); SET_PARTIAL(dbst, *data); bdb_test_error(dbcp->c_put(dbcp, key, data, DB_CURRENT)); } else if (st->replace != Qfalse) { rb_ary_push(st->replace, res); } break; case BDB_ST_SELECT: res = bdb_assoc(st->db, key, data); if (RTEST(rb_yield(res))) { rb_ary_push(st->replace, res); } break; case BDB_ST_KV: if (st->primary) { rb_yield(bdb_assoc3(st->db, key, pkey, data)); } else { rb_yield(bdb_assoc_dyna(st->db, key, data)); } break; case BDB_ST_REJECT: { VALUE ary = bdb_assoc(st->db, key, data); if (!RTEST(rb_yield(ary))) { rb_hash_aset(st->replace, RARRAY_PTR(ary)[0], RARRAY_PTR(ary)[1]); } break; } case BDB_ST_DELETE: if (RTEST(rb_yield(bdb_assoc(st->db, key, data)))) { bdb_test_error(dbcp->c_del(dbcp, 0)); } break; } } static int bdb_i_last_prefix(dbcp, key, pkey, data, orig, st) DBC *dbcp; DBT *key, *pkey, *data, *orig; eachst *st; { int ret, flags = DB_LAST; while (1) { #if HAVE_CONST_DB_MULTIPLE_KEY if (st->type == BDB_ST_KV && st->primary) { ret = bdb_test_error(dbcp->c_pget(dbcp, key, pkey, data, DB_LAST)); } else #endif { #if HAVE_CURSOR_C_GET_KEY_MALLOC key->flags |= DB_DBT_MALLOC; #endif ret = bdb_test_error(dbcp->c_get(dbcp, key, data, flags)); #if HAVE_CURSOR_C_GET_KEY_MALLOC key->flags &= ~DB_DBT_MALLOC; #endif } flags = DB_PREV; if (ret == DB_NOTFOUND) { return ret; } if (key->size >= orig->size && !memcmp(key->data, orig->data, orig->size)) { return 0; } if (memcmp(key->data, orig->data, (key->size > orig->size)?orig->size:key->size) < 0) { return DB_NOTFOUND; } } } static VALUE bdb_i_each_kv(st) eachst *st; { bdb_DB *dbst; DBC *dbcp; DBT pkey, key, data, orig; int ret, init = Qfalse, prefix = Qfalse; db_recno_t recno; volatile VALUE res = Qnil; prefix = st->type & BDB_ST_PREFIX; st->type &= ~BDB_ST_PREFIX; GetDB(st->db, dbst); dbcp = st->dbcp; MEMZERO(&key, DBT, 1); INIT_RECNO(dbst, key, recno); MEMZERO(&orig, DBT, 1); MEMZERO(&data, DBT, 1); data.flags = DB_DBT_MALLOC; SET_PARTIAL(dbst, data); MEMZERO(&pkey, DBT, 1); pkey.flags = DB_DBT_MALLOC; if (!NIL_P(st->set)) { res = bdb_test_recno(st->db, &key, &recno, st->set); if (prefix) { init = Qtrue; orig.size = key.size; orig.data = ALLOCA_N(char, key.size); MEMCPY(orig.data, key.data, char, key.size); } if (prefix && st->sens == DB_PREV) { ret = bdb_i_last_prefix(dbcp, &key, &pkey, &data, &orig, st); } else { #if HAVE_CONST_DB_MULTIPLE_KEY if (st->type == BDB_ST_KV && st->primary) { ret = bdb_test_error(dbcp->c_pget(dbcp, &key, &pkey, &data, (st->type & BDB_ST_DUP)?DB_SET: DB_SET_RANGE)); } else #endif { #if HAVE_CURSOR_C_GET_KEY_MALLOC key.flags |= DB_DBT_MALLOC; #endif MEMZERO(&data, DBT, 1); data.flags = DB_DBT_MALLOC; SET_PARTIAL(dbst, data); ret = bdb_test_error(dbcp->c_get(dbcp, &key, &data, (st->type & BDB_ST_DUP)?DB_SET: DB_SET_RANGE)); #if HAVE_CURSOR_C_GET_KEY_MALLOC key.flags &= ~DB_DBT_MALLOC; #endif } } if (ret == DB_NOTFOUND) { return Qfalse; } if (prefix) { if (key.size >= orig.size && !memcmp(key.data, orig.data, orig.size)) { bdb_treat(st, &pkey, &key, &data); } else { return Qfalse; } } else { bdb_treat(st, &pkey, &key, &data); } } do { #if HAVE_CONST_DB_MULTIPLE_KEY if (st->type == BDB_ST_KV && st->primary) { ret = bdb_test_error(dbcp->c_pget(dbcp, &key, &pkey, &data, st->sens)); } else #endif { #if HAVE_CURSOR_C_GET_KEY_MALLOC key.flags |= DB_DBT_MALLOC; #endif MEMZERO(&data, DBT, 1); data.flags = DB_DBT_MALLOC; SET_PARTIAL(dbst, data); ret = bdb_test_error(dbcp->c_get(dbcp, &key, &data, st->sens)); #if HAVE_CURSOR_C_GET_KEY_MALLOC key.flags &= ~DB_DBT_MALLOC; #endif } if (ret == DB_NOTFOUND) { return Qnil; } if (ret == DB_KEYEMPTY) continue; if (prefix) { if (!init) { init = Qtrue; orig.size = key.size; orig.data = ALLOCA_N(char, key.size); MEMCPY(orig.data, key.data, char, key.size); } if (key.size >= orig.size && !memcmp(key.data, orig.data, orig.size)) { bdb_treat(st, &pkey, &key, &data); } } else { bdb_treat(st, &pkey, &key, &data); } } while (1); return Qnil; } #if HAVE_CONST_DB_MULTIPLE_KEY static VALUE bdb_i_each_kv_bulk(st) eachst *st; { bdb_DB *dbst; DBC *dbcp; DBT key, data; DBT rkey, rdata; DBT pkey; int ret, init; db_recno_t recno; void *p; volatile VALUE res = Qnil; GetDB(st->db, dbst); dbcp = st->dbcp; MEMZERO(&key, DBT, 1); MEMZERO(&pkey, DBT, 1); MEMZERO(&rkey, DBT, 1); INIT_RECNO(dbst, key, recno); MEMZERO(&data, DBT, 1); MEMZERO(&rdata, DBT, 1); st->data = data.data = (void *)ALLOC_N(char, st->len); data.ulen = st->len; data.flags = DB_DBT_USERMEM; SET_PARTIAL(dbst, data); SET_PARTIAL(dbst, rdata); init = 1; do { if (init && !NIL_P(st->set)) { res = bdb_test_recno(st->db, &key, &recno, st->set); ret = bdb_test_error(dbcp->c_get(dbcp, &key, &data, ((st->type & BDB_ST_DUP)?DB_SET: DB_SET_RANGE)|DB_MULTIPLE_KEY)); init = 0; } else { ret = bdb_test_error(dbcp->c_get(dbcp, &key, &data, st->sens | DB_MULTIPLE_KEY)); } if (ret == DB_NOTFOUND) { return Qnil; } if (ret == DB_KEYEMPTY) continue; for (DB_MULTIPLE_INIT(p, &data);;) { if (RECNUM_TYPE(dbst)) { DB_MULTIPLE_RECNO_NEXT(p, &data, recno, rdata.data, rdata.size); } else { DB_MULTIPLE_KEY_NEXT(p, &data, rkey.data, rkey.size, rdata.data, rdata.size); } if (p == NULL) break; bdb_treat(st, 0, &rkey, &rdata); } } while (1); return Qnil; } #endif VALUE bdb_each_kvc(argc, argv, obj, sens, replace, type) VALUE obj, *argv; int argc, sens; VALUE replace; int type; { bdb_DB *dbst; DB_TXN *txnid; DBC *dbcp; eachst st; int flags = 0; if (argc && TYPE(argv[argc - 1]) == T_HASH) { VALUE g, f = argv[argc - 1]; if ((g = rb_hash_aref(f, rb_intern("flags"))) != RHASH(f)->ifnone || (g = rb_hash_aref(f, rb_str_new2("flags"))) != RHASH(f)->ifnone) { flags = NUM2INT(g); } argc--; } MEMZERO(&st, eachst, 1); #if HAVE_CONST_DB_MULTIPLE_KEY { VALUE bulkv = Qnil; st.set = Qnil; if (type & BDB_ST_ONE) { rb_scan_args(argc, argv, "01", &st.set); } else { if (type & BDB_ST_DUP) { rb_scan_args(argc, argv, "11", &st.set, &bulkv); } else { if (rb_scan_args(argc, argv, "02", &st.set, &bulkv) == 2) { if (bulkv == Qtrue || bulkv == Qfalse) { st.primary = RTEST(bulkv); bulkv = Qnil; } } } } if (!NIL_P(bulkv)) { st.len = 1024 * NUM2INT(bulkv); if (st.len < 0) { rb_raise(bdb_eFatal, "negative value for bulk retrieval"); } } } #else if (type & BDB_ST_DUP) { if (argc != 1) { rb_raise(bdb_eFatal, "invalid number of arguments (%d for 1)", argc); } st.set = argv[0]; } else { rb_scan_args(argc, argv, "01", &st.set); } #endif type &= ~BDB_ST_ONE; if ((type & ~BDB_ST_PREFIX) == BDB_ST_DELETE) { rb_secure(4); } INIT_TXN(txnid, obj, dbst); #if HAVE_DB_CURSOR_4 bdb_test_error(dbst->dbp->cursor(dbst->dbp, txnid, &dbcp, flags)); #else bdb_test_error(dbst->dbp->cursor(dbst->dbp, txnid, &dbcp)); #endif st.db = obj; st.dbcp = dbcp; st.sens = sens | TEST_INIT_LOCK(dbst); st.replace = replace; st.type = type & ~BDB_ST_ONE; #if HAVE_CONST_DB_MULTIPLE_KEY if (st.len) { rb_ensure(bdb_i_each_kv_bulk, (VALUE)&st, bdb_each_ensure, (VALUE)&st); } else #endif { rb_ensure(bdb_i_each_kv, (VALUE)&st, bdb_each_ensure, (VALUE)&st); } if (replace == Qtrue || replace == Qfalse) { return obj; } else { return st.replace; } } #if HAVE_CONST_DB_NEXT_DUP static VALUE bdb_get_dup(int argc, VALUE *argv, VALUE obj) { VALUE result = Qfalse; if (!rb_block_given_p()) { result = rb_ary_new(); } return bdb_each_kvc(argc, argv, obj, DB_NEXT_DUP, result, BDB_ST_DUPU); } static VALUE bdb_common_each_dup(int argc, VALUE *argv, VALUE obj) { if (!rb_block_given_p()) { rb_raise(bdb_eFatal, "each_dup called out of an iterator"); } return bdb_each_kvc(argc, argv, obj, DB_NEXT_DUP, Qfalse, BDB_ST_DUPKV); } static VALUE bdb_common_each_dup_val(int argc, VALUE *argv, VALUE obj) { if (!rb_block_given_p()) { rb_raise(bdb_eFatal, "each_dup called out of an iterator"); } return bdb_each_kvc(argc, argv, obj, DB_NEXT_DUP, Qfalse, BDB_ST_DUPVAL); } static VALUE bdb_common_dups(int argc, VALUE *argv, VALUE obj) { int flags = BDB_ST_DUPKV; VALUE result = rb_ary_new(); if (argc > 1) { if (RTEST(argv[argc - 1])) { flags = BDB_ST_DUPKV; } else { flags = BDB_ST_DUPVAL; } argc--; } return bdb_each_kvc(argc, argv, obj, DB_NEXT_DUP, result, flags); } #endif static VALUE bdb_delete_if(int argc, VALUE *argv, VALUE obj) { return bdb_each_kvc(argc, argv, obj, DB_NEXT, Qfalse, BDB_ST_DELETE | BDB_ST_ONE); } static VALUE bdb_reject(int argc, VALUE *argv, VALUE obj) { return bdb_each_kvc(argc, argv, obj, DB_NEXT, rb_hash_new(), BDB_ST_REJECT); } VALUE bdb_each_value(int argc, VALUE *argv, VALUE obj) { return bdb_each_kvc(argc, argv, obj, DB_NEXT, Qfalse, BDB_ST_VALUE); } VALUE bdb_each_eulav(int argc, VALUE *argv, VALUE obj) { return bdb_each_kvc(argc, argv, obj, DB_PREV, Qfalse, BDB_ST_VALUE | BDB_ST_ONE); } VALUE bdb_each_key(int argc, VALUE *argv, VALUE obj) { return bdb_each_kvc(argc, argv, obj, DB_NEXT, Qfalse, BDB_ST_KEY); } static VALUE bdb_each_yek(int argc, VALUE *argv, VALUE obj) { return bdb_each_kvc(argc, argv, obj, DB_PREV, Qfalse, BDB_ST_KEY | BDB_ST_ONE); } static VALUE bdb_each_pair(int argc, VALUE *argv, VALUE obj) { return bdb_each_kvc(argc, argv, obj, DB_NEXT, Qfalse, BDB_ST_KV); } static VALUE bdb_each_prefix(int argc, VALUE *argv, VALUE obj) { return bdb_each_kvc(argc, argv, obj, DB_NEXT, Qfalse, BDB_ST_KV | BDB_ST_PREFIX); } static VALUE bdb_each_riap(int argc, VALUE *argv, VALUE obj) { return bdb_each_kvc(argc, argv, obj, DB_PREV, Qfalse, BDB_ST_KV | BDB_ST_ONE); } static VALUE bdb_each_xiferp(int argc, VALUE *argv, VALUE obj) { return bdb_each_kvc(argc, argv, obj, DB_PREV, Qfalse, BDB_ST_KV | BDB_ST_ONE | BDB_ST_PREFIX); } static VALUE bdb_each_pair_prim(int argc, VALUE *argv, VALUE obj) { VALUE tmp[2] = {Qnil, Qtrue}; rb_scan_args(argc, argv, "01", tmp); return bdb_each_kvc(2, tmp, obj, DB_NEXT, Qfalse, BDB_ST_KV); } static VALUE bdb_each_riap_prim(int argc, VALUE *argv, VALUE obj) { VALUE tmp[2] = {Qnil, Qtrue}; rb_scan_args(argc, argv, "01", tmp); return bdb_each_kvc(2, tmp, obj, DB_PREV, Qfalse, BDB_ST_KV); } VALUE bdb_to_type(obj, result, flag) VALUE obj, result, flag; { bdb_DB *dbst; DB_TXN *txnid; DBC *dbcp; DBT key, data; int ret, flags; db_recno_t recno; INIT_TXN(txnid, obj, dbst); #if HAVE_DB_CURSOR_4 bdb_test_error(dbst->dbp->cursor(dbst->dbp, txnid, &dbcp, 0)); #else bdb_test_error(dbst->dbp->cursor(dbst->dbp, txnid, &dbcp)); #endif flags = ((flag == Qnil)?DB_PREV:DB_NEXT) | TEST_INIT_LOCK(dbst); do { MEMZERO(&key, DBT, 1); INIT_RECNO(dbst, key, recno); MEMZERO(&data, DBT, 1); data.flags = DB_DBT_MALLOC; SET_PARTIAL(dbst, data); bdb_cache_error(dbcp->c_get(dbcp, &key, &data, flags), dbcp->c_close(dbcp), ret); if (ret == DB_NOTFOUND) { dbcp->c_close(dbcp); return result; } if (ret == DB_KEYEMPTY) continue; switch (TYPE(result)) { case T_ARRAY: if (flag == Qtrue) { rb_ary_push(result, bdb_assoc(obj, &key, &data)); } else { rb_ary_push(result, bdb_test_load(obj, &data, FILTER_VALUE)); } break; case T_HASH: if (flag == Qtrue) { rb_hash_aset(result, bdb_test_load_key(obj, &key), bdb_test_load(obj, &data, FILTER_VALUE)); } else { rb_hash_aset(result, bdb_test_load(obj, &data, FILTER_VALUE), bdb_test_load_key(obj, &key)); } } } while (1); return result; } static VALUE bdb_to_a(obj) VALUE obj; { return bdb_to_type(obj, rb_ary_new(), Qtrue); } static VALUE bdb_update_i(pair, obj) VALUE pair, obj; { Check_Type(pair, T_ARRAY); if (RARRAY_LEN(pair) < 2) { rb_raise(rb_eArgError, "pair must be [key, value]"); } bdb_put(2, RARRAY_PTR(pair), obj); return Qnil; } static VALUE each_pair(obj) VALUE obj; { return rb_funcall(obj, rb_intern("each_pair"), 0, 0); } static VALUE bdb_update(obj, other) VALUE obj, other; { rb_iterate(each_pair, other, bdb_update_i, obj); return obj; } VALUE bdb_clear(int argc, VALUE *argv, VALUE obj) { #if HAVE_ST_DB_TRUNCATE bdb_DB *dbst; DB_TXN *txnid; unsigned int count = 0; #endif int flags = 0; rb_secure(4); #if HAVE_ST_DB_TRUNCATE INIT_TXN(txnid, obj, dbst); #if HAVE_CONST_DB_AUTO_COMMIT if (txnid == NULL && (dbst->options & BDB_AUTO_COMMIT)) { flags |= DB_AUTO_COMMIT; } #endif bdb_test_error(dbst->dbp->truncate(dbst->dbp, txnid, &count, flags)); return INT2NUM(count); #else flags = 0; if (argc && TYPE(argv[argc - 1]) == T_HASH) { VALUE g, f = argv[argc - 1]; if ((g = rb_hash_aref(f, rb_intern("flags"))) != RHASH(f)->ifnone || (g = rb_hash_aref(f, rb_str_new2("flags"))) != RHASH(f)->ifnone) { flags = NUM2INT(g); } argc--; } if (argc) { flags = NUM2INT(argv[0]); } return bdb_lgth_intern(obj, Qtrue, flags); #endif } static VALUE bdb_replace(int argc, VALUE *argv, VALUE obj) { VALUE g; int flags; if (argc == 0 || argc > 2) { rb_raise(rb_eArgError, "invalid number of arguments (0 for 1)"); } flags = 0; if (TYPE(argv[argc - 1]) == T_HASH) { VALUE f = argv[argc - 1]; if ((g = rb_hash_aref(f, rb_intern("flags"))) != RHASH(f)->ifnone || (g = rb_hash_aref(f, rb_str_new2("flags"))) != RHASH(f)->ifnone) { flags = NUM2INT(g); } argc--; } if (argc == 2) { flags = NUM2INT(argv[1]); } g = INT2FIX(flags); bdb_clear(1, &g, obj); rb_iterate(each_pair, argv[0], bdb_update_i, obj); return obj; } static VALUE bdb_invert(obj) VALUE obj; { return bdb_to_type(obj, rb_hash_new(), Qfalse); } static VALUE bdb_to_hash(obj) VALUE obj; { return bdb_to_type(obj, rb_hash_new(), Qtrue); } static VALUE bdb_kv(obj, type) VALUE obj; int type; { bdb_DB *dbst; DB_TXN *txnid; DBC *dbcp; DBT key, data; int ret, flags; db_recno_t recno; VALUE ary; ary = rb_ary_new(); INIT_TXN(txnid, obj, dbst); #if HAVE_DB_CURSOR_4 bdb_test_error(dbst->dbp->cursor(dbst->dbp, txnid, &dbcp, 0)); #else bdb_test_error(dbst->dbp->cursor(dbst->dbp, txnid, &dbcp)); #endif flags = DB_NEXT | TEST_INIT_LOCK(dbst); do { MEMZERO(&key, DBT, 1); INIT_RECNO(dbst, key, recno); MEMZERO(&data, DBT, 1); data.flags = DB_DBT_MALLOC; SET_PARTIAL(dbst, data); bdb_cache_error(dbcp->c_get(dbcp, &key, &data, flags), dbcp->c_close(dbcp), ret); if (ret == DB_NOTFOUND) { dbcp->c_close(dbcp); return ary; } if (ret == DB_KEYEMPTY) continue; switch (type) { case BDB_ST_VALUE: FREE_KEY(dbst, key); rb_ary_push(ary, bdb_test_load(obj, &data, FILTER_VALUE)); break; case BDB_ST_KEY: free(data.data); rb_ary_push(ary, bdb_test_load_key(obj, &key)); break; } } while (1); return ary; } static VALUE bdb_values(obj) VALUE obj; { return bdb_kv(obj, BDB_ST_VALUE); } static VALUE bdb_keys(obj) VALUE obj; { return bdb_kv(obj, BDB_ST_KEY); } VALUE bdb_internal_value(obj, a, b, sens) VALUE obj, a, b; int sens; { bdb_DB *dbst; DB_TXN *txnid; DBC *dbcp; DBT key, data; int ret, flags; db_recno_t recno; INIT_TXN(txnid, obj, dbst); MEMZERO(&key, DBT, 1); INIT_RECNO(dbst, key, recno); #if HAVE_DB_CURSOR_4 bdb_test_error(dbst->dbp->cursor(dbst->dbp, txnid, &dbcp, 0)); #else bdb_test_error(dbst->dbp->cursor(dbst->dbp, txnid, &dbcp)); #endif flags = sens | TEST_INIT_LOCK(dbst); do { MEMZERO(&data, DBT, 1); data.flags = DB_DBT_MALLOC; SET_PARTIAL(dbst, data); bdb_cache_error(dbcp->c_get(dbcp, &key, &data, flags), dbcp->c_close(dbcp), ret); if (ret == DB_NOTFOUND) { dbcp->c_close(dbcp); return (b == Qfalse)?Qfalse:Qnil; } if (ret == DB_KEYEMPTY) continue; if (rb_equal(a, bdb_test_load(obj, &data, FILTER_VALUE)) == Qtrue) { VALUE d; dbcp->c_close(dbcp); if (b == Qfalse) { d = Qtrue; FREE_KEY(dbst, key); } else { d = bdb_test_load_key(obj, &key); } return d; } FREE_KEY(dbst, key); } while (1); return (b == Qfalse)?Qfalse:Qnil; } VALUE bdb_index(obj, a) VALUE obj, a; { return bdb_internal_value(obj, a, Qtrue, DB_NEXT); } static VALUE bdb_indexes(int argc, VALUE *argv, VALUE obj) { VALUE indexes; int i; #if HAVE_RB_ARY_VALUES_AT rb_warn("Common#%s is deprecated; use Common#values_at", #if HAVE_RB_FRAME_THIS_FUNC rb_id2name(rb_frame_this_func()) #else rb_id2name(rb_frame_last_func()) #endif ); #endif indexes = rb_ary_new2(argc); for (i = 0; i < argc; i++) { rb_ary_push(indexes, bdb_get(1, &argv[i], obj)); } return indexes; } static VALUE bdb_values_at(int argc, VALUE *argv, VALUE obj) { VALUE result = rb_ary_new2(argc); long i; for (i = 0; i < argc; i++) { rb_ary_push(result, bdb_get(1, &argv[i], obj)); } return result; } static VALUE bdb_select(int argc, VALUE *argv, VALUE obj) { VALUE result = rb_ary_new(); if (rb_block_given_p()) { if (argc > 0) { rb_raise(rb_eArgError, "wrong number arguments(%d for 0)", argc); } return bdb_each_kvc(argc, argv, obj, DB_NEXT, result, BDB_ST_SELECT); } rb_warn("Common#select(index..) is deprecated; use Common#values_at"); return bdb_values_at(argc, argv, obj); } VALUE bdb_has_value(obj, a) VALUE obj, a; { return bdb_internal_value(obj, a, Qfalse, DB_NEXT); } static VALUE bdb_sync(obj) VALUE obj; { bdb_DB *dbst; if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4) rb_raise(rb_eSecurityError, "Insecure: can't sync the database"); GetDB(obj, dbst); bdb_test_error(dbst->dbp->sync(dbst->dbp, 0)); return Qtrue; } #if HAVE_TYPE_DB_HASH_STAT static VALUE bdb_hash_stat(int argc, VALUE *argv, VALUE obj) { bdb_DB *dbst; DB_HASH_STAT *bdb_stat; VALUE hash, flagv; int flags = 0; #if HAVE_DB_STAT_4_TXN DB_TXN *txnid = NULL; #endif if (rb_scan_args(argc, argv, "01", &flagv) == 1) { flags = NUM2INT(flagv); } GetDB(obj, dbst); #if HAVE_DB_STAT_4 #if HAVE_DB_STAT_4_TXN if (RTEST(dbst->txn)) { bdb_TXN *txnst; GetTxnDB(dbst->txn, txnst); txnid = txnst->txnid; } bdb_test_error(dbst->dbp->stat(dbst->dbp, txnid, &bdb_stat, flags)); #else bdb_test_error(dbst->dbp->stat(dbst->dbp, &bdb_stat, 0, flags)); #endif #else bdb_test_error(dbst->dbp->stat(dbst->dbp, &bdb_stat, flags)); #endif hash = rb_hash_new(); rb_hash_aset(hash, rb_tainted_str_new2("hash_magic"), INT2NUM(bdb_stat->hash_magic)); rb_hash_aset(hash, rb_tainted_str_new2("hash_version"), INT2NUM(bdb_stat->hash_version)); rb_hash_aset(hash, rb_tainted_str_new2("hash_pagesize"), INT2NUM(bdb_stat->hash_pagesize)); #if HAVE_ST_DB_HASH_STAT_HASH_NKEYS rb_hash_aset(hash, rb_tainted_str_new2("hash_nkeys"), INT2NUM(bdb_stat->hash_nkeys)); #if ! HAVE_ST_DB_HASH_STAT_HASH_NRECS rb_hash_aset(hash, rb_tainted_str_new2("hash_nrecs"), INT2NUM(bdb_stat->hash_nkeys)); #endif #endif #if HAVE_ST_DB_HASH_STAT_HASH_NRECS rb_hash_aset(hash, rb_tainted_str_new2("hash_nrecs"), INT2NUM(bdb_stat->hash_nrecs)); #endif #if HAVE_ST_DB_HASH_STAT_HASH_NDATA rb_hash_aset(hash, rb_tainted_str_new2("hash_ndata"), INT2NUM(bdb_stat->hash_ndata)); #endif #if HAVE_ST_DB_HASH_STAT_HASH_NELEM rb_hash_aset(hash, rb_tainted_str_new2("hash_nelem"), INT2NUM(bdb_stat->hash_nelem)); #endif rb_hash_aset(hash, rb_tainted_str_new2("hash_ffactor"), INT2NUM(bdb_stat->hash_ffactor)); rb_hash_aset(hash, rb_tainted_str_new2("hash_buckets"), INT2NUM(bdb_stat->hash_buckets)); rb_hash_aset(hash, rb_tainted_str_new2("hash_free"), INT2NUM(bdb_stat->hash_free)); rb_hash_aset(hash, rb_tainted_str_new2("hash_bfree"), INT2NUM(bdb_stat->hash_bfree)); rb_hash_aset(hash, rb_tainted_str_new2("hash_bigpages"), INT2NUM(bdb_stat->hash_bigpages)); rb_hash_aset(hash, rb_tainted_str_new2("hash_big_bfree"), INT2NUM(bdb_stat->hash_big_bfree)); rb_hash_aset(hash, rb_tainted_str_new2("hash_overflows"), INT2NUM(bdb_stat->hash_overflows)); rb_hash_aset(hash, rb_tainted_str_new2("hash_ovfl_free"), INT2NUM(bdb_stat->hash_ovfl_free)); rb_hash_aset(hash, rb_tainted_str_new2("hash_dup"), INT2NUM(bdb_stat->hash_dup)); rb_hash_aset(hash, rb_tainted_str_new2("hash_dup_free"), INT2NUM(bdb_stat->hash_dup_free)); #if HAVE_ST_DB_HASH_STAT_HASH_PAGECNT rb_hash_aset(hash, rb_tainted_str_new2("hash_pagecnt"), INT2NUM(bdb_stat->hash_pagecnt)); #endif free(bdb_stat); return hash; } #endif VALUE bdb_tree_stat(int argc, VALUE *argv, VALUE obj) { bdb_DB *dbst; DB_BTREE_STAT *bdb_stat; VALUE hash, flagv; char pad; int flags = 0; #if HAVE_DB_STAT_4_TXN DB_TXN *txnid = NULL; #endif if (rb_scan_args(argc, argv, "01", &flagv) == 1) { flags = NUM2INT(flagv); } GetDB(obj, dbst); #if HAVE_DB_STAT_4 #if HAVE_DB_STAT_4_TXN if (RTEST(dbst->txn)) { bdb_TXN *txnst; GetTxnDB(dbst->txn, txnst); txnid = txnst->txnid; } bdb_test_error(dbst->dbp->stat(dbst->dbp, txnid, &bdb_stat, flags)); #else bdb_test_error(dbst->dbp->stat(dbst->dbp, &bdb_stat, 0, flags)); #endif #else bdb_test_error(dbst->dbp->stat(dbst->dbp, &bdb_stat, flags)); #endif hash = rb_hash_new(); rb_hash_aset(hash, rb_tainted_str_new2("bt_magic"), INT2NUM(bdb_stat->bt_magic)); rb_hash_aset(hash, rb_tainted_str_new2("bt_version"), INT2NUM(bdb_stat->bt_version)); rb_hash_aset(hash, rb_tainted_str_new2("bt_dup_pg"), INT2NUM(bdb_stat->bt_dup_pg)); rb_hash_aset(hash, rb_tainted_str_new2("bt_dup_pgfree"), INT2NUM(bdb_stat->bt_dup_pgfree)); rb_hash_aset(hash, rb_tainted_str_new2("bt_free"), INT2NUM(bdb_stat->bt_free)); rb_hash_aset(hash, rb_tainted_str_new2("bt_int_pg"), INT2NUM(bdb_stat->bt_int_pg)); rb_hash_aset(hash, rb_tainted_str_new2("bt_int_pgfree"), INT2NUM(bdb_stat->bt_int_pgfree)); rb_hash_aset(hash, rb_tainted_str_new2("bt_leaf_pg"), INT2NUM(bdb_stat->bt_leaf_pg)); rb_hash_aset(hash, rb_tainted_str_new2("bt_leaf_pgfree"), INT2NUM(bdb_stat->bt_leaf_pgfree)); rb_hash_aset(hash, rb_tainted_str_new2("bt_levels"), INT2NUM(bdb_stat->bt_levels)); rb_hash_aset(hash, rb_tainted_str_new2("bt_minkey"), INT2NUM(bdb_stat->bt_minkey)); #if HAVE_ST_DB_BTREE_STAT_BT_NRECS rb_hash_aset(hash, rb_tainted_str_new2("bt_nrecs"), INT2NUM(bdb_stat->bt_nrecs)); #endif #if HAVE_ST_DB_BTREE_STAT_BT_NKEYS rb_hash_aset(hash, rb_tainted_str_new2("bt_nkeys"), INT2NUM(bdb_stat->bt_nkeys)); #if ! HAVE_ST_DB_BTREE_STAT_BT_NRECS rb_hash_aset(hash, rb_tainted_str_new2("bt_nrecs"), INT2NUM(bdb_stat->bt_nkeys)); #endif #endif #if HAVE_ST_DB_BTREE_STAT_BT_NDATA rb_hash_aset(hash, rb_tainted_str_new2("bt_ndata"), INT2NUM(bdb_stat->bt_ndata)); #endif rb_hash_aset(hash, rb_tainted_str_new2("bt_over_pg"), INT2NUM(bdb_stat->bt_over_pg)); rb_hash_aset(hash, rb_tainted_str_new2("bt_over_pgfree"), INT2NUM(bdb_stat->bt_over_pgfree)); rb_hash_aset(hash, rb_tainted_str_new2("bt_pagesize"), INT2NUM(bdb_stat->bt_pagesize)); rb_hash_aset(hash, rb_tainted_str_new2("bt_re_len"), INT2NUM(bdb_stat->bt_re_len)); pad = (char)bdb_stat->bt_re_pad; rb_hash_aset(hash, rb_tainted_str_new2("bt_re_pad"), rb_tainted_str_new(&pad, 1)); #if HAVE_ST_DB_BTREE_STAT_BT_PAGECNT rb_hash_aset(hash, rb_tainted_str_new2("bt_pagecnt"), INT2NUM(bdb_stat->bt_pagecnt)); #endif free(bdb_stat); return hash; } #if HAVE_TYPE_DB_QUEUE_STAT static VALUE bdb_queue_stat(int argc, VALUE *argv, VALUE obj) { bdb_DB *dbst; DB_QUEUE_STAT *bdb_stat; VALUE hash, flagv; char pad; int flags = 0; #if HAVE_DB_STAT_4_TXN DB_TXN *txnid = NULL; #endif if (rb_scan_args(argc, argv, "01", &flagv) == 1) { flags = NUM2INT(flagv); } GetDB(obj, dbst); #if HAVE_DB_STAT_4 #if HAVE_DB_STAT_4_TXN if (RTEST(dbst->txn)) { bdb_TXN *txnst; GetTxnDB(dbst->txn, txnst); txnid = txnst->txnid; } bdb_test_error(dbst->dbp->stat(dbst->dbp, txnid, &bdb_stat, flags)); #else bdb_test_error(dbst->dbp->stat(dbst->dbp, &bdb_stat, 0, flags)); #endif #else bdb_test_error(dbst->dbp->stat(dbst->dbp, &bdb_stat, flags)); #endif hash = rb_hash_new(); rb_hash_aset(hash, rb_tainted_str_new2("qs_magic"), INT2NUM(bdb_stat->qs_magic)); rb_hash_aset(hash, rb_tainted_str_new2("qs_version"), INT2NUM(bdb_stat->qs_version)); #if HAVE_ST_DB_QUEUE_STAT_QS_NKEYS rb_hash_aset(hash, rb_tainted_str_new2("qs_nkeys"), INT2NUM(bdb_stat->qs_nkeys)); #if ! HAVE_ST_DB_QUEUE_STAT_QS_NRECS rb_hash_aset(hash, rb_tainted_str_new2("qs_nrecs"), INT2NUM(bdb_stat->qs_nkeys)); #endif #endif #if HAVE_ST_DB_QUEUE_STAT_QS_NDATA rb_hash_aset(hash, rb_tainted_str_new2("qs_ndata"), INT2NUM(bdb_stat->qs_ndata)); #endif #if HAVE_ST_DB_QUEUE_STAT_QS_NRECS rb_hash_aset(hash, rb_tainted_str_new2("qs_nrecs"), INT2NUM(bdb_stat->qs_nrecs)); #endif rb_hash_aset(hash, rb_tainted_str_new2("qs_pages"), INT2NUM(bdb_stat->qs_pages)); rb_hash_aset(hash, rb_tainted_str_new2("qs_pagesize"), INT2NUM(bdb_stat->qs_pagesize)); rb_hash_aset(hash, rb_tainted_str_new2("qs_pgfree"), INT2NUM(bdb_stat->qs_pgfree)); rb_hash_aset(hash, rb_tainted_str_new2("qs_re_len"), INT2NUM(bdb_stat->qs_re_len)); pad = (char)bdb_stat->qs_re_pad; rb_hash_aset(hash, rb_tainted_str_new2("qs_re_pad"), rb_tainted_str_new(&pad, 1)); #if HAVE_ST_DB_QUEUE_STAT_QS_START rb_hash_aset(hash, rb_tainted_str_new2("qs_start"), INT2NUM(bdb_stat->qs_start)); #endif rb_hash_aset(hash, rb_tainted_str_new2("qs_first_recno"), INT2NUM(bdb_stat->qs_first_recno)); rb_hash_aset(hash, rb_tainted_str_new2("qs_cur_recno"), INT2NUM(bdb_stat->qs_cur_recno)); free(bdb_stat); return hash; } static VALUE bdb_queue_padlen(obj) VALUE obj; { bdb_DB *dbst; DB_QUEUE_STAT *bdb_stat; VALUE hash; char pad; #if HAVE_DB_STAT_4_TXN DB_TXN *txnid = NULL; #endif GetDB(obj, dbst); #if HAVE_DB_STAT_4 #if HAVE_DB_STAT_4_TXN if (RTEST(dbst->txn)) { bdb_TXN *txnst; GetTxnDB(dbst->txn, txnst); txnid = txnst->txnid; } bdb_test_error(dbst->dbp->stat(dbst->dbp, txnid, &bdb_stat, 0)); #else bdb_test_error(dbst->dbp->stat(dbst->dbp, &bdb_stat, 0, 0)); #endif #else bdb_test_error(dbst->dbp->stat(dbst->dbp, &bdb_stat, 0)); #endif pad = (char)bdb_stat->qs_re_pad; hash = rb_assoc_new(rb_tainted_str_new(&pad, 1), INT2NUM(bdb_stat->qs_re_len)); free(bdb_stat); return hash; } #endif static VALUE bdb_set_partial(obj, a, b) VALUE obj, a, b; { bdb_DB *dbst; VALUE ret; GetDB(obj, dbst); if (dbst->marshal) { rb_raise(bdb_eFatal, "set_partial is not implemented with Marshal"); } ret = rb_ary_new2(3); rb_ary_push(ret, (dbst->partial == DB_DBT_PARTIAL)?Qtrue:Qfalse); rb_ary_push(ret, INT2NUM(dbst->doff)); rb_ary_push(ret, INT2NUM(dbst->dlen)); dbst->doff = NUM2UINT(a); dbst->dlen = NUM2UINT(b); dbst->partial = DB_DBT_PARTIAL; return ret; } static VALUE bdb_clear_partial(obj) VALUE obj; { bdb_DB *dbst; VALUE ret; GetDB(obj, dbst); if (dbst->marshal) { rb_raise(bdb_eFatal, "set_partial is not implemented with Marshal"); } ret = rb_ary_new2(3); rb_ary_push(ret, (dbst->partial == DB_DBT_PARTIAL)?Qtrue:Qfalse); rb_ary_push(ret, INT2NUM(dbst->doff)); rb_ary_push(ret, INT2NUM(dbst->dlen)); dbst->doff = dbst->dlen = dbst->partial = 0; return ret; } #if HAVE_ST_DB_SET_ERRCALL static VALUE bdb_i_create(obj) VALUE obj; { DB *dbp; bdb_ENV *envst = 0; DB_ENV *envp; bdb_DB *dbst; VALUE ret, env; envp = NULL; env = 0; if (rb_obj_is_kind_of(obj, bdb_cEnv)) { GetEnvDB(obj, envst); envp = envst->envp; env = obj; } bdb_test_error(db_create(&dbp, envp, 0)); dbp->set_errpfx(dbp, "BDB::"); dbp->set_errcall(dbp, bdb_env_errcall); ret = Data_Make_Struct(bdb_cCommon, bdb_DB, bdb_mark, bdb_free, dbst); rb_obj_call_init(ret, 0, 0); dbst->env = env; dbst->dbp = dbp; if (envp) { dbst->options |= envst->options & BDB_INIT_LOCK; } return ret; } #endif static VALUE bdb_s_upgrade(int argc, VALUE *argv, VALUE obj) { #if HAVE_ST_DB_UPGRADE bdb_DB *dbst; VALUE a, b; int flags; VALUE val; rb_secure(4); flags = 0; if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { flags = NUM2INT(b); } SafeStringValue(a); val = bdb_i_create(obj); GetDB(val, dbst); bdb_test_error(dbst->dbp->upgrade(dbst->dbp, StringValuePtr(a), flags)); return val; #else rb_raise(bdb_eFatal, "You can't upgrade a database with this version of DB"); #endif } #if HAVE_ST_DB_REMOVE static VALUE bdb_s_remove(int argc, VALUE *argv, VALUE obj) { bdb_DB *dbst; VALUE a, b, c; char *name, *subname; rb_secure(2); c = bdb_i_create(obj); GetDB(c, dbst); name = subname = NULL; a = b = Qnil; if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { if (!NIL_P(b)) { SafeStringValue(b); subname = StringValuePtr(b); } } SafeStringValue(a); name = StringValuePtr(a); bdb_test_error(dbst->dbp->remove(dbst->dbp, name, subname, 0)); return Qtrue; } #endif #if HAVE_ST_DB_RENAME static VALUE bdb_s_rename(int argc, VALUE *argv, VALUE obj) { bdb_DB *dbst; VALUE a, b, c; char *name, *subname, *newname; rb_secure(2); c = bdb_i_create(obj); GetDB(c, dbst); name = subname = NULL; a = b = c = Qnil; rb_scan_args(argc, argv, "30", &a, &b, &c); if (!NIL_P(b)) { SafeStringValue(b); subname = StringValuePtr(b); } SafeStringValue(a); SafeStringValue(c); name = StringValuePtr(a); newname = StringValuePtr(c); bdb_test_error(dbst->dbp->rename(dbst->dbp, name, subname, newname, 0)); return Qtrue; } #endif #if HAVE_ST_DB_JOIN static VALUE bdb_i_joinclose(st) eachst *st; { bdb_DB *dbst; GetDB(st->db, dbst); if (st->dbcp && dbst && dbst->dbp) { st->dbcp->c_close(st->dbcp); } return Qnil; } static VALUE bdb_i_join(st) eachst *st; { int ret; DBT key, data; db_recno_t recno; bdb_DB *dbst; GetDB(st->db, dbst); MEMZERO(&key, DBT, 1); INIT_RECNO(dbst, key, recno); do { MEMZERO(&data, DBT, 1); data.flags |= DB_DBT_MALLOC; SET_PARTIAL(dbst, data); ret = bdb_test_error(st->dbcp->c_get(st->dbcp, &key, &data, st->sens)); if (ret == DB_NOTFOUND || ret == DB_KEYEMPTY) return Qnil; rb_yield(bdb_assoc(st->db, &key, &data)); } while (1); return Qnil; } static VALUE bdb_join(int argc, VALUE *argv, VALUE obj) { bdb_DB *dbst; bdb_DBC *dbcst; DBC *dbc, **dbcarr; int flags, i; eachst st; VALUE a, b, c; c = 0; flags = 0; GetDB(obj, dbst); if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { flags = NUM2INT(b); } if (TYPE(a) != T_ARRAY) { rb_raise(bdb_eFatal, "first argument must an array of cursors"); } if (RARRAY_LEN(a) == 0) { rb_raise(bdb_eFatal, "empty array"); } dbcarr = ALLOCA_N(DBC *, RARRAY_LEN(a) + 1); { DBC **dbs; bdb_DB *tmp; for (dbs = dbcarr, i = 0; i < RARRAY_LEN(a); i++, dbs++) { if (!rb_obj_is_kind_of(RARRAY_PTR(a)[i], bdb_cCursor)) { rb_raise(bdb_eFatal, "element %d is not a cursor", i); } GetCursorDB(RARRAY_PTR(a)[i], dbcst, tmp); *dbs = dbcst->dbc; } *dbs = 0; } dbc = 0; #if HAVE_TYPE_DB_INFO bdb_test_error(dbst->dbp->join(dbst->dbp, dbcarr, 0, &dbc)); #else bdb_test_error(dbst->dbp->join(dbst->dbp, dbcarr, &dbc, 0)); #endif st.db = obj; st.dbcp = dbc; st.sens = flags | TEST_INIT_LOCK(dbst); rb_ensure(bdb_i_join, (VALUE)&st, bdb_i_joinclose, (VALUE)&st); return obj; } #endif #if HAVE_ST_DB_BYTESWAPPED || HAVE_ST_DB_GET_BYTESWAPPED static VALUE bdb_byteswapp(obj) VALUE obj; { bdb_DB *dbst; int byteswap = 0; GetDB(obj, dbst); #if HAVE_ST_DB_BYTESWAPPED return dbst->dbp->byteswapped?Qtrue:Qfalse; #elif HAVE_DB_GET_BYTESWAPPED_2 dbst->dbp->get_byteswapped(dbst->dbp, &byteswap); return byteswap?Qtrue:Qfalse; #else return dbst->dbp->get_byteswapped(dbst->dbp)?Qtrue:Qfalse; #endif } #endif #if HAVE_ST_DB_ASSOCIATE static VALUE bdb_internal_second_call(tmp) VALUE *tmp; { return rb_funcall2(tmp[0], bdb_id_call, 3, tmp + 1); } static int bdb_call_secondary(secst, pkey, pdata, skey) DB *secst; DBT *pkey; DBT *pdata; DBT *skey; { VALUE obj, ary, second; bdb_DB *dbst, *secondst; VALUE result = Qnil; int i, inter; GetIdDb(obj, dbst); if (!dbst->dbp || !RTEST(dbst->secondary)) return DB_DONOTINDEX; for (i = 0; i < RARRAY_LEN(dbst->secondary); i++) { ary = RARRAY_PTR(dbst->secondary)[i]; if (RARRAY_LEN(ary) != 2) continue; second = RARRAY_PTR(ary)[0]; Data_Get_Struct(second, bdb_DB, secondst); if (!secondst->dbp) continue; if (secondst->dbp == secst) { VALUE tmp[4]; tmp[0] = RARRAY_PTR(ary)[1]; tmp[1] = second; tmp[2] = bdb_test_load_key(obj, pkey); tmp[3] = bdb_test_load(obj, pdata, FILTER_VALUE|FILTER_FREE); inter = 0; result = rb_protect(bdb_internal_second_call, (VALUE)tmp, &inter); if (inter) return BDB_ERROR_PRIVATE; if (result == Qfalse) return DB_DONOTINDEX; MEMZERO(skey, DBT, 1); if (result == Qtrue) { skey->data = pkey->data; skey->size = pkey->size; } else { DBT stmp; MEMZERO(&stmp, DBT, 1); result = bdb_test_dump(second, &stmp, result, FILTER_KEY); skey->data = stmp.data; skey->size = stmp.size; } return 0; } } rb_gv_set("$!", rb_str_new2("secondary index not found ?")); return BDB_ERROR_PRIVATE; } static VALUE bdb_associate(int argc, VALUE *argv, VALUE obj) { bdb_DB *dbst, *secondst; VALUE second, flag; int flags = 0; if (!rb_block_given_p()) { rb_raise(bdb_eFatal, "call out of an iterator"); } if (rb_scan_args(argc, argv, "11", &second, &flag) == 2) { flags = NUM2INT(flag); } if (!rb_obj_is_kind_of(second, bdb_cCommon)) { rb_raise(bdb_eFatal, "associate expect a BDB object"); } GetDB(second, secondst); if (RTEST(secondst->secondary)) { rb_raise(bdb_eFatal, "associate with a primary index"); } GetDB(obj, dbst); dbst->options |= BDB_NEED_CURRENT; if (!dbst->secondary) { dbst->secondary = rb_ary_new(); } rb_thread_local_aset(rb_thread_current(), bdb_id_current_db, obj); #if HAVE_RB_BLOCK_PROC rb_ary_push(dbst->secondary, rb_assoc_new(second, rb_block_proc())); #else rb_ary_push(dbst->secondary, rb_assoc_new(second, rb_f_lambda())); #endif secondst->secondary = Qnil; #if HAVE_DB_ASSOCIATE_TXN { DB_TXN *txnid = NULL; if (RTEST(dbst->txn)) { bdb_TXN *txnst; GetTxnDB(dbst->txn, txnst); txnid = txnst->txnid; } #if HAVE_CONST_DB_AUTO_COMMIT else if (dbst->options & BDB_AUTO_COMMIT) { flags |= DB_AUTO_COMMIT; } #endif bdb_test_error(dbst->dbp->associate(dbst->dbp, txnid, secondst->dbp, bdb_call_secondary, flags)); } #else bdb_test_error(dbst->dbp->associate(dbst->dbp, secondst->dbp, bdb_call_secondary, flags)); #endif return obj; } #endif static VALUE bdb_filename(obj) VALUE obj; { bdb_DB *dbst; GetDB(obj, dbst); return dbst->filename; } static VALUE bdb_database(obj) VALUE obj; { bdb_DB *dbst; GetDB(obj, dbst); return dbst->database; } #if HAVE_ST_DB_VERIFY static VALUE bdb_verify(int argc, VALUE *argv, VALUE obj) { bdb_DB *dbst; char *file, *database; VALUE flagv = Qnil, iov = Qnil; int flags = 0; #if HAVE_TYPE_RB_IO_T rb_io_t *fptr; #else OpenFile *fptr; #endif FILE *io = NULL; rb_secure(4); file = database = NULL; switch(rb_scan_args(argc, argv, "02", &iov, &flagv)) { case 2: flags = NUM2INT(flagv); case 1: if (!NIL_P(iov)) { iov = rb_convert_type(iov, T_FILE, "IO", "to_io"); GetOpenFile(iov, fptr); rb_io_check_writable(fptr); #if HAVE_RB_IO_STDIO_FILE io = rb_io_stdio_file(fptr); #else io = GetWriteFile(fptr); #endif } break; case 0: break; } GetDB(obj, dbst); if (!NIL_P(dbst->filename)) { file = StringValuePtr(dbst->filename); } if (!NIL_P(dbst->database)) { database = StringValuePtr(dbst->database); } bdb_test_error(dbst->dbp->verify(dbst->dbp, file, database, io, flags)); return Qnil; } #endif static VALUE bdb__txn__dup(VALUE obj, VALUE a) { bdb_DB *dbp, *dbh; bdb_TXN *txnst; VALUE res; GetDB(obj, dbp); GetTxnDB(a, txnst); res = Data_Make_Struct(CLASS_OF(obj), bdb_DB, bdb_mark, bdb_free, dbh); MEMCPY(dbh, dbp, bdb_DB, 1); dbh->txn = a; dbh->orig = obj; dbh->ori_val = res; dbh->options |= (txnst->options & BDB_INIT_LOCK) | BDB_NOT_OPEN; return res; } static VALUE bdb__txn__close(VALUE obj, VALUE commit, VALUE real) { bdb_DB *dbst, *dbst1; if (!real) { Data_Get_Struct(obj, bdb_DB, dbst); dbst->dbp = NULL; } else { if (commit) { Data_Get_Struct(obj, bdb_DB, dbst); if (dbst->orig) { Data_Get_Struct(dbst->orig, bdb_DB, dbst1); dbst1->len = dbst->len; } } // bdb_close(0, 0, obj); } return Qnil; } #if HAVE_ST_DB_SET_CACHE_PRIORITY static VALUE bdb_cache_priority_set(VALUE obj, VALUE a) { int priority; bdb_DB *dbst; GetDB(obj, dbst); priority = dbst->priority; bdb_test_error(dbst->dbp->set_cache_priority(dbst->dbp, NUM2INT(a))); dbst->priority = NUM2INT(a); return INT2FIX(priority); } static VALUE bdb_cache_priority_get(VALUE obj) { bdb_DB *dbst; GetDB(obj, dbst); return INT2FIX(dbst->priority); } #endif #if HAVE_ST_DB_SET_FEEDBACK static VALUE bdb_feedback_set(VALUE obj, VALUE a) { bdb_DB *dbst; GetDB(obj, dbst); if (NIL_P(a)) { dbst->feedback = a; } else { if (!rb_respond_to(a, bdb_id_call)) { rb_raise(bdb_eFatal, "arg must respond to #call"); } dbst->feedback = a; if (!(dbst->options & BDB_FEEDBACK)) { dbst->options |= BDB_FEEDBACK; rb_thread_local_aset(rb_thread_current(), bdb_id_current_db, obj); } } return a; } #endif static VALUE bdb_i_conf(obj, a) VALUE obj, a; { bdb_DB *dbst; u_int32_t value; #if HAVE_ST_DB_GET_CACHESIZE u_int32_t bytes, gbytes; int ncache; #endif #if HAVE_ST_DB_GET_RE_PAD || HAVE_ST_DB_GET_LORDER || HAVE_ST_DB_GET_RE_DELIM int intval; #endif #if HAVE_ST_DB_GET_DBNAME const char *filename, *dbname; #endif const char *str; GetDB(obj, dbst); str = StringValuePtr(a); #if HAVE_ST_DB_GET_BT_MINKEY if (strcmp(str, "bt_minkey") == 0) { bdb_test_error(dbst->dbp->get_bt_minkey(dbst->dbp, &value)); return INT2NUM(value); } #endif #if HAVE_ST_DB_GET_CACHESIZE if (strcmp(str, "cachesize") == 0) { VALUE res; bdb_test_error(dbst->dbp->get_cachesize(dbst->dbp, &gbytes, &bytes, &ncache)); res = rb_ary_new2(3); rb_ary_push(res, INT2NUM(gbytes)); rb_ary_push(res, INT2NUM(bytes)); rb_ary_push(res, INT2NUM(ncache)); return res; } #endif #if HAVE_ST_DB_GET_DBNAME if (strcmp(str, "dbname") == 0) { VALUE res; bdb_test_error(dbst->dbp->get_dbname(dbst->dbp, &filename, &dbname)); res = rb_ary_new2(3); if (filename && strlen(filename)) { rb_ary_push(res, rb_tainted_str_new2(filename)); } else { rb_ary_push(res, Qnil); } if (dbname && strlen(dbname)) { rb_ary_push(res, rb_tainted_str_new2(dbname)); } else { rb_ary_push(res, Qnil); } return res; } #endif #if HAVE_ST_DB_GET_ENV if (strcmp(str, "env") == 0) { return bdb_env(obj); } #endif #if HAVE_ST_DB_GET_H_FFACTOR if (strcmp(str, "h_ffactor") == 0) { bdb_test_error(dbst->dbp->get_h_ffactor(dbst->dbp, &value)); return INT2NUM(value); } #endif #if HAVE_ST_DB_GET_H_NELEM if (strcmp(str, "h_nelem") == 0) { bdb_test_error(dbst->dbp->get_h_nelem(dbst->dbp, &value)); return INT2NUM(value); } #endif #if HAVE_ST_DB_GET_LORDER if (strcmp(str, "lorder") == 0) { bdb_test_error(dbst->dbp->get_lorder(dbst->dbp, &intval)); return INT2NUM(intval); } #endif #if HAVE_ST_DB_GET_PAGESIZE if (strcmp(str, "pagesize") == 0) { bdb_test_error(dbst->dbp->get_pagesize(dbst->dbp, &value)); return INT2NUM(value); } #endif #if HAVE_ST_DB_GET_Q_EXTENTSIZE if (strcmp(str, "q_extentsize") == 0) { bdb_test_error(dbst->dbp->get_q_extentsize(dbst->dbp, &value)); return INT2NUM(value); } #endif #if HAVE_ST_DB_GET_RE_DELIM if (strcmp(str, "re_delim") == 0) { bdb_test_error(dbst->dbp->get_re_delim(dbst->dbp, &intval)); return INT2NUM(intval); } #endif #if HAVE_ST_DB_GET_RE_LEN if (strcmp(str, "re_len") == 0) { bdb_test_error(dbst->dbp->get_re_len(dbst->dbp, &value)); return INT2NUM(value); } #endif #if HAVE_ST_DB_GET_RE_PAD if (strcmp(str, "re_pad") == 0) { bdb_test_error(dbst->dbp->get_re_pad(dbst->dbp, &intval)); return INT2NUM(intval); } #endif #if HAVE_ST_DB_GET_RE_SOURCE if (strcmp(str, "re_source") == 0) { const char *strval; bdb_test_error(dbst->dbp->get_re_source(dbst->dbp, &strval)); if (strval && strlen(strval)) { return rb_tainted_str_new2(strval); } return Qnil; } #endif #if HAVE_ST_DB_GET_FLAGS if (strcmp(str, "flags") == 0) { bdb_test_error(dbst->dbp->get_flags(dbst->dbp, &value)); return INT2NUM(value); } #endif #if HAVE_ST_DB_GET_OPEN_FLAGS if (strcmp(str, "open_flags") == 0) { bdb_test_error(dbst->dbp->get_open_flags(dbst->dbp, &value)); return INT2NUM(value); } #endif rb_raise(rb_eArgError, "Unknown option %s", str); return obj; } static char * options[] = { #if HAVE_ST_DB_GET_BT_MINKEY "bt_minkey", #endif #if HAVE_ST_DB_GET_CACHESIZE "cachesize", #endif #if HAVE_ST_DB_GET_DBNAME "dbname", #endif #if HAVE_ST_DB_GET_ENV "env", #endif #if HAVE_ST_DB_GET_H_FFACTOR "h_ffactor", #endif #if HAVE_ST_DB_GET_H_NELEM "h_nelem", #endif #if HAVE_ST_DB_GET_LORDER "lorder", #endif #if HAVE_ST_DB_GET_PAGESIZE "pagesize", #endif #if HAVE_ST_DB_GET_Q_EXTENTSIZE "q_extentsize", #endif #if HAVE_ST_DB_GET_RE_DELIM "re_delim", #endif #if HAVE_ST_DB_GET_RE_LEN "re_len", #endif #if HAVE_ST_DB_GET_RE_PAD "re_pad", #endif #if HAVE_ST_DB_GET_RE_SOURCE "re_source", #endif #if HAVE_ST_DB_GET_FLAGS "flags", #endif #if HAVE_ST_DB_GET_OPEN_FLAGS "open_flags", #endif 0 }; struct optst { VALUE obj, str; }; static VALUE bdb_intern_conf(optp) struct optst *optp; { return bdb_i_conf(optp->obj, optp->str); } static VALUE bdb_conf(int argc, VALUE *argv, VALUE obj) { int i, state; VALUE res, val; struct optst opt; if (argc > 1) { rb_raise(rb_eArgError, "invalid number of arguments (%d for 1)", argc); } if (argc == 1) { return bdb_i_conf(obj, argv[0]); } res = rb_hash_new(); opt.obj = obj; for (i = 0; options[i] != NULL; i++) { opt.str = rb_str_new2(options[i]); val = rb_protect(bdb_intern_conf, (VALUE)&opt, &state); if (state == 0) { rb_hash_aset(res, opt.str, val); } } return res; } #if HAVE_ST_DB_FD static VALUE bdb_fd(VALUE obj) { int fd = 0; bdb_DB *dbst; VALUE ary[2]; GetDB(obj, dbst); if (dbst->dbp->fd(dbst->dbp, &fd)) { rb_raise(rb_eArgError, "invalid database handler"); } ary[0] = INT2FIX(fd); ary[1] = rb_str_new2("r"); return rb_class_new_instance(2, ary, rb_cIO); } #endif #if HAVE_ST_DB_SET_PRIORITY static VALUE bdb_set_priority(VALUE obj, VALUE a) { bdb_DB *dbst; GetDB(obj, dbst); if (dbst->dbp->set_priority(dbst->dbp, NUM2INT(a))) { rb_raise(rb_eArgError, "invalid argument"); } return a; } static VALUE bdb_priority(VALUE obj) { bdb_DB *dbst; DB_CACHE_PRIORITY prio = 0; GetDB(obj, dbst); if (dbst->dbp->get_priority(dbst->dbp, &prio)) { rb_raise(rb_eArgError, "invalid argument"); } return INT2FIX(prio); } #endif void bdb_init_common() { id_bt_compare = rb_intern("bdb_bt_compare"); id_bt_prefix = rb_intern("bdb_bt_prefix"); #if HAVE_CONST_DB_DUPSORT id_dup_compare = rb_intern("bdb_dup_compare"); #endif id_h_hash = rb_intern("bdb_h_hash"); #if HAVE_ST_DB_SET_H_COMPARE id_h_compare = rb_intern("bdb_h_compare"); #endif #if HAVE_ST_DB_SET_APPEND_RECNO id_append_recno = rb_intern("bdb_append_recno"); #endif #if HAVE_ST_DB_SET_FEEDBACK id_feedback = rb_intern("bdb_feedback"); #endif bdb_cCommon = rb_define_class_under(bdb_mDb, "Common", rb_cObject); rb_define_private_method(bdb_cCommon, "initialize", bdb_init, -1); rb_include_module(bdb_cCommon, rb_mEnumerable); #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_define_alloc_func(bdb_cCommon, bdb_s_alloc); #else rb_define_singleton_method(bdb_cCommon, "allocate", bdb_s_alloc, 0); #endif rb_define_singleton_method(bdb_cCommon, "new", bdb_s_new, -1); rb_define_singleton_method(bdb_cCommon, "create", bdb_s_new, -1); rb_define_singleton_method(bdb_cCommon, "open", bdb_s_open, -1); rb_define_singleton_method(bdb_cCommon, "[]", bdb_s_create, -1); #if HAVE_ST_DB_REMOVE rb_define_singleton_method(bdb_cCommon, "remove", bdb_s_remove, -1); rb_define_singleton_method(bdb_cCommon, "bdb_remove", bdb_s_remove, -1); rb_define_singleton_method(bdb_cCommon, "unlink", bdb_s_remove, -1); #endif rb_define_singleton_method(bdb_cCommon, "upgrade", bdb_s_upgrade, -1); rb_define_singleton_method(bdb_cCommon, "bdb_upgrade", bdb_s_upgrade, -1); #if HAVE_ST_DB_RENAME rb_define_singleton_method(bdb_cCommon, "rename", bdb_s_rename, -1); rb_define_singleton_method(bdb_cCommon, "bdb_rename", bdb_s_rename, -1); #endif rb_define_private_method(bdb_cCommon, "__txn_close__", bdb__txn__close, 2); rb_define_private_method(bdb_cCommon, "__txn_dup__", bdb__txn__dup, 1); rb_define_method(bdb_cCommon, "filename", bdb_filename, 0); rb_define_method(bdb_cCommon, "subname", bdb_database, 0); rb_define_method(bdb_cCommon, "database", bdb_database, 0); #if HAVE_ST_DB_VERIFY rb_define_method(bdb_cCommon, "verify", bdb_verify, -1); #endif rb_define_method(bdb_cCommon, "close", bdb_close, -1); rb_define_method(bdb_cCommon, "db_close", bdb_close, -1); rb_define_method(bdb_cCommon, "put", bdb_put, -1); rb_define_method(bdb_cCommon, "db_put", bdb_put, -1); rb_define_method(bdb_cCommon, "[]=", bdb_aset, 2); rb_define_method(bdb_cCommon, "store", bdb_put, -1); rb_define_method(bdb_cCommon, "env", bdb_env, 0); rb_define_method(bdb_cCommon, "environment", bdb_env, 0); rb_define_method(bdb_cCommon, "has_env?", bdb_env_p, 0); rb_define_method(bdb_cCommon, "has_environment?", bdb_env_p, 0); rb_define_method(bdb_cCommon, "env?", bdb_env_p, 0); rb_define_method(bdb_cCommon, "environment?", bdb_env_p, 0); rb_define_method(bdb_cCommon, "txn", bdb_txn, 0); rb_define_method(bdb_cCommon, "transaction", bdb_txn, 0); rb_define_method(bdb_cCommon, "txn?", bdb_txn_p, 0); rb_define_method(bdb_cCommon, "transaction?", bdb_txn_p, 0); rb_define_method(bdb_cCommon, "in_txn?", bdb_txn_p, 0); rb_define_method(bdb_cCommon, "in_transaction?", bdb_txn_p, 0); #if HAVE_CONST_DB_NEXT_DUP rb_define_method(bdb_cCommon, "count", bdb_count, 1); rb_define_method(bdb_cCommon, "dup_count", bdb_count, 1); rb_define_method(bdb_cCommon, "each_dup", bdb_common_each_dup, -1); rb_define_method(bdb_cCommon, "each_dup_value", bdb_common_each_dup_val, -1); rb_define_method(bdb_cCommon, "dups", bdb_common_dups, -1); rb_define_method(bdb_cCommon, "duplicates", bdb_common_dups, -1); rb_define_method(bdb_cCommon, "get_dup", bdb_get_dup, -1); #endif rb_define_method(bdb_cCommon, "get", bdb_get_dyna, -1); rb_define_method(bdb_cCommon, "db_get", bdb_get_dyna, -1); rb_define_method(bdb_cCommon, "[]", bdb_get_dyna, -1); #if HAVE_ST_DB_PGET rb_define_method(bdb_cCommon, "pget", bdb_pget, -1); rb_define_method(bdb_cCommon, "primary_get", bdb_pget, -1); rb_define_method(bdb_cCommon, "db_pget", bdb_pget, -1); #endif rb_define_method(bdb_cCommon, "fetch", bdb_fetch, -1); rb_define_method(bdb_cCommon, "delete", bdb_del, 1); rb_define_method(bdb_cCommon, "del", bdb_del, 1); rb_define_method(bdb_cCommon, "db_del", bdb_del, 1); rb_define_method(bdb_cCommon, "sync", bdb_sync, 0); rb_define_method(bdb_cCommon, "db_sync", bdb_sync, 0); rb_define_method(bdb_cCommon, "flush", bdb_sync, 0); rb_define_method(bdb_cCommon, "each", bdb_each_pair, -1); rb_define_method(bdb_cCommon, "each_primary", bdb_each_pair_prim, -1); rb_define_method(bdb_cCommon, "each_value", bdb_each_value, -1); rb_define_method(bdb_cCommon, "reverse_each_value", bdb_each_eulav, -1); rb_define_method(bdb_cCommon, "each_key", bdb_each_key, -1); rb_define_method(bdb_cCommon, "reverse_each_key", bdb_each_yek, -1); rb_define_method(bdb_cCommon, "each_pair", bdb_each_pair, -1); rb_define_method(bdb_cCommon, "reverse_each", bdb_each_riap, -1); rb_define_method(bdb_cCommon, "reverse_each_pair", bdb_each_riap, -1); rb_define_method(bdb_cCommon, "reverse_each_primary", bdb_each_riap_prim, -1); rb_define_method(bdb_cCommon, "keys", bdb_keys, 0); rb_define_method(bdb_cCommon, "values", bdb_values, 0); rb_define_method(bdb_cCommon, "delete_if", bdb_delete_if, -1); rb_define_method(bdb_cCommon, "reject!", bdb_delete_if, -1); rb_define_method(bdb_cCommon, "reject", bdb_reject, -1); rb_define_method(bdb_cCommon, "clear", bdb_clear, -1); rb_define_method(bdb_cCommon, "truncate", bdb_clear, -1); rb_define_method(bdb_cCommon, "replace", bdb_replace, -1); rb_define_method(bdb_cCommon, "update", bdb_update, 1); rb_define_method(bdb_cCommon, "include?", bdb_has_key, 1); rb_define_method(bdb_cCommon, "has_key?", bdb_has_key, 1); rb_define_method(bdb_cCommon, "key?", bdb_has_key, 1); rb_define_method(bdb_cCommon, "member?", bdb_has_key, 1); rb_define_method(bdb_cCommon, "has_value?", bdb_has_value, 1); rb_define_method(bdb_cCommon, "value?", bdb_has_value, 1); rb_define_method(bdb_cCommon, "has_both?", bdb_has_both, 2); rb_define_method(bdb_cCommon, "both?", bdb_has_both, 2); rb_define_method(bdb_cCommon, "to_a", bdb_to_a, 0); rb_define_method(bdb_cCommon, "to_hash", bdb_to_hash, 0); rb_define_method(bdb_cCommon, "invert", bdb_invert, 0); rb_define_method(bdb_cCommon, "empty?", bdb_empty, 0); rb_define_method(bdb_cCommon, "length", bdb_length, 0); rb_define_alias(bdb_cCommon, "size", "length"); rb_define_method(bdb_cCommon, "index", bdb_index, 1); rb_define_method(bdb_cCommon, "indexes", bdb_indexes, -1); rb_define_method(bdb_cCommon, "indices", bdb_indexes, -1); rb_define_method(bdb_cCommon, "select", bdb_select, -1); rb_define_method(bdb_cCommon, "values_at", bdb_values_at, -1); rb_define_method(bdb_cCommon, "set_partial", bdb_set_partial, 2); rb_define_method(bdb_cCommon, "clear_partial", bdb_clear_partial, 0); rb_define_method(bdb_cCommon, "partial_clear", bdb_clear_partial, 0); #if HAVE_ST_DB_JOIN rb_define_method(bdb_cCommon, "join", bdb_join, -1); #endif #if HAVE_ST_DB_BYTESWAPPED || HAVE_ST_DB_GET_BYTESWAPPED rb_define_method(bdb_cCommon, "byteswapped?", bdb_byteswapp, 0); rb_define_method(bdb_cCommon, "get_byteswapped", bdb_byteswapp, 0); #endif #if HAVE_ST_DB_ASSOCIATE rb_define_method(bdb_cCommon, "associate", bdb_associate, -1); #endif #if HAVE_ST_DB_SET_CACHE_PRIORITY rb_define_method(bdb_cCommon, "cache_priority=", bdb_cache_priority_set, 1); rb_define_method(bdb_cCommon, "cache_priority", bdb_cache_priority_get, 0); #endif #if HAVE_ST_DB_SET_FEEDBACK rb_define_method(bdb_cCommon, "feedback=", bdb_feedback_set, 1); #endif bdb_cBtree = rb_define_class_under(bdb_mDb, "Btree", bdb_cCommon); rb_define_method(bdb_cBtree, "stat", bdb_tree_stat, -1); rb_define_method(bdb_cBtree, "each_by_prefix", bdb_each_prefix, -1); rb_define_method(bdb_cBtree, "reverse_each_by_prefix", bdb_each_xiferp, -1); #if HAVE_TYPE_DB_COMPACT rb_define_method(bdb_cBtree, "compact", bdb_treerec_compact, -1); #endif #if HAVE_TYPE_DB_KEY_RANGE bdb_sKeyrange = rb_struct_define("Keyrange", "less", "equal", "greater", 0); rb_global_variable(&bdb_sKeyrange); rb_define_method(bdb_cBtree, "key_range", bdb_btree_key_range, 1); #endif bdb_cHash = rb_define_class_under(bdb_mDb, "Hash", bdb_cCommon); #if HAVE_TYPE_DB_HASH_STAT rb_define_method(bdb_cHash, "stat", bdb_hash_stat, -1); #endif bdb_cRecno = rb_define_class_under(bdb_mDb, "Recno", bdb_cCommon); rb_define_method(bdb_cRecno, "each_index", bdb_each_key, -1); rb_define_method(bdb_cRecno, "unshift", bdb_unshift, -1); rb_define_method(bdb_cRecno, "<<", bdb_append, 1); rb_define_method(bdb_cRecno, "push", bdb_append_m, -1); rb_define_method(bdb_cRecno, "stat", bdb_tree_stat, -1); #if HAVE_TYPE_DB_COMPACT rb_define_method(bdb_cRecno, "compact", bdb_treerec_compact, -1); #endif #if HAVE_CONST_DB_QUEUE bdb_cQueue = rb_define_class_under(bdb_mDb, "Queue", bdb_cCommon); rb_define_singleton_method(bdb_cQueue, "new", bdb_queue_s_new, -1); rb_define_singleton_method(bdb_cQueue, "create", bdb_queue_s_new, -1); rb_define_method(bdb_cQueue, "each_index", bdb_each_key, -1); rb_define_method(bdb_cQueue, "<<", bdb_append, 1); rb_define_method(bdb_cQueue, "push", bdb_append_m, -1); #if HAVE_CONST_DB_CONSUME rb_define_method(bdb_cQueue, "shift", bdb_consume, 0); #endif rb_define_method(bdb_cQueue, "stat", bdb_queue_stat, -1); rb_define_method(bdb_cQueue, "pad", bdb_queue_padlen, 0); #endif rb_define_method(bdb_cCommon, "configuration", bdb_conf, -1); rb_define_method(bdb_cCommon, "conf", bdb_conf, -1); #if HAVE_ST_DB_FD rb_define_method(bdb_cCommon, "fd", bdb_fd, 0); #endif #if HAVE_ST_DB_SET_PRIORITY rb_define_method(bdb_cCommon, "priority", bdb_priority, 0); rb_define_method(bdb_cCommon, "priority=", bdb_set_priority, 1); #endif bdb_cUnknown = rb_define_class_under(bdb_mDb, "Unknown", bdb_cCommon); } ruby-bdb-0.6.6/src/cursor.c000066400000000000000000000304361154714021300155050ustar00rootroot00000000000000#include "bdb.h" static void bdb_cursor_free(bdb_DBC *dbcst) { bdb_DB *dbst; if (dbcst->dbc && BDB_VALID(dbcst->db, T_DATA)) { Data_Get_Struct(dbcst->db, bdb_DB, dbst); if (dbst->dbp) { dbcst->dbc->c_close(dbcst->dbc); } dbcst->dbc = NULL; dbcst->db = 0; } free(dbcst); } static VALUE bdb_cursor(int argc, VALUE *argv, VALUE obj) { bdb_DB *dbst; DB_TXN *txnid; bdb_DBC *dbcst; DBC *dbc; VALUE a; int flags; INIT_TXN(txnid, obj, dbst); flags = 0; if (argc && TYPE(argv[argc - 1]) == T_HASH) { VALUE g, f = argv[argc - 1]; if ((g = rb_hash_aref(f, rb_intern("flags"))) != RHASH(f)->ifnone || (g = rb_hash_aref(f, rb_str_new2("flags"))) != RHASH(f)->ifnone) { flags = NUM2INT(g); } argc--; } if (argc) { flags = NUM2INT(argv[0]); } #if HAVE_DB_CURSOR_4 bdb_test_error(dbst->dbp->cursor(dbst->dbp, txnid, &dbc, flags)); #else bdb_test_error(dbst->dbp->cursor(dbst->dbp, txnid, &dbc)); #endif a = Data_Make_Struct(bdb_cCursor, bdb_DBC, 0, bdb_cursor_free, dbcst); dbcst->dbc = dbc; dbcst->db = obj; return a; } static VALUE bdb_write_cursor(VALUE obj) { VALUE f; #if HAVE_CONST_DB_WRITECURSOR f = INT2NUM(DB_WRITECURSOR); #else f = INT2NUM(DB_RMW); #endif return bdb_cursor(1, &f, obj); } static VALUE bdb_cursor_close(VALUE obj) { bdb_DBC *dbcst; bdb_DB *dbst; if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4) rb_raise(rb_eSecurityError, "Insecure: can't close the cursor"); GetCursorDB(obj, dbcst, dbst); bdb_test_error(dbcst->dbc->c_close(dbcst->dbc)); dbcst->dbc = NULL; return Qtrue; } static VALUE bdb_cursor_del(VALUE obj) { int flags = 0; bdb_DBC *dbcst; bdb_DB *dbst; rb_secure(4); GetCursorDB(obj, dbcst, dbst); bdb_test_error(dbcst->dbc->c_del(dbcst->dbc, flags)); return Qtrue; } #if HAVE_ST_DBC_C_DUP static VALUE bdb_cursor_dup(int argc, VALUE *argv, VALUE obj) { int flags = 0; VALUE a, b; bdb_DBC *dbcst, *dbcstdup; bdb_DB *dbst; DBC *dbcdup; if (rb_scan_args(argc, argv, "01", &a)) flags = NUM2INT(a); GetCursorDB(obj, dbcst, dbst); bdb_test_error(dbcst->dbc->c_dup(dbcst->dbc, &dbcdup, flags)); b = Data_Make_Struct(bdb_cCursor, bdb_DBC, 0, bdb_cursor_free, dbcstdup); dbcstdup->dbc = dbcdup; dbcstdup->db = dbcst->db; return b; } #endif static VALUE bdb_cursor_count(VALUE obj) { #if !HAVE_CONST_DB_NEXT_DUP rb_raise(bdb_eFatal, "DB_NEXT_DUP needs Berkeley DB 2.6 or later"); #else #if !HAVE_ST_DBC_C_COUNT DBT key, data; DBT key_o, data_o; int ret; #endif bdb_DBC *dbcst; bdb_DB *dbst; db_recno_t count; GetCursorDB(obj, dbcst, dbst); #if HAVE_ST_DBC_C_COUNT bdb_test_error(dbcst->dbc->c_count(dbcst->dbc, &count, 0)); return INT2NUM(count); #else MEMZERO(&key, DBT, 1); key.flags |= DB_DBT_MALLOC; MEMZERO(&data, DBT, 1); data.flags |= DB_DBT_MALLOC; MEMZERO(&key_o, DBT, 1); key_o.flags |= DB_DBT_MALLOC; MEMZERO(&data_o, DBT, 1); data_o.flags |= DB_DBT_MALLOC; SET_PARTIAL(dbst, data); ret = bdb_test_error(dbcst->dbc->c_get(dbcst->dbc, &key_o, &data_o, DB_CURRENT)); if (ret == DB_NOTFOUND || ret == DB_KEYEMPTY) return INT2NUM(0); count = 1; while (1) { MEMZERO(&key, DBT, 1); key.flags |= DB_DBT_MALLOC; MEMZERO(&data, DBT, 1); data.flags |= DB_DBT_MALLOC; SET_PARTIAL(dbst, data); ret = bdb_test_error(dbcst->dbc->c_get(dbcst->dbc, &key, &data, DB_NEXT_DUP)); if (ret == DB_NOTFOUND) { MEMZERO(&key_o, DBT, 1); key_o.flags |= DB_DBT_MALLOC; MEMZERO(&data_o, DBT, 1); data_o.flags |= DB_DBT_MALLOC; bdb_test_error(dbcst->dbc->c_get(dbcst->dbc, &key_o, &data_o, DB_SET)); FREE_KEY(dbst, key_o); free(data_o.data); return INT2NUM(count); } if (ret == DB_KEYEMPTY) continue; FREE_KEY(dbst, key); free(data.data); count++; } return INT2NUM(-1); #endif #endif } static VALUE bdb_cursor_get_common(int argc, VALUE *argv, VALUE obj, int c_pget) { volatile VALUE a = Qnil; VALUE b = Qnil; VALUE c; int flags, cnt, ret; DBT key, data, pkey; bdb_DBC *dbcst; bdb_DB *dbst; db_recno_t recno; cnt = rb_scan_args(argc, argv, "12", &a, &b, &c); flags = NUM2INT(a); MEMZERO(&key, DBT, 1); MEMZERO(&pkey, DBT, 1); pkey.flags |= DB_DBT_MALLOC; MEMZERO(&data, DBT, 1); GetCursorDB(obj, dbcst, dbst); if (flags == DB_SET_RECNO) { if (dbst->type != DB_BTREE || !(dbst->flags & DB_RECNUM)) { rb_raise(bdb_eFatal, "database must be Btree with RECNUM for SET_RECNO"); } if (cnt != 2) rb_raise(bdb_eFatal, "invalid number of arguments"); recno = NUM2INT(b); key.data = &recno; key.size = sizeof(db_recno_t); key.flags |= DB_DBT_MALLOC; data.flags |= DB_DBT_MALLOC; } else if (flags == DB_SET || flags == DB_SET_RANGE) { if (cnt != 2) rb_raise(bdb_eFatal, "invalid number of arguments"); b = bdb_test_recno(dbcst->db, &key, &recno, b); data.flags |= DB_DBT_MALLOC; } #if DB_GET_BOTH else if (flags == DB_GET_BOTH) { if (cnt != 3) rb_raise(bdb_eFatal, "invalid number of arguments"); b = bdb_test_recno(dbcst->db, &key, &recno, b); a = bdb_test_dump(dbcst->db, &data, c, FILTER_VALUE); } #endif else { if (cnt != 1) { rb_raise(bdb_eFatal, "invalid number of arguments"); } key.flags |= DB_DBT_MALLOC; data.flags |= DB_DBT_MALLOC; } SET_PARTIAL(dbst, data); #if HAVE_ST_DBC_C_PGET if (c_pget) { if (dbst->secondary != Qnil) { rb_raise(bdb_eFatal, "pget must be used with a secondary index"); } ret = bdb_test_error(dbcst->dbc->c_pget(dbcst->dbc, &key, &pkey, &data, flags)); } else #endif { ret = bdb_test_error(dbcst->dbc->c_get(dbcst->dbc, &key, &data, flags)); } if (ret == DB_NOTFOUND || ret == DB_KEYEMPTY) return Qnil; if (c_pget) { return bdb_assoc3(dbcst->db, &key, &pkey, &data); } else { return bdb_assoc_dyna(dbcst->db, &key, &data); } } static VALUE bdb_cursor_get(int argc, VALUE *argv, VALUE obj) { return bdb_cursor_get_common(argc, argv, obj, 0); } #if HAVE_ST_DBC_C_PGET static VALUE bdb_cursor_pget(int argc, VALUE *argv, VALUE obj) { return bdb_cursor_get_common(argc, argv, obj, 1); } #endif static VALUE bdb_cursor_set_xxx(VALUE obj, VALUE a, int flag) { VALUE *b; b = ALLOCA_N(VALUE, 2); b[0] = INT2NUM(flag); b[1] = a; return bdb_cursor_get(2, b, obj); } static VALUE bdb_cursor_set(VALUE obj, VALUE a) { return bdb_cursor_set_xxx(obj, a, DB_SET); } static VALUE bdb_cursor_set_range(VALUE obj, VALUE a) { return bdb_cursor_set_xxx(obj, a, DB_SET_RANGE); } static VALUE bdb_cursor_set_recno(VALUE obj, VALUE a) { return bdb_cursor_set_xxx(obj, a, DB_SET_RECNO); } static VALUE bdb_cursor_xxx(VALUE obj, int val) { VALUE b; b = INT2NUM(val); return bdb_cursor_get(1, &b, obj); } static VALUE bdb_cursor_next(VALUE obj) { return bdb_cursor_xxx(obj, DB_NEXT); } #if HAVE_CONST_DB_NEXT_DUP static VALUE bdb_cursor_next_dup(VALUE obj) { return bdb_cursor_xxx(obj, DB_NEXT_DUP); } #endif static VALUE bdb_cursor_prev(VALUE obj) { return bdb_cursor_xxx(obj, DB_PREV); } static VALUE bdb_cursor_first(VALUE obj) { return bdb_cursor_xxx(obj, DB_FIRST); } static VALUE bdb_cursor_last(VALUE obj) { return bdb_cursor_xxx(obj, DB_LAST); } static VALUE bdb_cursor_current(VALUE obj) { return bdb_cursor_xxx(obj, DB_CURRENT); } static VALUE bdb_cursor_put(int argc, VALUE *argv, VALUE obj) { int flags, cnt; DBT key, data; bdb_DBC *dbcst; bdb_DB *dbst; VALUE a, b, c, f; volatile VALUE d = Qnil; volatile VALUE e = Qnil; db_recno_t recno; int ret; rb_secure(4); MEMZERO(&key, DBT, 1); MEMZERO(&data, DBT, 1); cnt = rb_scan_args(argc, argv, "21", &a, &b, &c); GetCursorDB(obj, dbcst, dbst); flags = NUM2INT(a); if (flags == DB_KEYFIRST || flags == DB_KEYLAST) { if (cnt != 3) rb_raise(bdb_eFatal, "invalid number of arguments"); d = bdb_test_recno(dbcst->db, &key, &recno, b); e = bdb_test_dump(dbcst->db, &data, c, FILTER_VALUE); f = c; } else { e = bdb_test_dump(dbcst->db, &data, b, FILTER_VALUE); f = b; } SET_PARTIAL(dbst, data); ret = bdb_test_error(dbcst->dbc->c_put(dbcst->dbc, &key, &data, flags)); if (cnt == 3) { FREE_KEY(dbst, key); } if (data.flags & DB_DBT_MALLOC) free(data.data); if (ret == DB_KEYEXIST) { return Qfalse; } else { if (dbst->partial) { return bdb_cursor_current(obj); } else { return bdb_test_ret(obj, e, f, FILTER_VALUE); } } } #if HAVE_ST_DBC_GET_PRIORITY static VALUE bdb_cursor_set_priority(VALUE obj, VALUE a) { bdb_DBC *dbcst; bdb_DB *dbst; GetCursorDB(obj, dbcst, dbst); if (dbcst->dbc->set_priority(dbcst->dbc, NUM2INT(a))) { rb_raise(rb_eArgError, "invalid argument"); } return a; } static VALUE bdb_cursor_priority(VALUE obj) { bdb_DBC *dbcst; bdb_DB *dbst; DB_CACHE_PRIORITY prio = 0; GetCursorDB(obj, dbcst, dbst); if (dbcst->dbc->get_priority(dbcst->dbc, &prio)) { rb_raise(rb_eArgError, "invalid argument"); } return INT2FIX(prio); } #endif void bdb_init_cursor() { rb_define_method(bdb_cCommon, "db_cursor", bdb_cursor, -1); rb_define_method(bdb_cCommon, "cursor", bdb_cursor, -1); rb_define_method(bdb_cCommon, "db_write_cursor", bdb_write_cursor, 0); rb_define_method(bdb_cCommon, "write_cursor", bdb_write_cursor, 0); bdb_cCursor = rb_define_class_under(bdb_mDb, "Cursor", rb_cObject); #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_undef_alloc_func(bdb_cCursor); #else rb_undef_method(CLASS_OF(bdb_cCursor), "allocate"); #endif rb_undef_method(CLASS_OF(bdb_cCursor), "new"); rb_define_method(bdb_cCursor, "close", bdb_cursor_close, 0); rb_define_method(bdb_cCursor, "c_close", bdb_cursor_close, 0); rb_define_method(bdb_cCursor, "c_del", bdb_cursor_del, 0); rb_define_method(bdb_cCursor, "del", bdb_cursor_del, 0); rb_define_method(bdb_cCursor, "delete", bdb_cursor_del, 0); #if HAVE_ST_DBC_C_DUP rb_define_method(bdb_cCursor, "dup", bdb_cursor_dup, -1); rb_define_method(bdb_cCursor, "c_dup", bdb_cursor_dup, -1); rb_define_method(bdb_cCursor, "clone", bdb_cursor_dup, -1); rb_define_method(bdb_cCursor, "c_clone", bdb_cursor_dup, -1); #endif rb_define_method(bdb_cCursor, "count", bdb_cursor_count, 0); rb_define_method(bdb_cCursor, "c_count", bdb_cursor_count, 0); rb_define_method(bdb_cCursor, "get", bdb_cursor_get, -1); rb_define_method(bdb_cCursor, "c_get", bdb_cursor_get, -1); #if HAVE_ST_DBC_C_PGET rb_define_method(bdb_cCursor, "pget", bdb_cursor_pget, -1); rb_define_method(bdb_cCursor, "c_pget", bdb_cursor_pget, -1); #endif rb_define_method(bdb_cCursor, "put", bdb_cursor_put, -1); rb_define_method(bdb_cCursor, "c_put", bdb_cursor_put, -1); rb_define_method(bdb_cCursor, "c_next", bdb_cursor_next, 0); rb_define_method(bdb_cCursor, "next", bdb_cursor_next, 0); #if HAVE_CONST_DB_NEXT_DUP rb_define_method(bdb_cCursor, "c_next_dup", bdb_cursor_next_dup, 0); rb_define_method(bdb_cCursor, "next_dup", bdb_cursor_next_dup, 0); #endif rb_define_method(bdb_cCursor, "c_first", bdb_cursor_first, 0); rb_define_method(bdb_cCursor, "first", bdb_cursor_first, 0); rb_define_method(bdb_cCursor, "c_last", bdb_cursor_last, 0); rb_define_method(bdb_cCursor, "last", bdb_cursor_last, 0); rb_define_method(bdb_cCursor, "c_current", bdb_cursor_current, 0); rb_define_method(bdb_cCursor, "current", bdb_cursor_current, 0); rb_define_method(bdb_cCursor, "c_prev", bdb_cursor_prev, 0); rb_define_method(bdb_cCursor, "prev", bdb_cursor_prev, 0); rb_define_method(bdb_cCursor, "c_set", bdb_cursor_set, 1); rb_define_method(bdb_cCursor, "set", bdb_cursor_set, 1); rb_define_method(bdb_cCursor, "c_set_range", bdb_cursor_set_range, 1); rb_define_method(bdb_cCursor, "set_range", bdb_cursor_set_range, 1); rb_define_method(bdb_cCursor, "c_set_recno", bdb_cursor_set_recno, 1); rb_define_method(bdb_cCursor, "set_recno", bdb_cursor_set_recno, 1); #if HAVE_ST_DBC_GET_PRIORITY rb_define_method(bdb_cCursor, "priority", bdb_cursor_priority, 0); rb_define_method(bdb_cCursor, "priority=", bdb_cursor_set_priority, 1); #endif } ruby-bdb-0.6.6/src/delegator.c000066400000000000000000000121061154714021300161300ustar00rootroot00000000000000#include "bdb.h" static ID id_send; void bdb_deleg_mark(struct deleg_class *delegst) { rb_gc_mark(delegst->db); rb_gc_mark(delegst->key); rb_gc_mark(delegst->obj); } extern VALUE bdb_put _((int, VALUE *, VALUE)); #if ! HAVE_RB_BLOCK_CALL static VALUE bdb_deleg_each(VALUE *tmp) { return rb_funcall2(tmp[0], id_send, (int)tmp[1], (VALUE *)tmp[2]); } #endif static VALUE bdb_deleg_missing(int argc, VALUE *argv, VALUE obj) { struct deleg_class *delegst, *newst; bdb_DB *dbst; VALUE res, new; Data_Get_Struct(obj, struct deleg_class, delegst); if (rb_block_given_p()) { #if HAVE_RB_BLOCK_CALL res = rb_block_call(delegst->obj, id_send, argc, argv, rb_yield, 0); #else VALUE tmp[3]; tmp[0] = delegst->obj; tmp[1] = (VALUE)argc; tmp[2] = (VALUE)argv; res = rb_iterate((VALUE(*)(VALUE))bdb_deleg_each, (VALUE)tmp, rb_yield, 0); #endif } else { res = rb_funcall2(delegst->obj, id_send, argc, argv); } Data_Get_Struct(delegst->db, bdb_DB, dbst); if (dbst->dbp) { VALUE nargv[2]; if (!SPECIAL_CONST_P(res) && (TYPE(res) != T_DATA || RDATA(res)->dmark != (RUBY_DATA_FUNC)bdb_deleg_mark)) { new = Data_Make_Struct(bdb_cDelegate, struct deleg_class, bdb_deleg_mark, free, newst); newst->db = delegst->db; newst->obj = res; newst->key = (!delegst->type)?obj:delegst->key; newst->type = 1; res = new; } if (!delegst->type) { nargv[0] = delegst->key; nargv[1] = delegst->obj; } else { Data_Get_Struct(delegst->key, struct deleg_class, newst); nargv[0] = newst->key; nargv[1] = newst->obj; } bdb_put(2, nargv, delegst->db); } return res; } #define DELEG_0(id) \ { \ struct deleg_class *delegst; \ Data_Get_Struct(obj, struct deleg_class, delegst); \ return rb_funcall2(delegst->obj, id, 0, 0); \ } static VALUE bdb_deleg_inspect(VALUE obj) DELEG_0(rb_intern("inspect")) static VALUE bdb_deleg_to_s(VALUE obj) DELEG_0(rb_intern("to_s")) static VALUE bdb_deleg_to_str(VALUE obj) DELEG_0(rb_intern("to_str")) static VALUE bdb_deleg_to_a(VALUE obj) DELEG_0(rb_intern("to_a")) static VALUE bdb_deleg_to_ary(VALUE obj) DELEG_0(rb_intern("to_ary")) static VALUE bdb_deleg_to_i(VALUE obj) DELEG_0(rb_intern("to_i")) static VALUE bdb_deleg_to_int(VALUE obj) DELEG_0(rb_intern("to_int")) static VALUE bdb_deleg_to_f(VALUE obj) DELEG_0(rb_intern("to_f")) static VALUE bdb_deleg_to_hash(VALUE obj) DELEG_0(rb_intern("to_hash")) static VALUE bdb_deleg_to_io(VALUE obj) DELEG_0(rb_intern("to_io")) static VALUE bdb_deleg_to_proc(VALUE obj) DELEG_0(rb_intern("to_proc")) VALUE bdb_deleg_to_orig(VALUE obj) { struct deleg_class *delegst; Data_Get_Struct(obj, struct deleg_class, delegst); return delegst->obj; } static VALUE bdb_deleg_orig(VALUE obj) { return obj; } static VALUE bdb_deleg_dump(VALUE obj, VALUE limit) { struct deleg_class *delegst; bdb_DB *dbst; Data_Get_Struct(obj, struct deleg_class, delegst); Data_Get_Struct(delegst->db, bdb_DB, dbst); return rb_funcall(dbst->marshal, bdb_id_dump, 1, delegst->obj); } static VALUE bdb_deleg_load(VALUE obj, VALUE str) { bdb_DB *dbst; obj = bdb_local_aref(); Data_Get_Struct(obj, bdb_DB, dbst); return rb_funcall(dbst->marshal, bdb_id_load, 1, str); } void bdb_init_delegator() { id_send = rb_intern("send"); bdb_cDelegate = rb_define_class_under(bdb_mDb, "Delegate", rb_cObject); { VALUE ary = Qfalse, tmp; char *method; int i; ary = rb_class_instance_methods(1, &ary, rb_mKernel); for (i = 0; i < RARRAY_LEN(ary); i++) { tmp = rb_obj_as_string(RARRAY_PTR(ary)[i]); method = StringValuePtr(tmp); if (!strcmp(method, "==") || !strcmp(method, "===") || !strcmp(method, "=~") || !strcmp(method, "respond_to?") ) continue; rb_undef_method(bdb_cDelegate, method); } } rb_define_method(bdb_cDelegate, "method_missing", bdb_deleg_missing, -1); rb_define_method(bdb_cDelegate, "inspect", bdb_deleg_inspect, 0); rb_define_method(bdb_cDelegate, "to_s", bdb_deleg_to_s, 0); rb_define_method(bdb_cDelegate, "to_str", bdb_deleg_to_str, 0); rb_define_method(bdb_cDelegate, "to_a", bdb_deleg_to_a, 0); rb_define_method(bdb_cDelegate, "to_ary", bdb_deleg_to_ary, 0); rb_define_method(bdb_cDelegate, "to_i", bdb_deleg_to_i, 0); rb_define_method(bdb_cDelegate, "to_int", bdb_deleg_to_int, 0); rb_define_method(bdb_cDelegate, "to_f", bdb_deleg_to_f, 0); rb_define_method(bdb_cDelegate, "to_hash", bdb_deleg_to_hash, 0); rb_define_method(bdb_cDelegate, "to_io", bdb_deleg_to_io, 0); rb_define_method(bdb_cDelegate, "to_proc", bdb_deleg_to_proc, 0); rb_define_method(bdb_cDelegate, "_dump", bdb_deleg_dump, 1); rb_define_method(bdb_cDelegate, "_dump_data", bdb_deleg_dump, 1); rb_define_singleton_method(bdb_cDelegate, "_load", bdb_deleg_load, 1); rb_define_singleton_method(bdb_cDelegate, "_load_data", bdb_deleg_load, 1); /* don't use please */ rb_define_method(bdb_cDelegate, "to_orig", bdb_deleg_to_orig, 0); rb_define_method(rb_mKernel, "to_orig", bdb_deleg_orig, 0); } ruby-bdb-0.6.6/src/env.c000066400000000000000000002367661154714021300147760ustar00rootroot00000000000000#include "bdb.h" ID bdb_id_call; #if HAVE_ST_DB_ENV_SET_FEEDBACK static ID id_feedback; #endif ID bdb_id_current_env; static void bdb_env_mark _((bdb_ENV *)); #define GetIdEnv(obj, envst) do { \ VALUE th = rb_thread_current(); \ \ if (!RTEST(th) || !RBASIC(th)->flags) { \ rb_raise(bdb_eFatal, "invalid thread object"); \ } \ (obj) = rb_thread_local_aref(th, bdb_id_current_env); \ if (TYPE(obj) != T_DATA || \ RDATA(obj)->dmark != (RUBY_DATA_FUNC)bdb_env_mark) { \ rb_raise(bdb_eFatal, "BUG : current_env not set"); \ } \ GetEnvDB(obj, envst); \ } while (0) #define GetIdEnv1(obj, envst) do { \ VALUE th = rb_thread_current(); \ \ if (!RTEST(th) || !RBASIC(th)->flags) { \ rb_raise(bdb_eFatal, "invalid thread object"); \ } \ (obj) = rb_thread_local_aref(th, bdb_id_current_env); \ if (TYPE(obj) != T_DATA || \ RDATA(obj)->dmark != (RUBY_DATA_FUNC)bdb_env_mark) { \ obj = Qnil; \ } \ else { \ GetEnvDB(obj, envst); \ } \ } while (0) #if HAVE_ST_DB_ENV_SET_APP_DISPATCH static ID id_app_dispatch; #endif struct db_stoptions { bdb_ENV *env; VALUE config; int lg_max, lg_bsize; }; #if HAVE_ST_DB_ENV_SET_REP_TRANSPORT || HAVE_ST_DB_ENV_REP_SET_TRANSPORT #if HAVE_ENV_REP_TRANSPORT_6 static int bdb_env_rep_transport(DB_ENV *env, const DBT *control, const DBT *rec, const DB_LSN *lsn, int envid, u_int32_t flags) { VALUE obj, av, bv, res; bdb_ENV *envst; struct dblsnst *lsnst; VALUE lsnobj; GetIdEnv(obj, envst); lsnobj = bdb_makelsn(obj); Data_Get_Struct(lsnobj, struct dblsnst, lsnst); MEMCPY(lsnst->lsn, lsn, DB_LSN, 1); av = rb_tainted_str_new(control->data, control->size); bv = rb_tainted_str_new(rec->data, rec->size); if (envst->rep_transport == 0) { res = rb_funcall(obj, rb_intern("bdb_rep_transport"), 5, av, bv, lsnobj, INT2FIX(envid), INT2FIX(flags)); } else { res = rb_funcall(envst->rep_transport, bdb_id_call, 5, av, bv, lsnobj, INT2FIX(envid), INT2FIX(flags)); } return NUM2INT(res); } #else static int bdb_env_rep_transport(DB_ENV *env, const DBT *control, const DBT *rec, int envid, u_int32_t flags) { VALUE obj, av, bv, res; bdb_ENV *envst; GetIdEnv(obj, envst); av = rb_tainted_str_new(control->data, control->size); bv = rb_tainted_str_new(rec->data, rec->size); if (envst->rep_transport == 0) { res = rb_funcall(obj, rb_intern("bdb_rep_transport"), 4, av, bv, INT2FIX(envid), INT2FIX(flags)); } else { res = rb_funcall(envst->rep_transport, bdb_id_call, 4, av, bv, INT2FIX(envid), INT2FIX(flags)); } return NUM2INT(res); } #endif #endif #if HAVE_ST_DB_ENV_REP_ELECT static VALUE bdb_env_rep_elect(int argc, VALUE *argv, VALUE env) { VALUE nb, pri, ti, nvo; bdb_ENV *envst; int envid = 0, nvotes = 0; GetEnvDB(env, envst); #if (HAVE_DB_ENV_REP_ELECT_5 && !HAVE_DB_ENV_REP_ELECT_PRIO) || HAVE_DB_ENV_REP_ELECT_7 pri = ti = 0; if (rb_scan_args(argc, argv, "11", &nb, &nvo) == 2) { nvotes = NUM2INT(nvo); } #else if (rb_scan_args(argc, argv, "31", &nb, &pri, &ti, &nvo) == 4) { nvotes = NUM2INT(nvo); } #endif #if HAVE_DB_ENV_REP_ELECT_4 bdb_test_error(envst->envp->rep_elect(envst->envp, NUM2INT(nb), nvotes, 0)); #elif HAVE_DB_ENV_REP_ELECT_5 #if HAVE_DB_ENV_REP_ELECT_PRIO bdb_test_error(envst->envp->rep_elect(envst->envp, NUM2INT(nb), NUM2INT(pri), NUM2INT(ti), &envid)); #else bdb_test_error(envst->envp->rep_elect(envst->envp, NUM2INT(nb), nvotes, &envid, 0)); #endif #elif HAVE_DB_ENV_REP_ELECT_7 bdb_test_error(envst->envp->rep_elect(envst->envp, NUM2INT(nb), nvotes, NUM2INT(pri), NUM2INT(ti), &envid, 0)); #endif return INT2NUM(envid); } #endif #if HAVE_ST_DB_ENV_REP_PROCESS_MESSAGE static VALUE bdb_env_rep_process_message(VALUE env, VALUE av, VALUE bv, VALUE ev) { bdb_ENV *envst; DBT control, rec; int ret, envid; VALUE result; #if HAVE_DB_ENV_REP_PROCESS_MESSAGE_5 VALUE lsn; struct dblsnst *lsnst; #endif GetEnvDB(env, envst); av = rb_str_to_str(av); bv = rb_str_to_str(bv); MEMZERO(&control, DBT, 1); MEMZERO(&rec, DBT, 1); control.size = RSTRING_LEN(av); control.data = StringValuePtr(av); rec.size = RSTRING_LEN(bv); rec.data = StringValuePtr(bv); envid = NUM2INT(ev); #if HAVE_DB_ENV_REP_PROCESS_MESSAGE_5 lsn = bdb_makelsn(env); Data_Get_Struct(lsn, struct dblsnst, lsnst); #if HAVE_DB_ENV_REP_PROCESS_MESSAGE_ENVID ret = envst->envp->rep_process_message(envst->envp, &control, &rec, envid, lsnst->lsn); #else ret = envst->envp->rep_process_message(envst->envp, &control, &rec, &envid, lsnst->lsn); #endif #else ret = envst->envp->rep_process_message(envst->envp, &control, &rec, &envid); #endif if (ret == DB_RUNRECOVERY) { bdb_test_error(ret); } result = rb_ary_new(); rb_ary_push(result, INT2NUM(ret)); rb_ary_push(result, rb_str_new(rec.data, rec.size)); rb_ary_push(result, INT2NUM(envid)); #if DB_RET_NOTPERM || DB_RET_ISPERM if (ret == DB_REP_NOTPERM || ret == DB_REP_ISPERM) { rb_ary_push(result, lsn); } #endif return result; } #endif #if HAVE_ST_DB_ENV_REP_START static VALUE bdb_env_rep_start(VALUE env, VALUE ident, VALUE flags) { bdb_ENV *envst; DBT cdata; GetEnvDB(env, envst); if (!NIL_P(ident)) { ident = rb_str_to_str(ident); MEMZERO(&cdata, DBT, 1); cdata.size = RSTRING_LEN(ident); cdata.data = StringValuePtr(ident); } bdb_test_error(envst->envp->rep_start(envst->envp, NIL_P(ident)?NULL:&cdata, NUM2INT(flags))); return Qnil; } #endif #if HAVE_ST_DB_ENV_REP_SET_LIMIT || HAVE_ST_DB_ENV_SET_REP_LIMIT static VALUE bdb_env_rep_limit(int argc, VALUE *argv, VALUE obj) { bdb_ENV *envst; VALUE a, b; u_int32_t gbytes, bytes; GetEnvDB(obj, envst); gbytes = bytes = 0; switch(rb_scan_args(argc, argv, "11", &a, &b)) { case 1: if (TYPE(a) == T_ARRAY) { if (RARRAY_LEN(a) != 2) { rb_raise(bdb_eFatal, "Expected an Array with 2 values"); } gbytes = NUM2UINT(RARRAY_PTR(a)[0]); bytes = NUM2UINT(RARRAY_PTR(a)[1]); } else { bytes = NUM2UINT(RARRAY_PTR(a)[1]); } break; case 2: gbytes = NUM2UINT(a); bytes = NUM2UINT(b); break; } #if HAVE_ST_DB_ENV_REP_SET_LIMIT bdb_test_error(envst->envp->rep_set_limit(envst->envp, gbytes, bytes)); #else bdb_test_error(envst->envp->set_rep_limit(envst->envp, gbytes, bytes)); #endif return obj; } #endif #if HAVE_ST_DB_ENV_SET_FEEDBACK static void bdb_env_feedback(DB_ENV *envp, int opcode, int pct) { VALUE obj; bdb_ENV *envst; GetIdEnv(obj, envst); if (NIL_P(envst->feedback)) { return; } if (envst->feedback == 0) { rb_funcall(obj, id_feedback, 2, INT2NUM(opcode), INT2NUM(pct)); } else { rb_funcall(envst->feedback, bdb_id_call, 2, INT2NUM(opcode), INT2NUM(pct)); } } #endif #if HAVE_ST_DB_ENV_SET_APP_DISPATCH static int bdb_env_app_dispatch(DB_ENV *envp, DBT *log_rec, DB_LSN *lsn, db_recops op) { VALUE obj, lsnobj, logobj, res; bdb_ENV *envst; struct dblsnst *lsnst; GetIdEnv(obj, envst); lsnobj = bdb_makelsn(obj); Data_Get_Struct(lsnobj, struct dblsnst, lsnst); MEMCPY(lsnst->lsn, lsn, DB_LSN, 1); logobj = rb_str_new(log_rec->data, log_rec->size); if (envst->app_dispatch == 0) { res = rb_funcall(obj, id_app_dispatch, 3, logobj, lsnobj, INT2NUM(op)); } else { res = rb_funcall(envst->app_dispatch, bdb_id_call, 3, logobj, lsnobj, INT2NUM(op)); } return NUM2INT(res); } #endif #if HAVE_ST_DB_ENV_SET_MSGCALL static ID id_msgcall; static void bdb_env_msgcall(const DB_ENV *dbenv, const char *msg) { VALUE obj; bdb_ENV *envst; GetIdEnv(obj, envst); if (NIL_P(envst->msgcall)) { return; } if (envst->msgcall == 0) { rb_funcall(obj, id_msgcall, 1, rb_tainted_str_new2(msg)); } else { rb_funcall(envst->msgcall, bdb_id_call, 1, rb_tainted_str_new2(msg)); } } #endif #if HAVE_ST_DB_ENV_SET_THREAD_ID static ID id_thread_id; static void bdb_env_thread_id(DB_ENV *dbenv, pid_t *pid, db_threadid_t *tid) { VALUE obj; bdb_ENV *envst; VALUE res; GetIdEnv(obj, envst); if (NIL_P(envst->thread_id)) { *pid = 0; *tid = 0; return; } if (envst->thread_id == 0) { res = rb_funcall2(obj, id_thread_id, 0, 0); } else { res = rb_funcall2(envst->thread_id, bdb_id_call, 0, 0); } res = rb_Array(res); if (TYPE(res) != T_ARRAY || RARRAY_LEN(res) != 2) { rb_raise(bdb_eFatal, "expected [pid, threadid]"); } *pid = NUM2LONG(RARRAY_PTR(res)[0]); *tid = (db_threadid_t)NUM2LONG(RARRAY_PTR(res)[0]); return; } #endif #if HAVE_ST_DB_ENV_SET_THREAD_ID_STRING static ID id_thread_id_string; static char * bdb_env_thread_id_string(DB_ENV *dbenv, pid_t pid, db_threadid_t tid, char *buf) { VALUE obj; bdb_ENV *envst; VALUE res, a, b; GetIdEnv(obj, envst); if (NIL_P(envst->thread_id_string)) { snprintf(buf, DB_THREADID_STRLEN, "%d/%ld", pid, (long)tid); return buf; } a = LONG2NUM(pid); b = LONG2NUM((long)tid); if (envst->thread_id_string == 0) { res = rb_funcall(obj, id_thread_id_string, 2, a, b); } else { res = rb_funcall(envst->thread_id_string, bdb_id_call, 2, a, b); } snprintf(buf, DB_THREADID_STRLEN, "%s", StringValuePtr(res)); return buf; } #endif #if HAVE_ST_DB_ENV_SET_ISALIVE static ID id_isalive; #if HAVE_CONST_DB_MUTEX_PROCESS_ONLY static int bdb_env_isalive(DB_ENV *dbenv, pid_t pid, db_threadid_t tid, u_int32_t flags) { VALUE obj; bdb_ENV *envst; VALUE res, a ,b, c; GetIdEnv(obj, envst); if (NIL_P(envst->isalive)) { return 0; } a = LONG2NUM(pid); b = LONG2NUM((long)tid); c = INT2NUM(flags); if (envst->isalive == 0) { res = rb_funcall(obj, id_isalive, 3, a, b, c); } else { res = rb_funcall(envst->isalive, bdb_id_call, 3, a, b, c); } if (RTEST(res)) { return 1; } return 0; } #else static int bdb_env_isalive(DB_ENV *dbenv, pid_t pid, db_threadid_t tid) { VALUE obj; bdb_ENV *envst; VALUE res, a ,b; GetIdEnv(obj, envst); if (NIL_P(envst->isalive)) { return 0; } a = INT2NUM(pid); b = INT2NUM(tid); if (envst->isalive == 0) { res = rb_funcall(obj, id_isalive, 2, a, b); } else { res = rb_funcall(envst->isalive, bdb_id_call, 2, a, b); } if (RTEST(res)) { return 1; } return 0; } #endif #endif #if HAVE_ST_DB_ENV_SET_EVENT_NOTIFY static ID id_event_notify; static void bdb_env_event_notify(DB_ENV *dbenv, u_int32_t event, void *event_info) { VALUE obj; bdb_ENV *envst; VALUE a; GetIdEnv(obj, envst); if (NIL_P(envst->event_notify)) { return; } a = INT2NUM(event); if (envst->event_notify == 0) { rb_funcall(obj, id_event_notify, 1, a); } else { rb_funcall(envst->event_notify, bdb_id_call, 1, a); } } static VALUE bdb_env_set_notify(VALUE obj, VALUE a) { bdb_ENV *envst; GetEnvDB(obj, envst); if (!NIL_P(a)) { if (!rb_respond_to(a, bdb_id_call)) { rb_raise(rb_eArgError, "object must respond to #call"); } envst->envp->set_event_notify(envst->envp, bdb_env_event_notify); } envst->event_notify = a; return a; } #endif static VALUE bdb_env_i_options(VALUE obj, VALUE db_stobj) { char *options; DB_ENV *envp; VALUE key, value; bdb_ENV *envst; struct db_stoptions *db_st; Data_Get_Struct(db_stobj, struct db_stoptions, db_st); envst = db_st->env; key = rb_ary_entry(obj, 0); value = rb_ary_entry(obj, 1); envp = envst->envp; key = rb_obj_as_string(key); options = StringValuePtr(key); if (strcmp(options, "set_cachesize") == 0) { switch (TYPE(value)) { case T_FIXNUM: case T_FLOAT: case T_BIGNUM: #if HAVE_ST_DB_ENV_SET_CACHESIZE bdb_test_error(envp->set_cachesize(envp, 0, NUM2UINT(value), 0)); #else envp->mp_size = NUM2INT(value); #endif break; default: Check_Type(value, T_ARRAY); if (RARRAY_LEN(value) < 3) { rb_raise(bdb_eFatal, "expected 3 values for cachesize"); } #if HAVE_ST_DB_ENV_SET_CACHESIZE bdb_test_error(envp->set_cachesize(envp, NUM2UINT(RARRAY_PTR(value)[0]), NUM2UINT(RARRAY_PTR(value)[1]), NUM2INT(RARRAY_PTR(value)[2]))); #else envp->mp_size = NUM2INT(RARRAY_PTR(value)[1]); #endif break; } } #if HAVE_ST_DB_ENV_SET_REGION_INIT || HAVE_DB_ENV_SET_REGION_INIT else if (strcmp(options, "set_region_init") == 0) { #if HAVE_ST_DB_ENV_SET_REGION_INIT bdb_test_error(envp->set_region_init(envp, NUM2INT(value))); #else bdb_test_error(db_env_set_region_init(NUM2INT(value))); #endif } #endif #if HAVE_ST_DB_ENV_SET_TAS_SPINS || HAVE_DB_ENV_SET_TAS_SPINS else if (strcmp(options, "set_tas_spins") == 0) { #if HAVE_ST_DB_ENV_SET_TAS_SPINS bdb_test_error(envp->set_tas_spins(envp, NUM2INT(value))); #else bdb_test_error(db_env_set_tas_spins(NUM2INT(value))); #endif } #endif #if HAVE_ST_DB_ENV_SET_TX_MAX else if (strcmp(options, "set_tx_max") == 0) { bdb_test_error(envp->set_tx_max(envp, NUM2INT(value))); } #endif #if HAVE_ST_DB_ENV_SET_TX_TIMESTAMP else if (strcmp(options, "set_tx_timestamp") == 0) { time_t ti; value = rb_Integer(value); ti = (time_t)NUM2INT(value); bdb_test_error(envp->set_tx_timestamp(envp, &ti)); } #endif #if HAVE_ST_DB_ENV_DB_VERBOSE else if (strcmp(options, "set_verbose") == 0) { envp->db_verbose = NUM2INT(value); } #endif #if HAVE_ST_DB_ENV_SET_VERBOSE #if DB_VERB_CHECKPOINT else if (strcmp(options, "set_verb_chkpoint") == 0) { bdb_test_error(envp->set_verbose(envp, DB_VERB_CHKPOINT, NUM2INT(value))); } #endif else if (strcmp(options, "set_verb_deadlock") == 0) { bdb_test_error(envp->set_verbose(envp, DB_VERB_DEADLOCK, NUM2INT(value))); } else if (strcmp(options, "set_verb_recovery") == 0) { bdb_test_error(envp->set_verbose(envp, DB_VERB_RECOVERY, NUM2INT(value))); } else if (strcmp(options, "set_verb_waitsfor") == 0) { bdb_test_error(envp->set_verbose(envp, DB_VERB_WAITSFOR, NUM2INT(value))); } #if DB_VERB_REPLICATION else if (strcmp(options, "set_verb_replication") == 0) { bdb_test_error(envp->set_verbose(envp, DB_VERB_REPLICATION, NUM2INT(value))); } #endif #endif else if (strcmp(options, "set_lk_detect") == 0) { #if HAVE_ST_DB_ENV_LK_DETECT envp->lk_detect = NUM2INT(value); #endif #if HAVE_ST_DB_ENV_SET_LK_DETECT bdb_test_error(envp->set_lk_detect(envp, NUM2INT(value))); #endif } #if HAVE_ST_DB_ENV_LK_MAX || HAVE_ST_DB_ENV_SET_LK_MAX else if (strcmp(options, "set_lk_max") == 0) { #if HAVE_ST_DB_ENV_LK_MAX envp->lk_max = NUM2INT(value); #else bdb_test_error(envp->set_lk_max(envp, NUM2INT(value))); #endif } #endif #if HAVE_ST_DB_ENV_LK_CONFLICTS || HAVE_ST_DB_ENV_SET_LK_CONFLICTS else if (strcmp(options, "set_lk_conflicts") == 0) { int i, j, l, v; unsigned char *conflits, *p; Check_Type(value, T_ARRAY); l = RARRAY_LEN(value); p = conflits = ALLOC_N(unsigned char, l * l); for (i = 0; i < l; i++) { if (TYPE(RARRAY_PTR(value)[i]) != T_ARRAY || RARRAY_LEN(RARRAY_PTR(value)[i]) != l) { free(conflits); rb_raise(bdb_eFatal, "invalid array for lk_conflicts"); } for (j = 0; j < l; j++, p++) { if (TYPE(RARRAY_PTR(RARRAY_PTR(value)[i])[j]) != T_FIXNUM) { free(conflits); rb_raise(bdb_eFatal, "invalid value for lk_conflicts"); } v = NUM2INT(RARRAY_PTR(RARRAY_PTR(value)[i])[j]); if (v != 0 && v != 1) { free(conflits); rb_raise(bdb_eFatal, "invalid value for lk_conflicts"); } *p = (unsigned char)v; } } #if HAVE_ST_DB_ENV_LK_CONFLICTS envp->lk_modes = l; envp->lk_conflicts = conflits; #else bdb_test_error(envp->set_lk_conflicts(envp, conflits, l)); #endif } #endif #if HAVE_ST_DB_ENV_SET_LK_MAX_LOCKS else if (strcmp(options, "set_lk_max_locks") == 0) { bdb_test_error(envp->set_lk_max_locks(envp, NUM2INT(value))); } #endif #if HAVE_ST_DB_ENV_SET_LK_MAX_LOCKERS else if (strcmp(options, "set_lk_max_lockers") == 0) { bdb_test_error(envp->set_lk_max_lockers(envp, NUM2INT(value))); } #endif #if HAVE_ST_DB_ENV_SET_LK_MAX_OBJECTS else if (strcmp(options, "set_lk_max_objects") == 0) { bdb_test_error(envp->set_lk_max_objects(envp, NUM2INT(value))); } #endif else if (strcmp(options, "set_lg_max") == 0) { db_st->lg_max = NUM2INT(value); } #if HAVE_ST_DB_ENV_SET_LG_BSIZE else if (strcmp(options, "set_lg_bsize") == 0) { db_st->lg_bsize = NUM2INT(value); } #endif else if (strcmp(options, "set_data_dir") == 0) { SafeStringValue(value); #if HAVE_ST_DB_ENV_SET_DATA_DIR bdb_test_error(envp->set_data_dir(envp, StringValuePtr(value))); #else { char *tmp; tmp = ALLOCA_N(char, strlen("DB_DATA_DIR") + RSTRING_LEN(value) + 2); sprintf(tmp, "DB_DATA_DIR %s", StringValuePtr(value)); rb_ary_push(db_st->config, rb_str_new2(tmp)); } #endif } else if (strcmp(options, "set_lg_dir") == 0) { SafeStringValue(value); #if HAVE_ST_DB_ENV_SET_LG_DIR bdb_test_error(envp->set_lg_dir(envp, StringValuePtr(value))); #else { char *tmp; tmp = ALLOCA_N(char, strlen("DB_LOG_DIR") + RSTRING_LEN(value) + 2); sprintf(tmp, "DB_LOG_DIR %s", StringValuePtr(value)); rb_ary_push(db_st->config, rb_str_new2(tmp)); } #endif } else if (strcmp(options, "set_tmp_dir") == 0) { SafeStringValue(value); #if HAVE_ST_DB_ENV_SET_TMP_DIR bdb_test_error(envp->set_tmp_dir(envp, StringValuePtr(value))); #else { char *tmp; tmp = ALLOCA_N(char, strlen("DB_TMP_DIR") + RSTRING_LEN(value) + 2); sprintf(tmp, "DB_TMP_DIR %s", StringValuePtr(value)); rb_ary_push(db_st->config, rb_str_new2(tmp)); } #endif } #if HAVE_ST_DB_ENV_SET_SERVER || HAVE_ST_DB_ENV_SET_RPC_SERVER else if (strcmp(options, "set_server") == 0 || strcmp(options, "set_rpc_server") == 0) { char *host; long sv_timeout, cl_timeout; unsigned long flags; host = 0; sv_timeout = cl_timeout = 0; flags = 0; switch (TYPE(value)) { case T_STRING: SafeStringValue(value); host = StringValuePtr(value); break; case T_ARRAY: switch (RARRAY_LEN(value)) { default: case 3: sv_timeout = NUM2INT(RARRAY_PTR(value)[2]); case 2: cl_timeout = NUM2INT(RARRAY_PTR(value)[1]); case 1: SafeStringValue(RARRAY_PTR(value)[0]); host = StringValuePtr(RARRAY_PTR(value)[0]); break; case 0: rb_raise(bdb_eFatal, "Empty array for \"set_server\""); break; } break; default: rb_raise(bdb_eFatal, "Invalid type for \"set_server\""); break; } #if HAVE_ST_DB_ENV_SET_RPC_SERVER bdb_test_error(envp->set_rpc_server(envp, NULL, host, cl_timeout, sv_timeout, flags)); #else bdb_test_error(envp->set_server(envp, host, cl_timeout, sv_timeout, flags)); #endif } #endif #if HAVE_ST_DB_ENV_SET_FLAGS else if (strcmp(options, "set_flags") == 0) { bdb_test_error(envp->set_flags(envp, NUM2UINT(value), 1)); } #endif else if (strcmp(options, "marshal") == 0) { switch (value) { case Qtrue: envst->marshal = bdb_mMarshal; break; case Qfalse: envst->marshal = Qfalse; break; default: if (!bdb_respond_to(value, bdb_id_load) || !bdb_respond_to(value, bdb_id_dump)) { rb_raise(bdb_eFatal, "marshal value must be true or false"); } envst->marshal = value; break; } } else if (strcmp(options, "thread") == 0) { if (RTEST(value)) { envst->options &= ~BDB_NO_THREAD; } else { envst->options |= BDB_NO_THREAD; } } #if HAVE_ST_DB_ENV_REP_SET_TRANSPORT || HAVE_ST_DB_ENV_SET_REP_TRANSPORT else if (strcmp(options, "set_rep_transport") == 0 || strcmp(options, "rep_set_transport") == 0) { if (TYPE(value) != T_ARRAY || RARRAY_LEN(value) != 2) { rb_raise(bdb_eFatal, "expected an Array of length 2 for set_rep_transport"); } if (!FIXNUM_P(RARRAY_PTR(value)[0])) { rb_raise(bdb_eFatal, "expected a Fixnum for the 1st arg of set_rep_transport"); } if (!rb_respond_to(RARRAY_PTR(value)[1], bdb_id_call)) { rb_raise(bdb_eFatal, "2nd arg must respond to #call"); } envst->rep_transport = RARRAY_PTR(value)[1]; #if HAVE_ST_DB_ENV_REP_SET_TRANSPORT bdb_test_error(envst->envp->rep_set_transport(envst->envp, NUM2INT(RARRAY_PTR(value)[0]), bdb_env_rep_transport)); #else bdb_test_error(envst->envp->set_rep_transport(envst->envp, NUM2INT(RARRAY_PTR(value)[0]), bdb_env_rep_transport)); #endif envst->options |= BDB_REP_TRANSPORT; } #endif #if HAVE_ST_DB_ENV_SET_TIMEOUT else if (strcmp(options, "set_timeout") == 0) { if (TYPE(value) == T_ARRAY) { if (RARRAY_LEN(value) >= 1 && !NIL_P(RARRAY_PTR(value)[0])) { bdb_test_error(envst->envp->set_timeout(envst->envp, NUM2UINT(RARRAY_PTR(value)[0]), DB_SET_TXN_TIMEOUT)); } if (RARRAY_LEN(value) == 2 && !NIL_P(RARRAY_PTR(value)[1])) { bdb_test_error(envst->envp->set_timeout(envst->envp, NUM2UINT(RARRAY_PTR(value)[0]), DB_SET_LOCK_TIMEOUT)); } } else { bdb_test_error(envst->envp->set_timeout(envst->envp, NUM2UINT(value), DB_SET_TXN_TIMEOUT)); } } else if (strcmp(options, "set_txn_timeout") == 0) { bdb_test_error(envst->envp->set_timeout(envst->envp, NUM2UINT(value), DB_SET_TXN_TIMEOUT)); } else if (strcmp(options, "set_lock_timeout") == 0) { bdb_test_error(envst->envp->set_timeout(envst->envp, NUM2UINT(value), DB_SET_LOCK_TIMEOUT)); } #endif #if HAVE_ST_DB_ENV_SET_ENCRYPT else if (strcmp(options, "set_encrypt") == 0) { char *passwd; int flags = DB_ENCRYPT_AES; if (TYPE(value) == T_ARRAY) { if (RARRAY_LEN(value) != 2) { rb_raise(bdb_eFatal, "Expected an Array with 2 values"); } passwd = StringValuePtr(RARRAY_PTR(value)[0]); flags = NUM2INT(RARRAY_PTR(value)[1]); } else { passwd = StringValuePtr(value); } bdb_test_error(envst->envp->set_encrypt(envst->envp, passwd, flags)); envst->options |= BDB_ENV_ENCRYPT; } #endif #if HAVE_ST_DB_ENV_SET_REP_LIMIT || HAVE_ST_DB_ENV_REP_SET_LIMIT else if (strcmp(options, "set_rep_limit") == 0 || strcmp(options, "rep_set_limit") == 0) { u_int32_t gbytes, bytes; gbytes = bytes = 0; if (TYPE(value) == T_ARRAY) { if (RARRAY_LEN(value) != 2) { rb_raise(bdb_eFatal, "Expected an Array with 2 values"); } gbytes = NUM2UINT(RARRAY_PTR(value)[0]); bytes = NUM2UINT(RARRAY_PTR(value)[1]); } else { bytes = NUM2UINT(RARRAY_PTR(value)[1]); } #if HAVE_ST_DB_ENV_REP_SET_LIMIT bdb_test_error(envst->envp->rep_set_limit(envst->envp, gbytes, bytes)); #else bdb_test_error(envst->envp->set_rep_limit(envst->envp, gbytes, bytes)); #endif } #endif #if HAVE_ST_DB_ENV_SET_FEEBACK else if (strcmp(options, "set_feedback") == 0) { if (!rb_respond_to(value, bdb_id_call)) { rb_raise(bdb_eFatal, "arg must respond to #call"); } envst->options |= BDB_FEEDBACK; envst->feedback = value; envst->envp->set_feedback(envst->envp, bdb_env_feedback); } #endif #if HAVE_ST_DB_ENV_SET_APP_DISPATCH else if (strcmp(options, "set_app_dispatch") == 0) { if (!rb_respond_to(value, bdb_id_call)) { rb_raise(bdb_eFatal, "arg must respond to #call"); } envst->options |= BDB_APP_DISPATCH; envst->app_dispatch = value; envst->envp->set_app_dispatch(envst->envp, bdb_env_app_dispatch); } #endif #if HAVE_ST_DB_ENV_SET_MSGCALL else if (strcmp(options, "set_msgcall") == 0) { if (!rb_respond_to(value, bdb_id_call)) { rb_raise(bdb_eFatal, "arg must respond to #call"); } envst->msgcall = value; envst->envp->set_msgcall(envst->envp, bdb_env_msgcall); } #endif #if HAVE_ST_DB_ENV_SET_THREAD_ID else if (strcmp(options, "set_thread_id") == 0) { if (!rb_respond_to(value, bdb_id_call)) { rb_raise(bdb_eFatal, "arg must respond to #call"); } envst->thread_id = value; envst->envp->set_thread_id(envst->envp, bdb_env_thread_id); } #endif #if HAVE_ST_DB_ENV_SET_THREAD_ID_STRING else if (strcmp(options, "set_thread_id_string") == 0) { if (!rb_respond_to(value, bdb_id_call)) { rb_raise(bdb_eFatal, "arg must respond to #call"); } envst->thread_id_string = value; envst->envp->set_thread_id_string(envst->envp, bdb_env_thread_id_string); } #endif #if HAVE_ST_DB_ENV_SET_ISALIVE else if (strcmp(options, "set_isalive") == 0) { if (!rb_respond_to(value, bdb_id_call)) { rb_raise(bdb_eFatal, "arg must respond to #call"); } envst->isalive = value; envst->envp->set_isalive(envst->envp, bdb_env_isalive); } #endif #if HAVE_ST_DB_ENV_SET_SHM_KEY else if (strcmp(options, "set_shm_key") == 0) { bdb_test_error(envst->envp->set_shm_key(envst->envp, NUM2INT(value))); } #endif #if HAVE_ST_DB_ENV_REP_SET_NSITES else if (strcmp(options, "set_rep_nsites") == 0 || strcmp(options, "rep_set_nsites") == 0) { bdb_test_error(envst->envp->rep_set_nsites(envst->envp, NUM2INT(value))); } #endif #if HAVE_ST_DB_ENV_REP_SET_PRIORITY else if (strcmp(options, "set_rep_priority") == 0 || strcmp(options, "rep_set_priority") == 0) { bdb_test_error(envst->envp->rep_set_priority(envst->envp, NUM2INT(value))); } #endif #if HAVE_ST_DB_ENV_REP_SET_CONFIG else if (strcmp(options, "set_rep_config") == 0 || strcmp(options, "rep_set_config") == 0) { int onoff = 0; if (TYPE(value) != T_ARRAY || RARRAY_LEN(value) != 2) { rb_raise(bdb_eFatal, "Expected an Array with 2 values"); } if (RARRAY_PTR(value)[1] == Qtrue) { onoff = 1; } else if (RARRAY_PTR(value)[1] == Qfalse || RARRAY_PTR(value)[1] == Qnil) { onoff = 0; } else { onoff = NUM2UINT(RARRAY_PTR(value)[1]); } bdb_test_error(envst->envp->rep_set_config(envst->envp, NUM2UINT(RARRAY_PTR(value)[0]), onoff)); } #endif #if HAVE_ST_DB_ENV_REP_SET_TIMEOUT else if (strcmp(options, "set_rep_timeout") == 0 || strcmp(options, "rep_set_timeout") == 0) { if (TYPE(value) != T_ARRAY || RARRAY_LEN(value) != 2) { rb_raise(bdb_eFatal, "Expected an Array with 2 values"); } bdb_test_error(envst->envp->rep_set_timeout(envst->envp, NUM2UINT(RARRAY_PTR(value)[0]), NUM2UINT(RARRAY_PTR(value)[1]))); } #endif #if HAVE_ST_DB_ENV_REPMGR_SET_LOCAL_SITE else if (strcmp(options, "repmgr_set_local_site") == 0 || strcmp(options, "set_repmgr_local_site") == 0) { if (TYPE(value) != T_ARRAY || RARRAY_LEN(value) != 2) { rb_raise(bdb_eFatal, "Expected an Array with 2 values"); } bdb_test_error(envst->envp->repmgr_set_local_site(envst->envp, StringValuePtr(RARRAY_PTR(value)[0]), NUM2UINT(RARRAY_PTR(value)[1]), 0)); } #endif #if HAVE_ST_DB_ENV_REPMGR_ADD_REMOTE_SITE else if (strcmp(options, "repmgr_add_remote_site") == 0) { int flags = 0; if (TYPE(value) != T_ARRAY || RARRAY_LEN(value) < 2 || RARRAY_LEN(value) > 4) { rb_raise(bdb_eFatal, "Expected an Array with 3 values"); } if (RARRAY_LEN(value) == 3) { flags = NUM2INT(RARRAY_PTR(value)[2]); } bdb_test_error(envst->envp->repmgr_add_remote_site(envst->envp, StringValuePtr(RARRAY_PTR(value)[0]), NUM2UINT(RARRAY_PTR(value)[1]), NULL, flags)); } #endif #if HAVE_ST_DB_ENV_REPMGR_SET_ACK_POLICY else if (strcmp(options, "repmgr_set_ack_policy") == 0 || strcmp(options, "set_repmgr_ack_policy") == 0) { bdb_test_error(envst->envp->repmgr_set_ack_policy(envst->envp, NUM2UINT(value))); } #endif #if HAVE_ST_DB_ENV_SET_INTERMEDIATE_DIR_MODE else if (strcmp(options, "set_intermediate_dir_mode") == 0) { char *dir; dir = StringValuePtr(value); bdb_test_error(envst->envp->set_intermediate_dir_mode(envst->envp, dir)); } #endif return Qnil; } struct env_iv { bdb_ENV *envst; VALUE env; }; #if BDB_NEED_ENV_CURRENT static VALUE bdb_env_aref() { VALUE obj; bdb_ENV *envst; GetIdEnv1(obj, envst); return obj; } #endif VALUE bdb_protect_close(VALUE obj) { return rb_funcall2(obj, rb_intern("close"), 0, 0); } static void bdb_final(bdb_ENV *envst) { VALUE *ary; int i; ary = envst->db_ary.ptr; if (ary) { envst->db_ary.mark = Qtrue; for (i = 0; i < envst->db_ary.len; i++) { if (rb_respond_to(ary[i], rb_intern("close"))) { bdb_protect_close(ary[i]); } } envst->db_ary.mark = Qfalse; envst->db_ary.total = envst->db_ary.len = 0; envst->db_ary.ptr = 0; free(ary); } if (envst->envp) { if (!(envst->options & BDB_ENV_NOT_OPEN)) { #if HAVE_ST_DB_ENV_CLOSE envst->envp->close(envst->envp, 0); #else db_appexit(envst->envp); free(envst->envp); #endif } envst->envp = NULL; } #if BDB_NEED_ENV_CURRENT { VALUE obj; bdb_ENV *thst; int status = 0; obj = bdb_env_aref(); if (!status && !NIL_P(obj)) { Data_Get_Struct(obj, bdb_ENV, thst); if (thst == envst) { rb_thread_local_aset(rb_thread_current(), bdb_id_current_env, Qnil); } } } #endif } static void bdb_env_free(bdb_ENV *envst) { bdb_final(envst); free(envst); } static VALUE bdb_env_close(VALUE obj) { bdb_ENV *envst; if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4) { rb_raise(rb_eSecurityError, "Insecure: can't close the environnement"); } GetEnvDB(obj, envst); bdb_final(envst); RDATA(obj)->dfree = free; return Qnil; } static void bdb_env_mark(bdb_ENV *envst) { rb_gc_mark(envst->marshal); #if HAVE_ST_DB_ENV_SET_REP_TRANSPORT rb_gc_mark(envst->rep_transport); #endif #if HAVE_ST_DB_ENV_SET_APP_DISPATCH rb_gc_mark(envst->app_dispatch); #endif #if HAVE_ST_DB_ENV_SET_MSGCALL rb_gc_mark(envst->msgcall); #endif #if HAVE_ST_DB_ENV_SET_THREAD_ID rb_gc_mark(envst->thread_id); #endif #if HAVE_ST_DB_ENV_SET_THREAD_ID_STRING rb_gc_mark(envst->thread_id_string); #endif #if HAVE_ST_DB_ENV_SET_ISALIVE rb_gc_mark(envst->isalive); #endif #if HAVE_ST_DB_ENV_SET_FEEDBACK rb_gc_mark(envst->feedback); #endif #if HAVE_ST_DB_ENV_SET_EVENT_NOTIFY rb_gc_mark(envst->event_notify); #endif rb_gc_mark(envst->home); bdb_ary_mark(&envst->db_ary); } VALUE bdb_env_open_db(int argc, VALUE *argv, VALUE obj) { VALUE cl; if (argc < 1) rb_raise(bdb_eFatal, "Invalid number of arguments"); cl = argv[0]; if (FIXNUM_P(cl)) { switch (NUM2INT(cl)) { case DB_BTREE: cl = bdb_cBtree; break; case DB_HASH: cl = bdb_cHash; break; case DB_RECNO: cl = bdb_cRecno; break; #if HAVE_CONST_DB_QUEUE case DB_QUEUE: cl = bdb_cQueue; break; #endif case DB_UNKNOWN: cl = bdb_cUnknown; break; default: rb_raise(bdb_eFatal, "Unknown database type"); } } else if (TYPE(cl) != T_CLASS) { cl = CLASS_OF(cl); } MEMCPY(argv, argv + 1, VALUE, argc - 1); if (argc > 1 && TYPE(argv[argc - 2]) == T_HASH) { argc--; } else { argv[argc - 1] = rb_hash_new(); } if (rb_obj_is_kind_of(obj, bdb_cEnv)) { rb_hash_aset(argv[argc - 1], rb_tainted_str_new2("env"), obj); } else { rb_hash_aset(argv[argc - 1], rb_tainted_str_new2("txn"), obj); } return rb_funcall2(cl, rb_intern("new"), argc, argv); } #if HAVE_DB_ENV_ERRCALL_3 void bdb_env_errcall(const DB_ENV *env, const char *errpfx, const char *msg) { bdb_errcall = 1; bdb_errstr = rb_tainted_str_new2(msg); } #else void bdb_env_errcall(const char *errpfx, char *msg) { bdb_errcall = 1; bdb_errstr = rb_tainted_str_new2(msg); } #endif VALUE bdb_return_err() { if (bdb_errcall) { bdb_errcall = 0; return bdb_errstr; } return Qnil; } #ifndef NT #ifdef HAVE_SYS_TIME_H #include #else struct timeval { long tv_sec; long tv_usec; }; #endif /* HAVE_SYS_TIME_H */ #endif /* NT */ static int bdb_func_sleep(unsigned long sec, unsigned long usec) { struct timeval timeout; timeout.tv_sec = sec; timeout.tv_usec = usec; rb_thread_wait_for(timeout); return 0; } #if HAVE_ST_DB_ENV_SET_FUNC_YIELD || HAVE_DB_JUMP_SET || HAVE_DB_ENV_SET_FUNC_SLEEP static int bdb_func_yield() { rb_thread_schedule(); return 0; } #endif #if 0 static void * bdb_func_malloc(size_t size) { return malloc(size); } #endif static VALUE bdb_set_func(bdb_ENV *envst) { #if HAVE_DB_ENV_SET_FUNC_YIELD #if HAVE_DB_ENV_SET_FUNC_SLEEP bdb_test_error(db_env_set_func_yield(bdb_func_yield)); bdb_test_error(db_env_set_func_sleep(bdb_func_sleep)); #else bdb_test_error(db_env_set_func_yield(bdb_func_sleep)); #endif #elif HAVE_ST_DB_ENV_SET_FUNC_SLEEP || HAVE_ST_DB_ENV_SET_FUNC_YIELD #if HAVE_ST_DB_ENV_SET_FUNC_SLEEP bdb_test_error(envst->envp->set_func_sleep(envst->envp, bdb_func_sleep)); #endif #if HAVE_ST_DB_ENV_SET_FUNC_YIELD bdb_test_error(envst->envp->set_func_yield(envst->envp, bdb_func_yield)); #endif #elif HAVE_DB_JUMP_SET bdb_test_error(db_jump_set((void *)bdb_func_sleep, DB_FUNC_SLEEP)); bdb_test_error(db_jump_set((void *)bdb_func_yield, DB_FUNC_YIELD)); #endif return Qtrue; } static VALUE bdb_env_each_options(VALUE opt, VALUE stobj) { VALUE res; DB_ENV *envp; struct db_stoptions *db_st; res = rb_iterate(rb_each, opt, bdb_env_i_options, stobj); Data_Get_Struct(stobj, struct db_stoptions, db_st); envp = db_st->env->envp; #if HAVE_ST_DB_ENV_SET_LG_BSIZE if (db_st->lg_bsize) { bdb_test_error(envp->set_lg_bsize(envp, db_st->lg_bsize)); } #endif if (db_st->lg_max) { #if HAVE_ST_DB_ENV_LG_MAX envp->lg_max = db_st->lg_max; #else bdb_test_error(envp->set_lg_max(envp, db_st->lg_max)); #endif } return res; } static VALUE bdb_env_s_i_options(VALUE obj, int *flags) { char *options; VALUE key, value; key = rb_ary_entry(obj, 0); value = rb_ary_entry(obj, 1); key = rb_obj_as_string(key); options = StringValuePtr(key); if (strcmp(options, "env_flags") == 0) { *flags = NUM2INT(value); } #if HAVE_CONST_DB_CLIENT else if (strcmp(options, "set_rpc_server") == 0 || strcmp(options, "set_server") == 0) { *flags |= DB_CLIENT; } #endif return Qnil; } #if HAVE_ST_DB_ENV_SET_ENV_NOTIFY static VALUE bdb_env_s_j_options(VALUE obj, VALUE *res) { char *options; VALUE key, value; key = rb_ary_entry(obj, 0); value = rb_ary_entry(obj, 1); key = rb_obj_as_string(key); options = StringValuePtr(key); if (strcmp(options, "set_event_notify") == 0) { *res = value; } return Qnil; } #endif static VALUE bdb_env_s_alloc(VALUE obj) { VALUE res; bdb_ENV *envst; res = Data_Make_Struct(obj, bdb_ENV, bdb_env_mark, bdb_env_free, envst); envst->options |= BDB_ENV_NOT_OPEN; return res; } static VALUE bdb_env_s_new(int argc, VALUE *argv, VALUE obj) { bdb_ENV *envst; VALUE res; int flags = 0; #ifdef HAVE_RB_DEFINE_ALLOC_FUNC res = rb_obj_alloc(obj); #else res = rb_funcall2(obj, rb_intern("allocate"), 0, 0); #endif Data_Get_Struct(res, bdb_ENV, envst); #if ! HAVE_DB_ENV_CREATE envst->envp = ALLOC(DB_ENV); MEMZERO(envst->envp, DB_ENV, 1); envst->envp->db_errpfx = "BDB::"; envst->envp->db_errcall = bdb_env_errcall; #else if (argc && TYPE(argv[argc - 1]) == T_HASH) { rb_iterate(rb_each, argv[argc - 1], bdb_env_s_i_options, (VALUE)&flags); } bdb_test_error(db_env_create(&(envst->envp), flags)); envst->envp->set_errpfx(envst->envp, "BDB::"); envst->envp->set_errcall(envst->envp, bdb_env_errcall); #if HAVE_ST_DB_ENV_SET_ALLOC bdb_test_error(envst->envp->set_alloc(envst->envp, malloc, realloc, free)); #endif #if HAVE_ST_DB_ENV_SET_ENV_NOTIFY if (argc && TYPE(argv[argc - 1]) == T_HASH) { VALUE value = Qnil; rb_iterate(rb_each, argv[argc - 1], bdb_env_s_j_options, (VALUE)&value); if (!NIL_P(value)) { if (!rb_respond_to(value, bdb_id_call)) { rb_raise(bdb_eFatal, "arg must respond to #call"); } envst->event_notify = value; envst->envp->set_event_notify(envst->envp, bdb_env_event_notify); } } #endif #endif rb_obj_call_init(res, argc, argv); return res; } #if HAVE_ST_DB_ENV_SET_ALLOC VALUE bdb_env_s_rslbl(int argc, VALUE *argv, VALUE obj, DB_ENV *env) { bdb_ENV *envst; VALUE res; #ifdef HAVE_RB_DEFINE_ALLOC_FUNC res = rb_obj_alloc(obj); #else res = rb_funcall2(obj, rb_intern("allocate"), 0, 0); #endif Data_Get_Struct(res, bdb_ENV, envst); envst->envp = env; envst->envp->set_errpfx(envst->envp, "BDB::"); envst->envp->set_errcall(envst->envp, bdb_env_errcall); bdb_test_error(envst->envp->set_alloc(envst->envp, malloc, realloc, free)); rb_obj_call_init(res, argc, argv); return res; } #endif VALUE bdb_env_init(int argc, VALUE *argv, VALUE obj) { DB_ENV *envp; bdb_ENV *envst; VALUE a, c, d; char *db_home, **db_config; int ret, mode, flags; VALUE st_config; VALUE envid; envid = 0; st_config = 0; db_config = 0; mode = flags = 0; if (!RDATA(obj)->dmark) { RDATA(obj)->dmark = (RUBY_DATA_FUNC)bdb_env_mark; } Data_Get_Struct(obj, bdb_ENV, envst); #if HAVE_ST_DB_ENV_SET_ERRCALL envst->envp->set_errcall(envst->envp, bdb_env_errcall); #endif envp = envst->envp; #if HAVE_ST_DB_ENV_SET_ENCRYPT if (rb_const_defined(CLASS_OF(obj), rb_intern("BDB_ENCRYPT"))) { char *passwd; int flags = DB_ENCRYPT_AES; VALUE value = rb_const_get(CLASS_OF(obj), rb_intern("BDB_ENCRYPT")); if (TYPE(value) == T_ARRAY) { if (RARRAY_LEN(value) != 2) { rb_raise(bdb_eFatal, "Expected an Array with 2 values"); } passwd = StringValuePtr(RARRAY_PTR(value)[0]); flags = NUM2INT(RARRAY_PTR(value)[1]); } else { passwd = StringValuePtr(value); } bdb_test_error(envp->set_encrypt(envp, passwd, flags)); envst->options |= BDB_ENV_ENCRYPT; } #endif if (argc && TYPE(argv[argc - 1]) == T_HASH) { int i; VALUE db_stobj; struct db_stoptions *db_st; st_config = rb_ary_new(); db_stobj = Data_Make_Struct(rb_cObject, struct db_stoptions, 0, free, db_st); db_st->env = envst; db_st->config = st_config; bdb_env_each_options(argv[argc - 1], db_stobj); if (RARRAY_LEN(st_config) > 0) { db_config = ALLOCA_N(char *, RARRAY_LEN(st_config) + 1); for (i = 0; i < RARRAY_LEN(st_config); i++) { db_config[i] = StringValuePtr(RARRAY_PTR(st_config)[i]); } db_config[RARRAY_LEN(st_config)] = 0; } argc--; } rb_scan_args(argc, argv, "12", &a, &c, &d); SafeStringValue(a); db_home = StringValuePtr(a); switch (argc) { case 3: mode = NUM2INT(d); case 2: flags = NUM2INT(c); break; } if (flags & DB_CREATE) { rb_secure(4); } if (flags & DB_USE_ENVIRON) { rb_secure(1); } #ifndef BDB_NO_THREAD_COMPILE if (!(envst->options & BDB_NO_THREAD)) { bdb_set_func(envst); flags |= DB_THREAD; } #endif #if HAVE_DB_APPINIT if ((ret = db_appinit(db_home, db_config, envp, flags)) != 0) { if (envst->envp) { free(envst->envp); } envst->envp = NULL; if (bdb_errcall) { bdb_errcall = 0; rb_raise(bdb_eFatal, "%s -- %s", StringValuePtr(bdb_errstr), db_strerror(ret)); } else rb_raise(bdb_eFatal, "%s", db_strerror(ret)); } #else #if HAVE_ST_DB_ENV_SET_EVENT_NOTIFY if (envst->event_notify == 0 && rb_respond_to(obj, id_event_notify) == Qtrue) { envp->set_event_notify(envp, bdb_env_event_notify); } #endif #if HAVE_ST_DB_ENV_SET_REP_TRANSPORT || HAVE_ST_DB_ENV_REP_SET_TRANSPORT if (envst->rep_transport == 0 && rb_respond_to(obj, rb_intern("bdb_rep_transport")) == Qtrue) { if (!rb_const_defined(CLASS_OF(obj), rb_intern("ENVID"))) { rb_raise(bdb_eFatal, "ENVID must be defined to use rep_transport"); } envid = rb_const_get(CLASS_OF(obj), rb_intern("ENVID")); #if HAVE_ST_DB_ENV_REP_SET_TRANSPORT bdb_test_error(envp->rep_set_transport(envp, NUM2INT(envid), bdb_env_rep_transport)); #else bdb_test_error(envp->set_rep_transport(envp, NUM2INT(envid), bdb_env_rep_transport)); #endif envst->options |= BDB_REP_TRANSPORT; } #endif #if HAVE_ST_DB_ENV_SET_FEEDBACK if (envst->feedback == 0 && rb_respond_to(obj, id_feedback) == Qtrue) { envp->set_feedback(envp, bdb_env_feedback); envst->options |= BDB_FEEDBACK; } #endif #if HAVE_ST_DB_ENV_SET_APP_DISPATCH if (envst->app_dispatch == 0 && rb_respond_to(obj, id_app_dispatch) == Qtrue) { envp->set_app_dispatch(envp, bdb_env_app_dispatch); envst->options |= BDB_APP_DISPATCH; } #endif #if HAVE_ST_DB_ENV_SET_MSGCALL if (envst->msgcall == 0 && rb_respond_to(obj, id_msgcall) == Qtrue) { envp->set_msgcall(envp, bdb_env_msgcall); } #endif #if HAVE_ST_DB_ENV_SET_THREAD_ID if (envst->thread_id == 0 && rb_respond_to(obj, id_thread_id) == Qtrue) { envp->set_thread_id(envp, bdb_env_thread_id); } #endif #if HAVE_ST_DB_ENV_SET_THREAD_ID_STRING if (envst->thread_id_string == 0 && rb_respond_to(obj, id_thread_id_string) == Qtrue) { envp->set_thread_id_string(envp, bdb_env_thread_id_string); } #endif #if HAVE_ST_DB_ENV_SET_ISALIVE if (envst->isalive == 0 && rb_respond_to(obj, id_isalive) == Qtrue) { envp->set_isalive(envp, bdb_env_isalive); } #endif #if HAVE_ENV_OPEN_DB_CONFIG if ((ret = envp->open(envp, db_home, db_config, flags, mode)) != 0) #else if ((ret = envp->open(envp, db_home, flags, mode)) != 0) #endif { envp->close(envp, 0); envst->envp = NULL; if (bdb_errcall) { bdb_errcall = 0; rb_raise(bdb_eFatal, "%s -- %s", StringValuePtr(bdb_errstr), db_strerror(ret)); } else rb_raise(bdb_eFatal, "%s", db_strerror(ret)); } #endif envst->options &= ~BDB_ENV_NOT_OPEN; if (flags & DB_INIT_LOCK) { envst->options |= BDB_INIT_LOCK; } #if HAVE_CONST_DB_AUTO_COMMIT if (flags & DB_INIT_TXN) { envst->options |= BDB_AUTO_COMMIT; } #endif envst->home = rb_tainted_str_new2(db_home); OBJ_FREEZE(envst->home); #if HAVE_CONST_DB_INIT_REP if (flags & DB_INIT_REP) { envst->options |= BDB_REP_TRANSPORT; } #endif if (envst->options & BDB_NEED_ENV_CURRENT) { rb_thread_local_aset(rb_thread_current(), bdb_id_current_env, obj); } return obj; } static VALUE bdb_env_internal_close(VALUE obj) { return rb_funcall2(obj, rb_intern("close"), 0, 0); } static VALUE bdb_env_s_open(int argc, VALUE *argv, VALUE obj) { VALUE res = rb_funcall2(obj, rb_intern("new"), argc, argv); if (rb_block_given_p()) { return rb_ensure(rb_yield, res, bdb_env_internal_close, res); } return res; } static VALUE bdb_env_s_remove(int argc, VALUE *argv, VALUE obj) { DB_ENV *envp; VALUE a, b; char *db_home; int flag = 0; rb_secure(2); if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { flag = NUM2INT(b); } db_home = StringValuePtr(a); #if ! HAVE_DB_ENV_CREATE envp = ALLOCA_N(DB_ENV, 1); MEMZERO(envp, DB_ENV, 1); envp->db_errpfx = "BDB::"; envp->db_errcall = bdb_env_errcall; if (lock_unlink(db_home, flag, envp) == EBUSY) { rb_raise(bdb_eFatal, "The shared memory region was in use"); } if (log_unlink(db_home, flag, envp) == EBUSY) { rb_raise(bdb_eFatal, "The shared memory region was in use"); } if (memp_unlink(db_home, flag, envp) == EBUSY) { rb_raise(bdb_eFatal, "The shared memory region was in use"); } if (txn_unlink(db_home, flag, envp) == EBUSY) { rb_raise(bdb_eFatal, "The shared memory region was in use"); } #else bdb_test_error(db_env_create(&envp, 0)); envp->set_errpfx(envp, "BDB::"); envp->set_errcall(envp, bdb_env_errcall); #if HAVE_ENV_REMOVE_4 bdb_test_error(envp->remove(envp, db_home, NULL, flag)); #else bdb_test_error(envp->remove(envp, db_home, flag)); #endif #endif return Qtrue; } static VALUE bdb_env_set_flags(int argc, VALUE *argv, VALUE obj) { #if HAVE_ST_DB_ENV_SET_FLAGS bdb_ENV *envst; VALUE opt, flag; int state = 1; GetEnvDB(obj, envst); if (rb_scan_args(argc, argv, "11", &flag, &opt)) { switch (TYPE(opt)) { case T_TRUE: state = 1; break; case T_FALSE: state = 0; break; case T_FIXNUM: state = NUM2INT(opt); break; default: rb_raise(bdb_eFatal, "invalid value for onoff"); } } bdb_test_error(envst->envp->set_flags(envst->envp, NUM2INT(flag), state)); #endif return Qnil; } static VALUE bdb_env_home(VALUE obj) { bdb_ENV *envst; GetEnvDB(obj, envst); return envst->home; } #if HAVE_ST_DB_ENV_REP_SET_TRANSPORT || HAVE_ST_DB_ENV_SET_REP_TRANSPORT #if ! HAVE_RB_BLOCK_CALL static VALUE bdb_env_iterate(VALUE *tmp) { return rb_funcall2(tmp[0], rb_intern("__bdb_thread_init__"), (int)tmp[1], (VALUE *)tmp[2]); } #endif static VALUE bdb_thread_init(int argc, VALUE *argv, VALUE obj) { VALUE env; if ((env = rb_thread_local_aref(rb_thread_current(), bdb_id_current_env)) != Qnil) { rb_thread_local_aset(obj, bdb_id_current_env, env); } if (rb_block_given_p()) { #if HAVE_RB_BLOCK_CALL return rb_block_call(obj, rb_intern("__bdb_thread_init__"), argc, argv, rb_yield, obj); #else VALUE tmp[3]; tmp[0] = obj; tmp[1] = (VALUE)argc; tmp[2] = (VALUE)argv; return rb_iterate((VALUE (*)(VALUE))bdb_env_iterate, (VALUE)tmp, rb_yield, obj); #endif } return rb_funcall2(obj, rb_intern("__bdb_thread_init__"), argc, argv); } #endif #if HAVE_ST_DB_ENV_SET_FEEDBACK static VALUE bdb_env_feedback_set(VALUE obj, VALUE a) { bdb_ENV *envst; GetEnvDB(obj, envst); if (NIL_P(a)) { envst->feedback = a; } else { if (!rb_respond_to(a, bdb_id_call)) { rb_raise(bdb_eFatal, "arg must respond to #call"); } envst->feedback = a; if (!(envst->options & BDB_NEED_ENV_CURRENT)) { envst->options |= BDB_FEEDBACK; rb_thread_local_aset(rb_thread_current(), bdb_id_current_env, obj); } } return a; } #endif static VALUE bdb_env_i_conf(VALUE obj, VALUE a) { bdb_ENV *envst; u_int32_t value; char *str; const char *strval; GetEnvDB(obj, envst); str = StringValuePtr(a); #if HAVE_ST_DB_ENV_GET_CACHESIZE if (strcmp(str, "cachesize") == 0) { u_int32_t bytes, gbytes; int ncache; VALUE res; bdb_test_error(envst->envp->get_cachesize(envst->envp, &gbytes, &bytes, &ncache)); res = rb_ary_new2(3); rb_ary_push(res, INT2NUM(gbytes)); rb_ary_push(res, INT2NUM(bytes)); rb_ary_push(res, INT2NUM(ncache)); return res; } #endif #if HAVE_ST_DB_ENV_GET_DATA_DIRS if (strcmp(str, "data_dirs") == 0) { VALUE res; const char **dirs; int i; bdb_test_error(envst->envp->get_data_dirs(envst->envp, &dirs)); res = rb_ary_new(); if (dirs) { for (i = 0; dirs[i] != NULL; i++) { rb_ary_push(res, rb_tainted_str_new2(dirs[i])); } } return res; } #endif #if HAVE_ST_DB_ENV_GET_FLAGS if (strcmp(str, "flags") == 0) { bdb_test_error(envst->envp->get_flags(envst->envp, &value)); return INT2NUM(value); } #endif #if HAVE_ST_DB_ENV_GET_HOME if (strcmp(str, "home") == 0) { bdb_test_error(envst->envp->get_home(envst->envp, &strval)); if (strval && strlen(strval)) { return rb_tainted_str_new2(strval); } return Qnil; } #endif #if HAVE_ST_DB_ENV_GET_LG_BSIZE if (strcmp(str, "lg_bsize") == 0) { bdb_test_error(envst->envp->get_lg_bsize(envst->envp, &value)); return INT2NUM(value); } #endif #if HAVE_ST_DB_ENV_GET_LG_DIR if (strcmp(str, "lg_dir") == 0) { bdb_test_error(envst->envp->get_lg_dir(envst->envp, &strval)); if (strval && strlen(strval)) { return rb_tainted_str_new2(strval); } return Qnil; } #endif #if HAVE_ST_DB_ENV_GET_LG_MAX if (strcmp(str, "lg_max") == 0) { bdb_test_error(envst->envp->get_lg_max(envst->envp, &value)); return INT2NUM(value); } #endif #if HAVE_ST_DB_ENV_GET_LG_REGIONMAX if (strcmp(str, "lg_regionmax") == 0) { bdb_test_error(envst->envp->get_lg_regionmax(envst->envp, &value)); return INT2NUM(value); } #endif #if HAVE_ST_DB_ENV_GET_LK_DETECT if (strcmp(str, "lk_detect") == 0) { u_int32_t lk_detect; bdb_test_error(envst->envp->get_lk_detect(envst->envp, &lk_detect)); return INT2NUM(lk_detect); } #endif #if HAVE_ST_DB_ENV_GET_LK_MAX_LOCKERS if (strcmp(str, "lk_max_lockers") == 0) { bdb_test_error(envst->envp->get_lk_max_lockers(envst->envp, &value)); return INT2NUM(value); } #endif #if HAVE_ST_DB_ENV_GET_LK_MAX_LOCKS if (strcmp(str, "lk_max_locks") == 0) { bdb_test_error(envst->envp->get_lk_max_locks(envst->envp, &value)); return INT2NUM(value); } #endif #if HAVE_ST_DB_ENV_GET_LK_MAX_OBJECTS if (strcmp(str, "lk_max_objects") == 0) { bdb_test_error(envst->envp->get_lk_max_objects(envst->envp, &value)); return INT2NUM(value); } #endif #if HAVE_ST_DB_ENV_GET_MP_MMAPSIZE if (strcmp(str, "mp_mmapsize") == 0) { size_t size; bdb_test_error(envst->envp->get_mp_mmapsize(envst->envp, &size)); return LONG2NUM(size); } #endif #if HAVE_ST_DB_ENV_GET_OPEN_FLAGS if (strcmp(str, "open_flags") == 0) { bdb_test_error(envst->envp->get_open_flags(envst->envp, &value)); return INT2NUM(value); } #if HAVE_ST_DB_ENV_REP_SET_LIMIT || HAVE_ST_DB_SET_REP_LIMIT if (strcmp(str, "rep_limit") == 0) { u_int32_t bytes, gbytes; VALUE res; #if HAVE_ST_DB_ENV_REP_SET_LIMIT bdb_test_error(envst->envp->rep_get_limit(envst->envp, &gbytes, &bytes)); #else bdb_test_error(envst->envp->get_rep_limit(envst->envp, &gbytes, &bytes)); #endif res = rb_ary_new2(2); rb_ary_push(res, INT2NUM(gbytes)); rb_ary_push(res, INT2NUM(bytes)); return res; } #endif #endif #if HAVE_ST_DB_ENV_GET_SHM_KEY if (strcmp(str, "shm_key") == 0) { long shm_key; bdb_test_error(envst->envp->get_shm_key(envst->envp, &shm_key)); return INT2NUM(shm_key); } #endif #if HAVE_ST_DB_ENV_GET_TAS_SPINS if (strcmp(str, "tas_spins") == 0) { bdb_test_error(envst->envp->get_tas_spins(envst->envp, &value)); return INT2NUM(value); } #endif #if HAVE_ST_DB_ENV_GET_TIMEOUT { db_timeout_t timeout; if (strcmp(str, "txn_timeout") == 0) { bdb_test_error(envst->envp->get_timeout(envst->envp, &timeout, DB_SET_TXN_TIMEOUT)); return INT2NUM(timeout); } if (strcmp(str, "lock_timeout") == 0) { bdb_test_error(envst->envp->get_timeout(envst->envp, &timeout, DB_SET_LOCK_TIMEOUT)); return INT2NUM(timeout); } } #endif #if HAVE_ST_DB_ENV_GET_TMP_DIR if (strcmp(str, "tmp_dir") == 0) { bdb_test_error(envst->envp->get_tmp_dir(envst->envp, &strval)); if (strval && strlen(strval)) { return rb_tainted_str_new2(strval); } return Qnil; } #endif #if HAVE_ST_DB_ENV_GET_TX_MAX if (strcmp(str, "tx_max") == 0) { bdb_test_error(envst->envp->get_tx_max(envst->envp, &value)); return INT2NUM(value); } #endif #if HAVE_ST_DB_ENV_GET_TX_TIMESTAMP if (strcmp(str, "tx_timestamp") == 0) { time_t timeval; bdb_test_error(envst->envp->get_tx_timestamp(envst->envp, &timeval)); return INT2NUM(timeval); } #endif #if HAVE_ST_DB_ENV_REP_GET_PRIORITY if (strcmp(str, "rep_priority") == 0) { int size = 0; bdb_test_error(envst->envp->rep_get_priority(envst->envp, &size)); return INT2NUM(size); } #endif #if HAVE_ST_DB_ENV_GET_REP_NSITES if (strcmp(str, "rep_nsites") == 0) { size_t size = 0; bdb_test_error(envst->envp->rep_get_nsites(envst->envp, &size)); return INT2NUM(size); } #endif rb_raise(rb_eArgError, "Unknown option %s", str); return obj; } static char * options[] = { #if HAVE_ST_DB_ENV_GET_CACHESIZE "cachesize", #endif #if HAVE_ST_DB_ENV_GET_DATA_DIRS "data_dirs", #endif #if HAVE_ST_DB_ENV_GET_FLAGS "flags", #endif #if HAVE_ST_DB_ENV_GET_HOME "home", #endif #if HAVE_ST_DB_ENV_GET_LG_BSIZE "lg_bsize", #endif #if HAVE_ST_DB_ENV_GET_LG_DIR "lg_dir", #endif #if HAVE_ST_DB_ENV_GET_LG_MAX "lg_max", #endif #if HAVE_ST_DB_ENV_GET_LG_REGIONMAX "lg_regionmax", #endif #if HAVE_ST_DB_ENV_GET_LK_DETECT "lk_detect", #endif #if HAVE_ST_DB_ENV_GET_LK_MAX_LOCKERS "lk_max_lockers", #endif #if HAVE_ST_DB_ENV_GET_LK_MAX_LOCKS "lk_max_locks", #endif #if HAVE_ST_DB_ENV_GET_LK_MAX_OBJECTS "lk_max_objects", #endif #if HAVE_ST_DB_ENV_GET_MP_MMAPSIZE "mp_mmapsize", #endif #if HAVE_ST_DB_ENV_GET_OPEN_FLAGS "open_flags", #endif #if HAVE_ST_DB_ENV_GET_REP_LIMIT "rep_limit", #endif #if HAVE_ST_DB_ENV_GET_SHM_KEY "shm_key", #endif #if HAVE_ST_DB_ENV_GET_TAS_SPINS "tas_spins", #endif #if HAVE_ST_DB_ENV_GET_TIMEOUT "txn_timeout", "lock_timeout", #endif #if HAVE_ST_DB_ENV_GET_TMP_DIR "tmp_dir", #endif #if HAVE_ST_DB_ENV_GET_TX_MAX "tx_max", #endif #if HAVE_ST_DB_ENV_REP_GET_PRIORITY "rep_priority", #endif #if HAVE_ST_DB_ENV_REP_GET_NSITES "rep_nsites", #endif #if HAVE_ST_DB_ENV_GET_TX_TIMESTAMP "tx_timestamp", #endif 0 }; struct optst { VALUE obj, str; }; static VALUE bdb_env_intern_conf(struct optst *optp) { return bdb_env_i_conf(optp->obj, optp->str); } static VALUE bdb_env_conf(int argc, VALUE *argv, VALUE obj) { int i, state; VALUE res, val; struct optst opt; if (argc > 1) { rb_raise(rb_eArgError, "invalid number of arguments (%d for 1)", argc); } if (argc == 1) { return bdb_env_i_conf(obj, argv[0]); } res = rb_hash_new(); opt.obj = obj; for (i = 0; options[i] != NULL; i++) { opt.str = rb_str_new2(options[i]); val = rb_protect((VALUE (*)(ANYARGS))bdb_env_intern_conf, (VALUE)&opt, &state); if (state == 0) { rb_hash_aset(res, opt.str, val); } } return res; } #if HAVE_ST_DB_ENV_LSN_RESET static VALUE bdb_env_lsn_reset(int argc, VALUE *argv, VALUE obj) { char *file; int flags; VALUE a, b; bdb_ENV *envst; GetEnvDB(obj, envst); flags = 0; if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { flags = NUM2INT(b); } file = StringValuePtr(a); bdb_test_error(envst->envp->lsn_reset(envst->envp, file, flags)); return obj; } #endif #if HAVE_ST_DB_ENV_FILEID_RESET static VALUE bdb_env_fileid_reset(int argc, VALUE *argv, VALUE obj) { char *file; int flags; VALUE a, b; bdb_ENV *envst; GetEnvDB(obj, envst); flags = 0; if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { flags = NUM2INT(b); } file = StringValuePtr(a); bdb_test_error(envst->envp->fileid_reset(envst->envp, file, flags)); return obj; } #endif #if HAVE_ST_DB_ENV_SET_MSGCALL static VALUE bdb_env_set_msgcall(VALUE obj, VALUE a) { bdb_ENV *envst; GetEnvDB(obj, envst); if (NIL_P(a)) { envst->msgcall = Qnil; envst->envp->set_msgcall(envst->envp, NULL); return obj; } if (!rb_respond_to(a, bdb_id_call)) { rb_raise(rb_eArgError, "object must respond to #call"); } if (!RTEST(envst->msgcall)) { envst->envp->set_msgcall(envst->envp, bdb_env_msgcall); } envst->msgcall = a; return obj; } #endif #if HAVE_ST_DB_ENV_SET_THREAD_ID static VALUE bdb_env_set_thread_id(VALUE obj, VALUE a) { bdb_ENV *envst; GetEnvDB(obj, envst); if (!rb_respond_to(a, bdb_id_call)) { rb_raise(rb_eArgError, "object must respond to #call"); } if (!RTEST(envst->thread_id)) { envst->envp->set_thread_id(envst->envp, bdb_env_thread_id); } envst->thread_id = a; return obj; } #endif #if HAVE_ST_DB_ENV_SET_THREAD_ID_STRING static VALUE bdb_env_set_thread_id_string(VALUE obj, VALUE a) { bdb_ENV *envst; GetEnvDB(obj, envst); if (!rb_respond_to(a, bdb_id_call)) { rb_raise(rb_eArgError, "object must respond to #call"); } if (!RTEST(envst->thread_id_string)) { envst->envp->set_thread_id_string(envst->envp, bdb_env_thread_id_string); } envst->thread_id_string = a; return obj; } #endif #if HAVE_ST_DB_ENV_SET_ISALIVE static VALUE bdb_env_set_isalive(VALUE obj, VALUE a) { bdb_ENV *envst; GetEnvDB(obj, envst); if (!rb_respond_to(a, bdb_id_call)) { rb_raise(rb_eArgError, "object must respond to #call"); } if (!RTEST(envst->isalive)) { envst->envp->set_isalive(envst->envp, bdb_env_isalive); } envst->isalive = a; return obj; } #endif #if HAVE_ST_DB_ENV_FAILCHK static VALUE bdb_env_failcheck(int argc, VALUE *argv, VALUE obj) { bdb_ENV *envst; int flags = 0; VALUE a; GetEnvDB(obj, envst); if (rb_scan_args(argc, argv, "01", &a)) { flags = NUM2INT(a); } bdb_test_error(flags = envst->envp->failchk(envst->envp, flags)); return INT2NUM(flags); } #endif #if HAVE_ST_DB_ENV_REPMGR_ADD_REMOTE_SITE static VALUE bdb_env_repmgr_add_remote(int argc, VALUE *argv, VALUE obj) { bdb_ENV *envst; VALUE a, b, c; int eid, flags; flags = 0; if (rb_scan_args(argc, argv, "21", &a, &b, &c) == 3) { flags = NUM2INT(c); } GetEnvDB(obj, envst); bdb_test_error(envst->envp->repmgr_add_remote_site(envst->envp, StringValuePtr(a), NUM2UINT(b), &eid, flags)); return INT2NUM(eid); } #endif #if HAVE_ST_DB_ENV_REPMGR_SET_ACK_POLICY static VALUE bdb_env_repmgr_set_ack_policy(VALUE obj, VALUE a) { bdb_ENV *envst; GetEnvDB(obj, envst); bdb_test_error(envst->envp->repmgr_set_ack_policy(envst->envp, NUM2UINT(a))); return a; } static VALUE bdb_env_repmgr_get_ack_policy(VALUE obj) { bdb_ENV *envst; int policy; GetEnvDB(obj, envst); bdb_test_error(envst->envp->repmgr_get_ack_policy(envst->envp, &policy)); return INT2NUM(policy); } #endif #if HAVE_ST_DB_ENV_REPMGR_SET_LOCAL_SITE static VALUE bdb_env_repmgr_set_local_site(int argc, VALUE *argv, VALUE obj) { bdb_ENV *envst; VALUE a, b, c; int flags; flags = 0; if (rb_scan_args(argc, argv, "21", &a, &b, &c) == 3) { flags = NUM2INT(c); } GetEnvDB(obj, envst); bdb_test_error(envst->envp->repmgr_set_local_site(envst->envp, StringValuePtr(a), NUM2UINT(b), flags)); return obj; } #endif #if HAVE_ST_DB_ENV_REPMGR_SITE_LIST static VALUE bdb_env_repmgr_site_list(VALUE obj) { bdb_ENV *envst; VALUE res, tmp; u_int count, i; DB_REPMGR_SITE *list; GetEnvDB(obj, envst); bdb_test_error(envst->envp->repmgr_site_list(envst->envp, &count, &list)); res = rb_ary_new(); for (i = 0; i < count; i++) { tmp = rb_hash_new(); rb_hash_aset(tmp, rb_tainted_str_new2("eid"), INT2NUM(list[i].eid)); rb_hash_aset(tmp, rb_tainted_str_new2("host"), rb_tainted_str_new2(list[i].host)); rb_hash_aset(tmp, rb_tainted_str_new2("port"), INT2NUM(list[i].port)); rb_hash_aset(tmp, rb_tainted_str_new2("status"), INT2NUM(list[i].status)); rb_ary_push(res, tmp); } free(list); return res; } #endif #if HAVE_ST_DB_ENV_REPMGR_START static VALUE bdb_env_repmgr_start(VALUE obj, VALUE a, VALUE b) { bdb_ENV *envst; GetEnvDB(obj, envst); bdb_test_error(envst->envp->repmgr_start(envst->envp, NUM2INT(a), NUM2INT(b))); return obj; } #endif #if HAVE_ST_DB_ENV_REP_SET_TRANSPORT || HAVE_ST_DB_ENV_SET_REP_TRANSPORT static VALUE bdb_env_rep_set_transport(VALUE obj, VALUE a, VALUE b) { bdb_ENV *envst; GetEnvDB(obj, envst); if (!FIXNUM_P(a)) { rb_raise(bdb_eFatal, "expected a Fixnum for the 1st arg of set_rep_transport"); } if (!rb_respond_to(b, bdb_id_call)) { rb_raise(bdb_eFatal, "2nd arg must respond to #call"); } envst->rep_transport = b; #if HAVE_ST_DB_ENV_REP_SET_TRANSPORT bdb_test_error(envst->envp->rep_set_transport(envst->envp, NUM2INT(a), bdb_env_rep_transport)); #else bdb_test_error(envst->envp->set_rep_transport(envst->envp, NUM2INT(a), bdb_env_rep_transport)); #endif return obj; } #endif #if HAVE_ST_DB_ENV_REP_SET_CONFIG static VALUE bdb_env_rep_set_config(VALUE obj, VALUE a, VALUE b) { bdb_ENV *envst; int onoff = 0; if (b == Qtrue) { onoff = 1; } else if (b == Qfalse || b == Qnil) { onoff = 0; } else { onoff = NUM2INT(b); } GetEnvDB(obj, envst); bdb_test_error(envst->envp->rep_set_config(envst->envp, NUM2UINT(a), onoff)); return obj; } static VALUE bdb_env_rep_get_config(VALUE obj, VALUE a) { bdb_ENV *envst; int offon; GetEnvDB(obj, envst); bdb_test_error(envst->envp->rep_get_config(envst->envp, NUM2UINT(a), &offon)); if (offon) { return Qtrue; } return Qfalse; } #endif #if HAVE_ST_DB_ENV_REP_SET_NSITES static VALUE bdb_env_rep_set_nsites(VALUE obj, VALUE a) { bdb_ENV *envst; GetEnvDB(obj, envst); bdb_test_error(envst->envp->rep_set_nsites(envst->envp, NUM2UINT(a))); return a; } static VALUE bdb_env_rep_get_nsites(VALUE obj, VALUE a) { bdb_ENV *envst; int offon; GetEnvDB(obj, envst); bdb_test_error(envst->envp->rep_get_nsites(envst->envp, &offon)); return INT2NUM(offon); } #endif #if HAVE_ST_DB_ENV_REP_SET_PRIORITY static VALUE bdb_env_rep_set_priority(VALUE obj, VALUE a) { bdb_ENV *envst; GetEnvDB(obj, envst); bdb_test_error(envst->envp->rep_set_priority(envst->envp, NUM2UINT(a))); return a; } static VALUE bdb_env_rep_get_priority(VALUE obj, VALUE a) { bdb_ENV *envst; int offon; GetEnvDB(obj, envst); bdb_test_error(envst->envp->rep_get_priority(envst->envp, &offon)); return INT2NUM(offon); } #endif #if HAVE_ST_DB_ENV_REP_SET_TIMEOUT static VALUE bdb_env_rep_set_timeout(VALUE obj, VALUE a, VALUE b) { bdb_ENV *envst; GetEnvDB(obj, envst); bdb_test_error(envst->envp->rep_set_timeout(envst->envp, NUM2UINT(a), NUM2INT(b))); return obj; } static VALUE bdb_env_rep_get_timeout(VALUE obj, VALUE a) { bdb_ENV *envst; u_int32_t offon; GetEnvDB(obj, envst); bdb_test_error(envst->envp->rep_get_timeout(envst->envp, NUM2UINT(a), &offon)); return INT2NUM(offon); } #endif #if HAVE_ST_DB_ENV_REP_SET_LIMIT || HAVE_ST_DB_LEN_SET_REP_LIMIT static VALUE bdb_env_rep_get_limit(VALUE obj) { bdb_ENV *envst; u_int32_t gbytes, bytes; VALUE res; GetEnvDB(obj, envst); #if HAVE_ST_DB_ENV_REP_SET_LIMIT bdb_test_error(envst->envp->rep_get_limit(envst->envp, &gbytes, &bytes)); #else bdb_test_error(envst->envp->get_rep_limit(envst->envp, &gbytes, &bytes)); #endif res = rb_ary_new2(2); rb_ary_push(res, INT2NUM(gbytes)); rb_ary_push(res, INT2NUM(bytes)); return res; } #endif #if HAVE_ST_DB_ENV_REP_SYNC static VALUE bdb_env_rep_sync(int argc, VALUE *argv, VALUE obj) { bdb_ENV *envst; VALUE a; int flags; flags = 0; if (rb_scan_args(argc, argv, "01", &a) == 1) { flags = NUM2INT(a); } GetEnvDB(obj, envst); bdb_test_error(envst->envp->rep_sync(envst->envp, flags)); return obj; } #endif #if HAVE_ST_DB_ENV_REP_STAT static VALUE bdb_env_rep_stat(int argc, VALUE *argv, VALUE obj) { bdb_ENV *envst; VALUE a, lsn; int flags; struct dblsnst *lsnst; DB_REP_STAT *bs; flags = 0; if (rb_scan_args(argc, argv, "01", &a) == 1) { flags = NUM2INT(a); } GetEnvDB(obj, envst); bdb_test_error(envst->envp->rep_stat(envst->envp, &bs, flags)); a = rb_hash_new(); #if HAVE_ST_DB_REP_STAT_ST_BULK_FILLS rb_hash_aset(a, rb_tainted_str_new2("st_bulk_fills"), INT2NUM(bs->st_bulk_fills)); #endif #if HAVE_ST_DB_REP_STAT_ST_BULK_OVERFLOWS rb_hash_aset(a, rb_tainted_str_new2("st_bulk_overflows"), INT2NUM(bs->st_bulk_overflows)); #endif #if HAVE_ST_DB_REP_STAT_ST_BULK_RECORDS rb_hash_aset(a, rb_tainted_str_new2("st_bulk_records"), INT2NUM(bs->st_bulk_records)); #endif #if HAVE_ST_DB_REP_STAT_ST_BULK_TRANSFERS rb_hash_aset(a, rb_tainted_str_new2("st_bulk_transfers"), INT2NUM(bs->st_bulk_transfers)); #endif #if HAVE_ST_DB_REP_STAT_ST_CLIENT_REREQUESTS rb_hash_aset(a, rb_tainted_str_new2("st_client_rerequests"), INT2NUM(bs->st_client_rerequests)); #endif #if HAVE_ST_DB_REP_STAT_ST_CLIENT_SVC_MISS rb_hash_aset(a, rb_tainted_str_new2("st_client_svc_miss"), INT2NUM(bs->st_client_svc_miss)); #endif #if HAVE_ST_DB_REP_STAT_ST_CLIENT_SVC_REQ rb_hash_aset(a, rb_tainted_str_new2("st_client_svc_req"), INT2NUM(bs->st_client_svc_req)); #endif rb_hash_aset(a, rb_tainted_str_new2("st_dupmasters"), INT2NUM(bs->st_dupmasters)); #if HAVE_ST_DB_REP_STAT_ST_EGEN rb_hash_aset(a, rb_tainted_str_new2("st_egen"), INT2NUM(bs->st_egen)); #endif rb_hash_aset(a, rb_tainted_str_new2("st_election_cur_winner"), INT2NUM(bs->st_election_cur_winner)); rb_hash_aset(a, rb_tainted_str_new2("st_election_gen"), INT2NUM(bs->st_election_gen)); lsn = bdb_makelsn(obj); Data_Get_Struct(lsn, struct dblsnst, lsnst); MEMCPY(lsnst->lsn, &bs->st_election_lsn, DB_LSN, 1); rb_hash_aset(a, rb_tainted_str_new2("st_election_lsn"), lsn); rb_hash_aset(a, rb_tainted_str_new2("st_election_nsites"), INT2NUM(bs->st_election_nsites)); #if HAVE_ST_DB_REP_STAT_ST_ELECTION_NVOTES rb_hash_aset(a, rb_tainted_str_new2("st_election_nvotes"), INT2NUM(bs->st_election_nvotes)); #endif rb_hash_aset(a, rb_tainted_str_new2("st_election_priority"), INT2NUM(bs->st_election_priority)); #if HAVE_ST_DB_REP_STAT_ST_ELECTION_SEC rb_hash_aset(a, rb_tainted_str_new2("st_election_sec"), INT2NUM(bs->st_election_sec)); #endif rb_hash_aset(a, rb_tainted_str_new2("st_election_status"), INT2NUM(bs->st_election_status)); rb_hash_aset(a, rb_tainted_str_new2("st_election_tiebreaker"), INT2NUM(bs->st_election_tiebreaker)); #if HAVE_ST_DB_REP_STAT_ST_ELECTION_USEC rb_hash_aset(a, rb_tainted_str_new2("st_election_usec"), INT2NUM(bs->st_election_usec)); #endif rb_hash_aset(a, rb_tainted_str_new2("st_election_votes"), INT2NUM(bs->st_election_votes)); rb_hash_aset(a, rb_tainted_str_new2("st_elections"), INT2NUM(bs->st_elections)); rb_hash_aset(a, rb_tainted_str_new2("st_elections_won"), INT2NUM(bs->st_elections_won)); rb_hash_aset(a, rb_tainted_str_new2("st_env_id"), INT2NUM(bs->st_env_id)); rb_hash_aset(a, rb_tainted_str_new2("st_env_priority"), INT2NUM(bs->st_env_priority)); rb_hash_aset(a, rb_tainted_str_new2("st_gen"), INT2NUM(bs->st_gen)); rb_hash_aset(a, rb_tainted_str_new2("st_log_duplicated"), INT2NUM(bs->st_log_duplicated)); rb_hash_aset(a, rb_tainted_str_new2("st_log_queued"), INT2NUM(bs->st_log_queued)); rb_hash_aset(a, rb_tainted_str_new2("st_log_queued_max"), INT2NUM(bs->st_log_queued_max)); rb_hash_aset(a, rb_tainted_str_new2("st_log_queued_total"), INT2NUM(bs->st_log_queued_total)); rb_hash_aset(a, rb_tainted_str_new2("st_log_records"), INT2NUM(bs->st_log_records)); rb_hash_aset(a, rb_tainted_str_new2("st_log_requested"), INT2NUM(bs->st_log_requested)); rb_hash_aset(a, rb_tainted_str_new2("st_master"), INT2NUM(bs->st_master)); rb_hash_aset(a, rb_tainted_str_new2("st_master_changes"), INT2NUM(bs->st_master_changes)); rb_hash_aset(a, rb_tainted_str_new2("st_msgs_badgen"), INT2NUM(bs->st_msgs_badgen)); rb_hash_aset(a, rb_tainted_str_new2("st_msgs_processed"), INT2NUM(bs->st_msgs_processed)); rb_hash_aset(a, rb_tainted_str_new2("st_msgs_recover"), INT2NUM(bs->st_msgs_recover)); rb_hash_aset(a, rb_tainted_str_new2("st_msgs_send_failures"), INT2NUM(bs->st_msgs_send_failures)); rb_hash_aset(a, rb_tainted_str_new2("st_msgs_sent"), INT2NUM(bs->st_msgs_sent)); rb_hash_aset(a, rb_tainted_str_new2("st_newsites"), INT2NUM(bs->st_newsites)); lsn = bdb_makelsn(obj); Data_Get_Struct(lsn, struct dblsnst, lsnst); MEMCPY(lsnst->lsn, &bs->st_next_lsn, DB_LSN, 1); rb_hash_aset(a, rb_tainted_str_new2("st_next_lsn"), lsn); #if HAVE_ST_DB_REP_STAT_ST_NEXT_PG rb_hash_aset(a, rb_tainted_str_new2("st_next_pg"), INT2NUM(bs->st_next_pg)); #endif rb_hash_aset(a, rb_tainted_str_new2("st_nsites"), INT2NUM(bs->st_nsites)); rb_hash_aset(a, rb_tainted_str_new2("st_nthrottles"), INT2NUM(bs->st_nthrottles)); rb_hash_aset(a, rb_tainted_str_new2("st_outdated"), INT2NUM(bs->st_outdated)); #if HAVE_ST_DB_REP_STAT_ST_PG_DUPLICATED rb_hash_aset(a, rb_tainted_str_new2("st_pg_duplicated"), INT2NUM(bs->st_pg_duplicated)); #endif #if HAVE_ST_DB_REP_STAT_ST_PG_RECORDS rb_hash_aset(a, rb_tainted_str_new2("st_pg_records"), INT2NUM(bs->st_pg_records)); #endif #if HAVE_ST_DB_REP_STAT_ST_PG_REQUESTED rb_hash_aset(a, rb_tainted_str_new2("st_pg_requested"), INT2NUM(bs->st_pg_requested)); #endif #if HAVE_ST_DB_REP_STAT_ST_STARTUP_COMPLETE rb_hash_aset(a, rb_tainted_str_new2("st_startup_complete"), INT2NUM(bs->st_startup_complete)); #endif rb_hash_aset(a, rb_tainted_str_new2("st_status"), INT2NUM(bs->st_status)); rb_hash_aset(a, rb_tainted_str_new2("st_txns_applied"), INT2NUM(bs->st_txns_applied)); lsn = bdb_makelsn(obj); Data_Get_Struct(lsn, struct dblsnst, lsnst); MEMCPY(lsnst->lsn, &bs->st_waiting_lsn, DB_LSN, 1); rb_hash_aset(a, rb_tainted_str_new2("st_waiting_lsn"), lsn); #if HAVE_ST_DB_REP_STAT_ST_WAITING_PG rb_hash_aset(a, rb_tainted_str_new2("st_waiting_pg"), INT2NUM(bs->st_waiting_pg)); #endif free(bs); return a; } #endif #if HAVE_ST_DB_ENV_REP_SET_TIMEOUT || HAVE_ST_DB_ENV_REP_SET_CONFIG static VALUE bdb_cInt; struct bdb_intern { VALUE obj; int sstype; }; #define BDB_INTERN_CONFIG 1 #define BDB_INTERN_TIMEOUT 2 #define REP_INTERN(str_, sstype_) \ static VALUE \ bdb_env_rep_intern_##str_(VALUE obj) \ { \ struct bdb_intern *st_intern; \ VALUE res; \ \ res = Data_Make_Struct(bdb_cInt, struct bdb_intern, 0, free, st_intern); \ st_intern->obj = obj; \ st_intern->sstype = sstype_; \ return res; \ } #if HAVE_ST_DB_ENV_REP_SET_CONFIG REP_INTERN(config, BDB_INTERN_CONFIG) #endif #if HAVE_ST_DB_ENV_REP_SET_TIMEOUT REP_INTERN(timeout, BDB_INTERN_TIMEOUT) #endif static VALUE bdb_intern_set(VALUE obj, VALUE a, VALUE b) { struct bdb_intern *st_intern; Data_Get_Struct(obj, struct bdb_intern, st_intern); #if HAVE_ST_DB_ENV_REP_SET_TIMEOUT if (st_intern->sstype == BDB_INTERN_TIMEOUT) { return bdb_env_rep_set_timeout(st_intern->obj, a, b); } #endif #if HAVE_ST_DB_ENV_REP_SET_CONFIG if (st_intern->sstype == BDB_INTERN_CONFIG) { return bdb_env_rep_set_config(st_intern->obj, a, b); } #endif rb_raise(rb_eArgError, "Invalid argument for Intern__#[]="); return Qnil; } static VALUE bdb_intern_get(VALUE obj, VALUE a) { struct bdb_intern *st_intern; Data_Get_Struct(obj, struct bdb_intern, st_intern); #if HAVE_ST_DB_ENV_REP_SET_TIMEOUT if (st_intern->sstype == BDB_INTERN_TIMEOUT) { return bdb_env_rep_get_timeout(st_intern->obj, a); } #endif #if HAVE_ST_DB_ENV_REP_SET_CONFIG if (st_intern->sstype == BDB_INTERN_CONFIG) { return bdb_env_rep_get_config(st_intern->obj, a); } #endif rb_raise(rb_eArgError, "Invalid argument for Intern__#[]"); return Qnil; } #endif #if HAVE_ST_DB_ENV_REP_SET_CLOCKSKEW static VALUE bdb_env_rep_set_clockskew(VALUE obj, VALUE a, VALUE b) { bdb_ENV *envst; GetEnvDB(obj, envst); bdb_test_error(envst->envp->rep_set_clockskew(envst->envp, NUM2UINT(a), NUM2INT(b))); return obj; } static VALUE bdb_env_rep_get_clockskew(VALUE obj, VALUE a) { bdb_ENV *envst; u_int32_t fast, slow; GetEnvDB(obj, envst); bdb_test_error(envst->envp->rep_get_clockskew(envst->envp, &fast, &slow)); return rb_assoc_new(INT2NUM(fast), INT2NUM(slow)); } #endif #if HAVE_ST_DB_ENV_REP_SET_REQUEST static VALUE bdb_env_rep_set_request(VALUE obj, VALUE a, VALUE b) { bdb_ENV *envst; GetEnvDB(obj, envst); bdb_test_error(envst->envp->rep_set_request(envst->envp, NUM2UINT(a), NUM2INT(b))); return obj; } static VALUE bdb_env_rep_get_request(VALUE obj, VALUE a) { bdb_ENV *envst; u_int32_t frmin, frmax; GetEnvDB(obj, envst); bdb_test_error(envst->envp->rep_get_request(envst->envp, &frmin, &frmax)); return rb_assoc_new(INT2NUM(frmin), INT2NUM(frmax)); } #endif #if HAVE_ST_DB_ENV_SET_INTERMEDIATE_DIR_MODE static VALUE bdb_env_dir_mode(VALUE obj) { bdb_ENV *envst; const char *dir; GetEnvDB(obj, envst); if (envst->envp->get_intermediate_dir_mode(envst->envp, &dir)) { rb_raise(rb_eArgError, "invalid environment"); } return rb_tainted_str_new2(dir); } #endif #if HAVE_ST_DB_ENV_LOG_SET_CONFIG static VALUE bdb_env_log_set_config(VALUE obj, VALUE a, VALUE b) { bdb_ENV *envst; int onoff; GetEnvDB(obj, envst); onoff = RTEST(b)?1:0; if (envst->envp->log_set_config(envst->envp, NUM2INT(a), onoff)) { rb_raise(rb_eArgError, "invalid argument"); } return obj; } static VALUE bdb_env_log_config(VALUE obj, VALUE a) { bdb_ENV *envst; int onoff; GetEnvDB(obj, envst); if (envst->envp->log_get_config(envst->envp, NUM2INT(a), &onoff)) { rb_raise(rb_eArgError, "invalid argument"); } if (onoff) { return Qtrue; } return Qfalse; } #endif void bdb_init_env() { bdb_id_call = rb_intern("call"); #if HAVE_ST_DB_ENV_SET_FEEDBACK id_feedback = rb_intern("bdb_feedback"); #endif bdb_id_current_env = rb_intern("bdb_current_env"); #if HAVE_ST_DB_ENV_SET_APP_DISPATCH id_app_dispatch = rb_intern("bdb_app_dispatch"); #endif #if HAVE_ST_DB_ENV_SET_MSGCALL id_msgcall = rb_intern("bdb_msgcall"); #endif #if HAVE_ST_DB_ENV_SET_THREAD_ID id_thread_id = rb_intern("bdb_thread_id"); #endif #if HAVE_ST_DB_ENV_SET_THREAD_ID_STRING id_thread_id_string = rb_intern("bdb_thread_id_string"); #endif #if HAVE_ST_DB_ENV_SET_ISALIVE id_isalive = rb_intern("bdb_isalive"); #endif #if HAVE_ST_DB_ENV_SET_ENV_NOTIFY id_event_notify = rb_intern("bdb_event_notify"); #endif bdb_cEnv = rb_define_class_under(bdb_mDb, "Env", rb_cObject); rb_define_private_method(bdb_cEnv, "initialize", bdb_env_init, -1); #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_define_alloc_func(bdb_cEnv, bdb_env_s_alloc); #else rb_define_singleton_method(bdb_cEnv, "allocate", bdb_env_s_alloc, 0); #endif rb_define_singleton_method(bdb_cEnv, "new", bdb_env_s_new, -1); rb_define_singleton_method(bdb_cEnv, "create", bdb_env_s_new, -1); rb_define_singleton_method(bdb_cEnv, "open", bdb_env_s_open, -1); rb_define_singleton_method(bdb_cEnv, "remove", bdb_env_s_remove, -1); rb_define_singleton_method(bdb_cEnv, "unlink", bdb_env_s_remove, -1); rb_define_method(bdb_cEnv, "open_db", bdb_env_open_db, -1); rb_define_method(bdb_cEnv, "close", bdb_env_close, 0); rb_define_method(bdb_cEnv, "set_flags", bdb_env_set_flags, -1); rb_define_method(bdb_cEnv, "home", bdb_env_home, 0); #if HAVE_ST_DB_ENV_REP_ELECT rb_define_method(bdb_cEnv, "rep_elect", bdb_env_rep_elect, -1); rb_define_method(bdb_cEnv, "elect", bdb_env_rep_elect, -1); #endif #if HAVE_ST_DB_ENV_REP_PROCESS_MESSAGE rb_define_method(bdb_cEnv, "rep_process_message", bdb_env_rep_process_message, 3); rb_define_method(bdb_cEnv, "process_message", bdb_env_rep_process_message, 3); #endif #if HAVE_ST_DB_ENV_REP_START rb_define_method(bdb_cEnv, "rep_start", bdb_env_rep_start, 2); #endif #if HAVE_ST_DB_ENV_REP_SET_TRANSPORT || HAVE_ST_DB_ENV_SET_REP_TRANSPORT if (!rb_method_boundp(rb_cThread, rb_intern("__bdb_thread_init__"), 1)) { rb_alias(rb_cThread, rb_intern("__bdb_thread_init__"), rb_intern("initialize")); rb_define_method(rb_cThread, "initialize", bdb_thread_init, -1); } #endif #if HAVE_ST_DB_ENV_SET_REP_LIMIT || HAVE_ST_DB_ENV_REP_SET_LIMIT rb_define_method(bdb_cEnv, "rep_limit=", bdb_env_rep_limit, -1); #endif #if HAVE_ST_DB_ENV_SET_FEEDBACK rb_define_method(bdb_cEnv, "feedback=", bdb_env_feedback_set, 1); #endif rb_define_method(bdb_cEnv, "configuration", bdb_env_conf, -1); rb_define_method(bdb_cEnv, "conf", bdb_env_conf, -1); #if HAVE_ST_DB_ENV_LSN_RESET rb_define_method(bdb_cEnv, "lsn_reset", bdb_env_lsn_reset, -1); #endif #if HAVE_ST_DB_ENV_FILEID_RESET rb_define_method(bdb_cEnv, "fileid_reset", bdb_env_fileid_reset, -1); #endif #if HAVE_ST_DB_ENV_SET_MSGCALL rb_define_method(bdb_cEnv, "msgcall=", bdb_env_set_msgcall, 1); #endif #if HAVE_ST_DB_ENV_SET_THREAD_ID rb_define_method(bdb_cEnv, "thread_id=", bdb_env_set_thread_id, 1); #endif #if HAVE_ST_DB_ENV_SET_THREAD_ID_STRING rb_define_method(bdb_cEnv, "thread_id_string=", bdb_env_set_thread_id_string, 1); #endif #if HAVE_ST_DB_ENV_SET_ISALIVE rb_define_method(bdb_cEnv, "isalive=", bdb_env_set_isalive, 1); #endif #if HAVE_ST_DB_ENV_FAILCHK rb_define_method(bdb_cEnv, "failcheck", bdb_env_failcheck, -1); #endif #if HAVE_ST_DB_ENV_SET_EVENT_NOTIFY rb_define_method(bdb_cEnv, "event_notify=", bdb_env_set_notify, 1); #endif #if HAVE_ST_DB_ENV_REP_SET_TIMEOUT || HAVE_ST_DB_ENV_REP_SET_CONFIG bdb_cInt = rb_define_class_under(bdb_mDb, "Intern__", rb_cObject); #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_undef_alloc_func(bdb_cInt); #else rb_undef_method(CLASS_OF(bdb_cInt), "allocate"); #endif rb_undef_method(CLASS_OF(bdb_cInt), "new"); rb_define_method(bdb_cInt, "[]", bdb_intern_get, 1); rb_define_method(bdb_cInt, "[]=", bdb_intern_set, 2); #endif #if HAVE_ST_DB_ENV_REPMGR_ADD_REMOTE_SITE rb_define_method(bdb_cEnv, "repmgr_add_remote_site", bdb_env_repmgr_add_remote, -1); #endif #if HAVE_ST_DB_ENV_REPMGR_SET_ACK_POLICY rb_define_method(bdb_cEnv, "repmgr_set_ack_policy", bdb_env_repmgr_set_ack_policy, 1); rb_define_method(bdb_cEnv, "repmgr_ack_policy=", bdb_env_repmgr_set_ack_policy, 1); rb_define_method(bdb_cEnv, "repmgr_get_ack_policy", bdb_env_repmgr_get_ack_policy, 0); rb_define_method(bdb_cEnv, "repmgr_ack_policy", bdb_env_repmgr_get_ack_policy, 0); #endif #if HAVE_ST_DB_ENV_REPMGR_SET_LOCAL_SITE rb_define_method(bdb_cEnv, "repmgr_set_local_site", bdb_env_repmgr_set_local_site, -1); #endif #if HAVE_ST_DB_ENV_REPMGR_SET_SITE_LIST rb_define_method(bdb_cEnv, "repmgr_site_list", bdb_env_repmgr_site_list, 0); #endif #if HAVE_ST_DB_ENV_REPMGR_START rb_define_method(bdb_cEnv, "repmgr_start", bdb_env_repmgr_start, 2); #endif #if HAVE_ST_DB_ENV_REP_SET_CONFIG rb_define_method(bdb_cEnv, "rep_set_config", bdb_env_rep_set_config, 2); rb_define_method(bdb_cEnv, "rep_get_config", bdb_env_rep_get_config, 1); rb_define_method(bdb_cEnv, "rep_config", bdb_env_rep_intern_config, 0); rb_define_method(bdb_cEnv, "rep_config?", bdb_env_rep_intern_config, 0); #endif #if HAVE_ST_DB_ENV_REP_SET_NSITES rb_define_method(bdb_cEnv, "rep_set_nsites", bdb_env_rep_set_nsites, 1); rb_define_method(bdb_cEnv, "rep_nsites=", bdb_env_rep_set_nsites, 1); rb_define_method(bdb_cEnv, "rep_get_nsites", bdb_env_rep_get_nsites, 0); rb_define_method(bdb_cEnv, "rep_nsites", bdb_env_rep_get_nsites, 0); #endif #if HAVE_ST_DB_ENV_REP_SET_PRIORITY rb_define_method(bdb_cEnv, "rep_set_priority", bdb_env_rep_set_priority, 1); rb_define_method(bdb_cEnv, "rep_priority=", bdb_env_rep_set_priority, 1); rb_define_method(bdb_cEnv, "rep_get_priority", bdb_env_rep_get_priority, 0); rb_define_method(bdb_cEnv, "rep_priority", bdb_env_rep_get_priority, 0); #endif #if HAVE_ST_DB_ENV_REP_SET_LIMIT || HAVE_ST_DB_ENV_SEP_REP_LIMIT rb_define_method(bdb_cEnv, "rep_get_limit", bdb_env_rep_get_limit, 0); rb_define_method(bdb_cEnv, "rep_limit", bdb_env_rep_get_limit, 0); #endif #if HAVE_ST_DB_ENV_REP_SET_TIMEOUT rb_define_method(bdb_cEnv, "rep_set_timeout", bdb_env_rep_set_timeout, 2); rb_define_method(bdb_cEnv, "rep_get_timeout", bdb_env_rep_get_timeout, 1); rb_define_method(bdb_cEnv, "rep_timeout", bdb_env_rep_intern_timeout, 1); rb_define_method(bdb_cEnv, "rep_timeout?", bdb_env_rep_intern_timeout, 1); #endif #if HAVE_ST_DB_ENV_REP_STAT rb_define_method(bdb_cEnv, "rep_stat", bdb_env_rep_stat, 0); #endif #if HAVE_ST_DB_ENV_REP_SYNC rb_define_method(bdb_cEnv, "rep_sync", bdb_env_rep_sync, -1); #endif #if HAVE_ST_DB_ENV_REP_SET_TRANSPORT || HAVE_ST_DB_ENV_SET_REP_TRANSPORT rb_define_method(bdb_cEnv, "rep_set_transport", bdb_env_rep_set_transport, 2); #endif #if HAVE_ST_DB_ENV_REP_SET_CLOCKSKEW rb_define_method(bdb_cEnv, "rep_set_clockskew", bdb_env_rep_set_clockskew, 2); rb_define_method(bdb_cEnv, "rep_get_clockskew", bdb_env_rep_get_clockskew, 0); rb_define_method(bdb_cEnv, "rep_clockskew", bdb_env_rep_get_clockskew, 0); #endif #if HAVE_ST_DB_ENV_REP_SET_REQUEST rb_define_method(bdb_cEnv, "rep_set_request", bdb_env_rep_set_request, 2); rb_define_method(bdb_cEnv, "rep_get_request", bdb_env_rep_get_request, 0); rb_define_method(bdb_cEnv, "rep_request", bdb_env_rep_get_request, 0); #endif #if HAVE_ST_DB_ENV_SET_INTERMEDIATE_DIR_MODE rb_define_method(bdb_cEnv, "intermediate_dir_mode", bdb_env_dir_mode, 0); #endif #if HAVE_ST_DB_ENV_LOG_SET_CONFIG rb_define_method(bdb_cEnv, "set_log_config", bdb_env_log_set_config, 2); rb_define_method(bdb_cEnv, "log_set_config", bdb_env_log_set_config, 2); rb_define_method(bdb_cEnv, "log_config", bdb_env_log_config, 1); #endif } ruby-bdb-0.6.6/src/extconf.rb000077500000000000000000000100701154714021300160120ustar00rootroot00000000000000#!/usr/bin/ruby ARGV.collect! {|x| x.sub(/^--with-db-prefix=/, "--with-db-dir=") } require 'mkmf' if ARGV.include?('--help') || ARGV.include?('-h') puts < default=/usr --with-db-include= default=/usr/include --with-db-lib= default=/usr/lib --with-db-version= default=auto-detected if above values include one, or suffixes of all supported versions) --with-db-uniquename= option --with-uniquename=NAME when Berkeley DB was build --disable-thread disable the use of DB_THREAD ------------------------------------------------------------ EOT exit end if unknown = enable_config("unknown") libs = if CONFIG.key?("LIBRUBYARG_STATIC") Config::expand(CONFIG["LIBRUBYARG_STATIC"].dup).sub(/^-l/, '') else Config::expand(CONFIG["LIBRUBYARG"].dup).sub(/lib([^.]*).*/, '\\1') end unknown = find_library(libs, "ruby_init", Config::expand(CONFIG["archdir"].dup)) end inc_dir, lib_dir = dir_config("db", "/usr/include", "/usr/lib") case Config::CONFIG["arch"] when /solaris2/ $DLDFLAGS ||= "" $DLDFLAGS += " -R#{lib_dir}" end $bdb_libdir = lib_dir $CFLAGS += " -DBDB_NO_THREAD_COMPILE" if enable_config("thread") == false unique = with_config("db-uniquename") || '' if with_config("db-pthread") $LDFLAGS += " -lpthread" end if csv = with_config('db-version') version = csv.split(',', -1) version << '' if version.empty? elsif m = lib_dir.match(%r{/db(?:([2-9])|([2-9])([0-9])|-([2-9]).([0-9]))(?:$|/)}) || inc_dir.match(%r{/db(?:([2-9])|([2-9])([0-9])|-([2-9]).([0-9]))(?:$|/)}) if m[1] version = [m[1], ''] else if m[2] major, minor = m[2], m[3] else major, minor = m[4], m[5] end version = ['-%d.%d' % [major, minor], '%d%d' % [major, minor], ''] end else version = [ %w[4.7 4.6 4.5 4.4 4.3 4.2 4.1 4.0 4 3 2].map { |ver| major, minor = ver.split('.') minor ? ['-%d.%d' % [major, minor], '%d%d' % [major, minor]] : major }, '' ].flatten end catch(:done) do pthread = /-lpthread/ =~ $LDFLAGS loop do version.each do |with_ver| if unique.is_a?(String) db_version = "db_version" + unique throw :done if have_library("db#{with_ver}", db_version, "db.h") end next if with_ver.empty? if !unique.is_a?(String) || unique.empty? m = with_ver.match(/^[^0-9]*([2-9])\.?([0-9]{0,3})/) major = m[1].to_i minor = m[2].to_i db_version = "db_version_" + (1000 * major + minor).to_s throw :done if have_library("db#{with_ver}", db_version, "db.h") end end break if pthread $LDFLAGS += " -lpthread" pthread = true puts 'Trying with -lpthread' end raise "libdb#{version.last} not found" end headers = ["ruby.h"] if have_header("ruby/io.h") headers << "ruby/io.h" else headers << "rubyio.h" end ["rb_frame_this_func", "rb_block_proc", "rb_io_stdio_file", "rb_block_call"].each do |f| have_func(f, "ruby.h") end ["insert", "values_at"].each do |f| print "checking for Array##{f}... " if [].respond_to?(f) puts "yes" $defs << "-DHAVE_RB_ARY_#{f.upcase}" else puts "no" end end have_type('rb_io_t', headers) if enable_config('db-xml') $defs << '-DHAVE_DBXML_INTERFACE' else $defs << '-DNOT_HAVE_DBXML_INTERFACE' end require './features' create_makefile("bdb") if unknown begin make = open("Makefile", "a") make.print <<-EOF unknown: $(DLLIB) \t@echo "main() {}" > /tmp/a.c \t$(CC) -static /tmp/a.c $(OBJS) $(CPPFLAGS) $(LIBPATH) $(LIBS) $(LOCAL_LIBS) \t@-rm /tmp/a.c a.out EOF ensure make.close end end # Local variables: # ruby-indent-tabs-mode: nil # ruby-indent-level: 3 # end: # vim: sw=3 ruby-bdb-0.6.6/src/features.rb000066400000000000000000000541151154714021300161670ustar00rootroot00000000000000#!/usr/bin/ruby unless "a".respond_to?(:tr_cpp) class String def tr_cpp strip.upcase.tr_s("^A-Z0-9_", "_") end end end def have_db_member(where, array) found = false array.each do |st| if have_struct_member(where, st, 'db.h') $defs.pop $defs << "-DHAVE_ST_#{where}_#{st.tr_cpp}" found = true else $defs << "-DNOT_HAVE_ST_#{where}_#{st.tr_cpp}" end end found end def have_db_type(type) if have_type(type, 'db.h') true else $defs << "-DNOT_HAVE_TYPE_#{type.tr_cpp}" false end end def try_db_compile(func, src, mess = nil) print "checking for #{func}... " unless mess if try_compile(src) $defs << "-DHAVE_#{func}" puts "yes" true else $defs << "-DNOT_HAVE_#{func}" puts "no" false end end def have_db_const(const) const.each do |c| print "checking for #{c} in db.h..." try_db_compile("CONST_#{c.tr_cpp}", < int main() { int x = #{c}; return x; } EOT end end def try_db_link(func, src) if try_link(src) $defs << "-DHAVE_#{func}" true else $defs << "-DNOT_HAVE_#{func}" false end end def try_db_run(func, src) ENV['LD_LIBRARY_PATH'] = $bdb_libdir if try_run(src) $defs << "-DHAVE_#{func}" true else $defs << "-DNOT_HAVE_#{func}" false end ensure ENV['LD_LIBRARY_PATH'] = '' end have_db_const([ "DB_AFTER", "DB_AGGRESSIVE", "DB_APPEND", "DB_ARCH_ABS", "DB_ARCH_DATA", "DB_ARCH_LOG", "DB_AUTO_COMMIT", "DB_BEFORE", "DB_BTREE", "DB_CACHED_COUNTS", "DB_CDB_ALLDB", "DB_CHECKPOINT", "DB_CHKSUM", "DB_CHKSUM_SHA1", "DB_CLIENT", "DB_CONFIG", "DB_CONSUME", "DB_CONSUME_WAIT", "DB_CREATE", "DB_CURLSN", "DB_CURRENT", "DB_DBT_MALLOC", "DB_DBT_PARTIAL", "DB_DBT_REALLOC","DB_DBT_USERMEM", "DB_DIRECT_DB", "DB_DIRECT_LOG", "DB_DIRTY_READ", "DB_DONOTINDEX", "DB_DSYNC_LOG", "DB_DUP", "DB_DUPSORT", "DB_EID_BROADCAST", "DB_EID_INVALID", "DB_ENCRYPT", "DB_ENCRYPT_AES", "DB_ENV_THREAD", "DB_EVENT_PANIC", "DB_EVENT_REP_CLIENT", "DB_EVENT_REP_ELECTED", "DB_EVENT_REP_MASTER", "DB_EVENT_REP_NEWMASTER", "DB_EVENT_REP_PERM_FAILED", "DB_EVENT_REP_STARTUPDONE", "DB_EVENT_WRITE_FAILED", "DB_EXCL", "DB_FAST_STAT", "DB_FIRST", "DB_FIXEDLEN", "DB_FLUSH", "DB_FORCE", "DB_GET_BOTH_RANGE", "DB_GET_RECNO", "DB_GET_BOTH", "DB_HASH", "DB_HOME", "DB_IGNORE_LEASE", "DB_INCOMPLETE", "DB_INIT_CDB", "DB_INIT_LOCK", "DB_INIT_LOG", "DB_INIT_MPOOL", "DB_INIT_REP", "DB_INIT_TXN", "DB_JOINENV", "DB_JOIN_ITEM", "DB_JOIN_NOSORT", "DB_KEYEMPTY", "DB_KEYEXIST", "DB_KEYFIRST", "DB_KEYLAST", "DB_LAST", "DB_LOCKDOWN", "DB_LOCK_CONFLICT", "DB_LOCK_DEADLOCK", "DB_LOCK_DEFAULT", "DB_LOCK_EXPIRE", "DB_LOCK_GET", "DB_LOCK_GET_TIMEOUT", "DB_LOCK_IREAD", "DB_LOCK_IWR", "DB_LOCK_IWRITE", "DB_LOCK_MAXLOCKS", "DB_LOCK_MINLOCKS", "DB_LOCK_MINWRITE", "DB_LOCK_NG", "DB_LOCK_NOTGRANTED", "DB_LOCK_NOTHELD", "DB_LOCK_NOWAIT", "DB_LOCK_OLDEST", "DB_LOCK_PUT", "DB_LOCK_PUT_ALL", "DB_LOCK_PUT_OBJ", "DB_LOCK_RANDOM", "DB_LOCK_READ", "DB_LOCK_TIMEOUT", "DB_LOCK_WRITE", "DB_LOCK_YOUNGEST", "DB_LOG_AUTOREMOVE", "DB_LOG_AUTO_REMOVE", "DB_LOG_DIRECT", "DB_LOG_DSYNC", "DB_LOG_INMEMORY", "DB_LOG_IN_MEMORY", "DB_LOG_ZERO", "DB_MPOOL_CLEAN", "DB_MPOOL_CREATE", "DB_MPOOL_DIRTY", "DB_MPOOL_DISCARD", "DB_MPOOL_LAST", "DB_MPOOL_NEW", "DB_MPOOL_PRIVATE", "DB_MULTIVERSION", "DB_MUTEX_PROCESS_ONLY", "DB_NEXT_DUP", "DB_NEXT_NODUP", "DB_NODUPDATA", "DB_NOORDERCHK", "DB_NOSERVER", "DB_NOSERVER_HOME", "DB_NOSERVER_ID", "DB_NOTFOUND", "DB_OLD_VERSION", "DB_ORDERCHKONLY", "DB_OVERWRITE", "DB_POSITION", "DB_PRIVATE", "DB_SYSTEM_MEM", "DB_RMW", "DB_PAD", "DB_PREV_DUP", "DB_PREV_NODUP", "DB_PRINTABLE", "DB_PRIORITY_DEFAULT", "DB_PRIORITY_HIGH", "DB_PRIORITY_LOW", "DB_PRIORITY_VERY_HIGH", "DB_QUEUE", "DB_RDONLY", "DB_READ_COMMITTED", "DB_READ_UNCOMMITTED", "DB_RECNO", "DB_RECNUM", "DB_RECORDCOUNT", "DB_RECOVER", "DB_RECOVER_FATAL", "DB_REGION_INIT", "DB_RENUMBER", "DB_REPFLAGS_MASK", "DB_REPMGR_ACKS_ALL", "DB_REPMGR_ACKS_ALL_PEERS", "DB_REPMGR_ACKS_NONE", "DB_REPMGR_ACKS_ONE", "DB_REPMGR_ACKS_ONE_PEER", "DB_REPMGR_ACKS_QUORUM", "DB_REPMGR_CONNECTED", "DB_REPMGR_DISCONNECTED", "DB_REPMGR_PEER", "DB_REP_ACK_TIMEOUT", "DB_REP_ANYWHERE", "DB_REP_BULKOVF", "DB_REP_CHECKPOINT_DELAY", "DB_REP_CLIENT", "DB_REP_CONF_BULK", "DB_REP_CONF_DELAYCLIENT", "DB_REP_CONF_NOAUTOINIT", "DB_REP_CONF_NOWAIT", "DB_REP_CONNECTION_RETRY", "DB_REP_DEFAULT_PRIORITY", "DB_REP_DUPMASTER", "DB_REP_EGENCHG", "DB_REP_ELECTION", "DB_REP_ELECTION_RETRY", "DB_REP_ELECTION_TIMEOUT", "DB_REP_FULL_ELECTION", "DB_REP_FULL_ELECTION_TIMEOUT", "DB_REP_HANDLE_DEAD", "DB_REP_HOLDELECTION", "DB_REP_IGNORE", "DB_REP_ISPERM", "DB_REP_JOIN_FAILURE", "DB_REP_LEASE_EXPIRED", "DB_REP_LEASE_TIMEOUT", "DB_REP_LOCKOUT", "DB_REP_LOGREADY", "DB_REP_LOGSONLY", "DB_REP_MASTER", "DB_REP_NEWMASTER", "DB_REP_NEWSITE", "DB_REP_NOBUFFER", "DB_REP_NOTPERM", "DB_REP_OUTDATED", "DB_REP_PAGEDONE", "DB_REP_PERMANENT", "DB_REP_REREQUEST", "DB_REP_UNAVAIL", "DB_RPCCLIENT", "DB_RUNRECOVERY", "DB_SALVAGE", "DB_SECONDARY_BAD", "DB_SET", "DB_SET_LOCK_TIMEOUT", "DB_SET_RANGE", "DB_SET_RECNO", "DB_SET_TXN_TIMEOUT", "DB_SNAPSHOT", "DB_STAT_ALL", "DB_STAT_CLEAR", "DB_STAT_SUBSYSTEM", "DB_THREAD", "DB_TRUNCATE", "DB_TXN_ABORT", "DB_TXN_APPLY", "DB_TXN_BACKWARD_ROLL", "DB_TXN_FORWARD_ROLL", "DB_TXN_NOSYNC", "DB_TXN_NOWAIT", "DB_TXN_PRINT", "DB_TXN_SNAPSHOT", "DB_TXN_SYNC", "DB_TXN_WRITE_NOSYNC", "DB_UNKNOWN", "DB_UPGRADE", "DB_USE_ENVIRON", "DB_USE_ENVIRON_ROOT", "DB_VERB_CHKPOINT", "DB_VERB_DEADLOCK", "DB_VERB_RECOVERY", "DB_VERB_REPLICATION", "DB_VERB_WAITSFOR", "DB_VERIFY", "DB_PRIORITY_VERY_LOW", "DB_WRITECURSOR", "DB_XA_CREATE", "DB_XIDDATASIZE", "DB_MULTIPLE_KEY", "DB_REP_CONF_LEASE", "DB_REP_HEARTBEAT_MONITOR", "DB_REP_HEARTBEAT_SEND", "DB_TXN_NOT_DURABLE" ]) # try_db_link('DB_STRERROR', < int main() { db_strerror(2); return 1; } EOT # have_db_type('DB_KEY_RANGE') have_db_type('DB_INFO') have_db_type('DB_SEQUENCE') have_db_type('DB_LOGC') have_db_type('DBTYPE') have_db_type('DB_COMPACT') if have_db_type('DB_HASH_STAT') have_db_member('DB_HASH_STAT', ['hash_nkeys', 'hash_nrecs', 'hash_ndata', 'hash_nelem', 'hash_pagecnt']) end if have_db_type('DB_QUEUE_STAT') have_db_member('DB_QUEUE_STAT', ['qs_nkeys', 'qs_nrecs', 'qs_ndata', 'qs_start']) end if have_db_type('DB_REP_STAT') have_db_member('DB_REP_STAT', ['st_bulk_fills', 'st_bulk_overflows', 'st_bulk_records', 'st_bulk_transfers', 'st_client_rerequests', 'st_client_svc_miss', 'st_client_svc_req', 'st_egen', 'st_election_nvotes', 'st_election_sec', 'st_election_usec', 'st_next_pg', 'st_pg_duplicated', 'st_pg_records', 'st_pg_requested', 'st_startup_complete', 'st_waiting_pg',]) end # have_db_member('DBC', ['c_close', 'c_count', 'c_del', 'c_dup', 'c_get', 'c_pget', 'c_put', 'close', 'count', 'del', 'dup', 'get', 'pget', 'put', 'get_priority']) # have_db_member('DB', ['app_private', 'set_h_compare', 'set_append_recno', 'set_feedback', 'set_q_extendsize', 'set_encrypt', 'set_errcall', 'get_type', 'pget', 'fd', 'set_priority', 'byteswapped', 'get_bt_minkey', 'get_cachesize', 'get_dbname', 'get_env', 'get_h_ffactor', 'get_h_nelem', 'get_lorder', 'get_pagesize', 'get_q_extentsize', 'get_re_delim', 'get_re_len', 'get_re_pad', 'get_re_source', 'get_flags', 'get_open_flags', 'verify', 'truncate', 'upgrade', 'remove', 'rename', 'join', 'get_byteswapped' ,'set_cache_priority']) if $defs.include?('-DHAVE_ST_DB_GET_TYPE') try_db_compile('DB_GET_TYPE_2', < int main() { DB *db = 0; DBTYPE dt = 0; db->get_type(db, &dt); return 1; } EOT end if have_db_member('DB', ['open']) if try_db_compile('DB_OPEN_7', < int main() { DB *db = 0; db->open(db, NULL, "", "", DB_BTREE, 0, 0); return 1; } EOT try_db_run('DB_OPEN_7_DB_CREATE', < int main() { DB *db = 0; db_create(&db, 0, 0); if (db->open(db, 0, NULL, NULL, DB_BTREE, 0, 0)) { return 0; } return 1; } EOT args = if $defs.include?('-DHAVE_DB_OPEN_7_DB_CREATE') 'db, NULL, NULL, NULL, DB_BTREE, DB_CREATE|DB_THREAD, 0' else 'db, NULL, NULL, DB_BTREE, DB_CREATE|DB_THREAD, 0' end try_db_run('DB_KEY_DBT_MALLOC', < #include int a_compare(DB *db, const DBT *dbt1, const DBT *dbt2) { return 1; } int main() { DB *db = 0; DBT k, v; char *s = "a"; db_create(&db, 0, 0); db->set_bt_compare(db, a_compare); if (db->open(#{args})) { return 1; } memset(&k, 0, sizeof(DBT)); k.data = s; k.size = 1; memset(&v, 0, sizeof(DBT)); v.data = s; v.size = 1; v.flags |= DB_DBT_MALLOC; if (db->get(db, 0, &k, &v, 0)) { db->close(db, 0); return 0; } db->close(db, 0); return 1; } EOT end end if have_db_member('DB', ['associate']) try_db_compile('DB_ASSOCIATE_TXN', < int main() { DB *db = 0; DB_TXN *txn = 0; db->associate(db, txn, db, 0, 0); return 1; } EOT end if $defs.include?("-DHAVE_ST_DB_JOIN") try_db_compile('DB_JOIN_FLAG_DBC', < int main() { DB *db = 0; DBC **dbcarr = 0, *dbc; db->join(db, dbcarr, 0, &dbc); return 1; } EOT end if $defs.include?("-DHAVE_ST_DB_GET_BYTESWAPPED") try_db_compile('DB_GET_BYTESWAPPED_2', < int main() { DB *db = 0; int swap; db->get_byteswapped(db, &swap); return 1; } EOT end # have_db_member('DB_ENV', ["get_cachesize", "get_data_dirs", "get_flags", "get_home", "get_lg_bsize", "get_lg_dir", "get_lg_max", "get_lg_regionmax", "get_lk_detect", "get_lk_max_lockers", "get_lk_max_locks", "get_lk_max_objects", "get_mp_mmapsize", "get_open_flags", "get_rep_limit", "get_rep_nsites", "get_shm_key", "get_tas_spins", "get_tmp_dir", "get_timeout", "get_tx_max", "get_tx_timestamp", "rep_get_nsites", "rep_get_priority"]) have_db_member('DB_ENV', ['lg_info', 'log_put', 'log_flush', 'log_cursor', 'log_file', 'log_flush', 'set_feedback', 'set_app_dispatch', 'set_rep_transport', 'set_timeout', 'set_txn_timeout', 'set_lock_timeout', 'set_encrypt', 'set_rep_limit', 'rep_elect', 'rep_start', 'rep_process_message', 'rep_set_limit', 'set_msgcall', 'set_thread_id', 'set_thread_id_string', 'set_isalive', 'set_shm_key', 'rep_set_nsites', 'rep_set_priority', 'rep_set_config', 'rep_set_timeout', 'rep_set_transport', 'repmgr_set_local_site', 'repmgr_add_remote_site', 'repmgr_set_ack_policy', 'repmgr_set_site_list', 'repmgr_start', 'set_intermediate_dir_mode', 'set_event_notify', 'set_cachesize', 'set_region_init', 'set_tas_spins', 'set_tx_timestamp', 'db_verbose', 'set_verbose', 'lk_detect', 'set_lk_detect', 'lk_max', 'set_lk_max', 'lk_conflicts', 'set_lk_conflicts', 'set_timeout', 'set_lk_max_locks', 'set_lk_max_lockers', 'lg_max', 'set_lk_max_objects', 'set_lg_bsize', 'set_data_dir', 'set_lg_dir', 'set_tmp_dir', 'set_server', 'set_rpc_server', 'set_flags', 'close', 'set_func_sleep', 'set_func_yield', 'set_alloc', 'set_errcall' , 'lsn_reset', 'fileid_reset', 'failchk', 'rep_sync', 'rep_stat', 'log_set_config', 'fidp', 'rep_set_clockskew', 'rep_set_request']) if ! $defs.include?("-DHAVE_ST_DB_ENV_SET_FUNC_SLEEP") ['db_env_set_func_yield', 'db_env_set_func_sleep'].each do |func| try_db_link(func.tr_cpp, < static int a_func() { return 0; } int main() { #{func}(a_func); return 1; } EOT end end try_db_link('DB_ENV_CREATE', < int main() { db_env_create((DB_ENV **)0, 0); return 1; } EOT if ! $defs.include?("-DHAVE_ST_DB_ENV_SET_REGION_INIT") try_db_link('DB_ENV_SET_REGION_INIT', < int main() { db_env_set_region_init(0); return 1; } EOT end try_db_link('DB_APPINIT', < int main() { db_appinit((char *)0, (char **)0, (DB_ENV *)0, 0); return 0; } EOT try_db_link('DB_JUMP_SET', < static int a_func() { return 0; } int main() { db_jump_set(a_func, 0); return 1; } EOT if have_db_member('DB_ENV', ['open']) try_db_compile('ENV_OPEN_DB_CONFIG', < int main() { DB_ENV *env = 0; char **db_config = 0; env->open(env, (char *)0, db_config, 0, 0); return 1; } EOT end db_env_create = "#define HAVE_DB_ENV_CREATE " db_env_create << if $defs.include?('-DHAVE_DB_ENV_CREATE') "1" else "0" end db_appinit = "#define HAVE_DB_APPINIT " db_appinit << if $defs.include?('-DHAVE_DB_APPINIT') "1" else "0" end env_open_db_config = "#define HAVE_ENV_OPEN_DB_CONFIG " env_open_db_config << if $defs.include?('-DHAVE_ENV_OPEN_DB_CONFIG') "1" else "0" end try_db_run('DB_ENV_ERRCALL_3', < #include #{db_env_create} #{db_appinit} #{env_open_db_config} static int value = 0; void bdb_env_errcall(const DB_ENV *env, const char *errpfx, const char *msg) { if (!strncmp((void *)env, "BDB::", 5)) { value = 1; } else { value = 0; } } int main() { DB_ENV *envp; #if ! HAVE_DB_ENV_CREATE envp = malloc(sizeof(DB_ENV)); memset(envp, 0, sizeof(DB_ENV)); envp->db_errpfx = "BDB::"; envp->db_errcall = bdb_env_errcall; #else db_env_create(&envp, 0); envp->set_errpfx(envp, "BDB::"); envp->set_errcall(envp, bdb_env_errcall); #endif #if HAVE_DB_APPINIT db_appinit("", 0, envp, 123456789); #else #if HAVE_ENV_OPEN_DB_CONFIG envp->open(envp, "", 0, 123456789, 123456789); #else envp->open(envp, "", 123456789, 123456789); #endif #endif return value; } EOT try_db_compile('ENV_REMOVE_4', < int main() { DB_ENV *env = 0; env->remove(env, (char *)0, NULL, 0); return 1; } EOT if $defs.include?('-DHAVE_ST_DB_ENV_LG_INFO') $defs << '-DNOT_HAVE_DB_LOG_REGISTER' $defs << '-DNOT_HAVE_DB_LOG_UNREGISTER' else if !have_db_member('DB_ENV', ['log_stat']) try_db_link('DB_LOG_STAT_3', < int main() { DB_ENV *env = 0; DB_LOG_STAT *bdb_stat; log_stat(env, &bdb_stat, 0); return 1; } EOT end if !have_db_member('DB_ENV', ['log_archive']) try_db_link('DB_LOG_ARCHIVE_4', < int main() { char **list = 0; int flag = 0; DB_ENV *env = 0; log_archive(env, &list, flag, NULL); return 1; } EOT end if have_db_member('DB_ENV', ['log_register']) $defs << '-DNOT_HAVE_DB_LOG_REGISTER' else if try_db_link('DB_LOG_REGISTER_4', < int main() { DB_ENV *env = 0; DB *db = 0; u_int32_t fidp; log_register(env, db, "", &fidp); return 1; } EOT $defs << '-DHAVE_DB_LOG_REGISTER' else try_db_link('DB_LOG_REGISTER', < int main() { DB_ENV *env = 0; DB *db = 0; log_register(env, db, ""); return 1; } EOT end end if have_db_member('DB_ENV', ['log_unregister']) $defs << '-DNOT_HAVE_DB_LOG_UNREGISTER' else try_db_link('DB_LOG_UNREGISTER', < int main() { DB_ENV *env = 0; log_register(env, (void *)0); return 1; } EOT end try_db_compile('DB_CURSOR_4', < int main() { DB *db = 0; DB_TXN *txn = 0; DBC *dbc; db->cursor(db, txn, &dbc, 0); return 1; } EOT end if $defs.include?("-DHAVE_ST_DB_ENV_REP_ELECT") if try_db_compile('DB_ENV_REP_ELECT_7', < int main() { DB_ENV *env = 0; int envid; env->rep_elect(env, 0, 0, 0, 0, &envid, 0); return 1; } EOT $defs << "-DNOT_HAVE_DB_ENV_REP_ELECT_5" $defs << "-DNOT_HAVE_DB_ENV_REP_ELECT_4" elsif try_db_compile('DB_ENV_REP_ELECT_5', < int main() { DB_ENV *env = 0; int envid; env->rep_elect(env, 0, 0, 0, &envid); return 1; } EOT $defs << "-DNOT_HAVE_DB_ENV_REP_ELECT_4" else $defs << "-DHAVE_DB_ENV_REP_ELECT_4" end end if $defs.include?("-DHAVE_ST_DB_ENV_REP_PROCESS_MESSAGE") if try_db_compile('DB_ENV_REP_PROCESS_MESSAGE_5', < int main() { DB_ENV *env = 0; DBT control, rec; int envid = 0; env->rep_process_message(env, &control, &rec, envid, (DB_LSN *)0); return 1; } EOT $defs << "-DNOT_HAVE_DB_ENV_REP_PROCESS_MESSAGE_4" else $defs << "-DHAVE_DB_ENV_REP_PROCESS_MESSAGE_4" end end # # have_db_member('DB_LOG_STAT', ['st_refcnt' ,'st_lg_bsize', 'st_lg_size', 'st_lg_max', 'st_wcount_fill', 'st_disk_file', 'st_disk_offset', 'st_flushcommit', 'st_maxcommitperflush', 'st_mincommitperflush']) # have_db_member('DB_BTREE_STAT', ['bt_nkeys', 'bt_nrecs', 'bt_ndata', 'bt_pagecnt']) try_db_compile('DB_STAT_4', < int main() { DB *db = 0; db->stat(db, (DB_TXN *)0, (void *)0, 0); return 1; } EOT try_db_compile('DB_CURSOR_4', < int main() { DB *db = 0; DBC *st = 0; db->cursor(db, (DB_TXN *)0, &st, 0); return 1; } EOT # # # # lock have_db_member('DB_ENV', ['lock_id_free', 'lock_id', 'lk_info', 'lock_detect', 'lock_stat', 'lock_get', 'lock_vec', 'lock_put']) have_db_member('DB_LOCK_STAT', ['st_id', 'st_lastid', 'st_lock_nowait', 'st_lock_wait', 'st_nnowaits', 'st_nconflicts', 'st_objs_nowait', 'st_objs_wait', 'st_lockers_nowait', 'st_lockers_wait', 'st_locks_nowait', 'st_locks_wait']) have_db_member('DB_LOCKREQ', ['timeout']) if ! $defs.include?("-DHAVE_ST_DB_ENV_LK_INFO") && ! $defs.include?("-DHAVE_ST_DB_ENV_LOCK_STAT") unless try_db_link('LOCK_STAT_3', < int main() { lock_stat((DB_ENV *)0, 0, 0); return 1; } EOT $defs << '-DHAVE_LOCK_STAT_2' end end # have_db_member('DB_TXN', ['abort', 'commit', 'id', 'prepare', 'discard', 'set_timeout', 'set_name']) have_db_member('DB_ENV', ['tx_info', 'txn_begin', 'txn_checkpoint', 'txn_recover', 'txn_stat', 'dbremove', 'dbrename', 'set_tx_max']) have_db_member('DB_TXN_STAT', ['st_maxnactive', 'st_regsize', 'st_region_wait', 'st_region_nowait', 'st_last_ckp', 'st_pending_ckp', 'st_nrestores']) have_db_member('DB_TXN_ACTIVE', ['tid', 'name', 'parentid']) if ! $defs.include?("-DHAVE_ST_DB_TXN_COMMIT") try_db_link('TXN_COMMIT_2', < int main() { txn_commit((DB_TXN *)0, 0); return 1; } EOT end if ! $defs.include?("-DHAVE_ST_DB_TXN_PREPARE") if try_db_link('TXN_PREPARE_2', < int main() { txn_prepare((DB_TXN *)0, (unsigned char *)0); return 1; } EOT $defs << '-DHAVE_TXN_PREPARE' elsif try_db_link('TXN_PREPARE', < int main() { txn_prepare((DB_TXN *)0); return 1; } EOT end end if ! $defs.include?("-DHAVE_ST_DB_ENV_TX_INFO") && ! $defs.include?("-DHAVE_ST_DB_ENV_TXN_CHECKPOINT") try_db_link('TXN_CHECKPOINT_4', < int main() { txn_checkpoint((DB_ENV *)0, 0, 0, 0); return 1; } EOT end try_db_link('TXN_RECOVER', < int main() { txn_recover((DB_TXN *)0, (DB_PREPLIST *)0, 0, 0); return 1; } EOT if ! $defs.include?("-DHAVE_ST_DB_TXN_DISCARD") try_db_link('TXN_DISCARD', < int main() { txn_discard((DB_TXN *)0, 0); return 1; } EOT end if ! $defs.include?("-DHAVE_ST_DB_ENV_TX_INFO") && ! $defs.include?("-DHAVE_ST_DB_ENV_TXN_STAT") try_db_link('TXN_STAT_3', < int main() { txn_stat((DB_ENV *)0, (DB_TXN_STAT *)0, 0); return 1; } EOT end # # begin conftest = CONFTEST_C.dup class Object remove_const('CONFTEST_C') end CONFTEST_C = 'conftest.cxx' if $defs.include?('-DHAVE_ST_DB_ENV_SET_REP_TRANSPORT') || $defs.include?('-DHAVE_ST_DB_ENV_REP_SET_TRANSPORT') set_rep = if $defs.include?('-DHAVE_ST_DB_ENV_SET_REP_TRANSPORT') 'set_rep_transport' else 'rep_set_transport' end try_db_compile('ENV_REP_TRANSPORT_6', < static int bdb_env_rep_transport(DB_ENV *env, const DBT *control, const DBT *rec, const DB_LSN *lsn, int envid, u_int32_t flags) { return 0; } int main() { DB_ENV *env = 0; env->#{set_rep}(env, 0, bdb_env_rep_transport); return 1; } EOT end if $defs.include?('-DHAVE_DB_ENV_REP_ELECT_5') try_db_compile('DB_ENV_REP_ELECT_PRIO', < int main() { DB_ENV *env = 0; int envid = 0; env->rep_elect(env, 0, 0, 0, &envid); return 1; } EOT end if $defs.include?('-DHAVE_DB_ENV_REP_PROCESS_MESSAGE_5') try_db_compile('DB_ENV_REP_PROCESS_MESSAGE_ENVID', < int main() { DB_ENV *env = 0; DBT control, rec; DB_LSN lsn; int envid = 0; env->rep_process_message(env, &control, &rec, envid, &lsn); return 1; } EOT end ensure class Object remove_const('CONFTEST_C') end CONFTEST_C = conftest end open('bdb_features.h', 'w') do |gen| $defs.delete_if do |k| if /\A-DHAVE/ =~ k k.sub!(/\A-D/, '#define ') k << ' 1' gen.puts k true end end $defs.delete_if do |k| if /\A-DNOT_HAVE/ =~ k k.sub!(/\A-DNOT_/, '#define ') k << ' 0' gen.puts k true end end end ruby-bdb-0.6.6/src/lock.c000066400000000000000000000400411154714021300151110ustar00rootroot00000000000000#include "bdb.h" static void lockid_mark( bdb_LOCKID *dblockid) { rb_gc_mark(dblockid->env); } void bdb_clean_env(VALUE env, VALUE obj) { bdb_ENV *envst; Data_Get_Struct(env, bdb_ENV, envst); bdb_ary_delete(&envst->db_ary, obj); } static void lockid_free( bdb_LOCKID *dblockid) { #if HAVE_ST_DB_ENV_LOCK_ID_FREE bdb_ENV *envst; bdb_clean_env(dblockid->env, dblockid->self); Data_Get_Struct(dblockid->env, bdb_ENV, envst); if (envst->envp) { envst->envp->lock_id_free(envst->envp, dblockid->lock); } #endif free(dblockid); } static VALUE bdb_env_lockid(VALUE obj) { unsigned int idp; bdb_ENV *envst; bdb_LOCKID *dblockid; VALUE a; GetEnvDB(obj, envst); #if HAVE_ST_DB_ENV_LK_INFO if (!envst->envp->lk_info) { rb_raise(bdb_eLock, "lock region not open"); } bdb_test_error(lock_id(envst->envp->lk_info, &idp)); #elif HAVE_ST_DB_ENV_LOCK_ID bdb_test_error(envst->envp->lock_id(envst->envp, &idp)); #else bdb_test_error(lock_id(envst->envp, &idp)); #endif a = Data_Make_Struct(bdb_cLockid, bdb_LOCKID, lockid_mark, lockid_free, dblockid); dblockid->lock = idp; dblockid->env = obj; dblockid->self = a; #if HAVE_ST_DB_ENV_LOCK_ID bdb_ary_push(&envst->db_ary, a); #endif return a; } static VALUE bdb_env_lockid_close(VALUE obj) { bdb_ENV *envst; bdb_LOCKID *dblockid; Data_Get_Struct(obj, bdb_LOCKID, dblockid); bdb_clean_env(dblockid->env, obj); #if HAVE_ST_DB_ENV_LOCK_ID_FREE GetEnvDB(dblockid->env, envst); RDATA(obj)->dfree = free; if (envst->envp) { bdb_test_error(envst->envp->lock_id_free(envst->envp, dblockid->lock)); } #endif dblockid->env = 0; return Qnil; } static VALUE bdb_env_lockdetect(int argc, VALUE *argv, VALUE obj) { VALUE a, b; bdb_ENV *envst; int flags, atype, aborted; flags = atype = aborted = 0; if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { flags = NUM2INT(b); } atype = NUM2INT(a); GetEnvDB(obj, envst); #if HAVE_ST_DB_ENV_LK_INFO if (!envst->envp->lk_info) { rb_raise(bdb_eLock, "lock region not open"); } bdb_test_error(lock_detect(envst->envp->lk_info, flags, atype)); #elif HAVE_ST_DB_ENV_LOCK_DETECT bdb_test_error(envst->envp->lock_detect(envst->envp, flags, atype, &aborted)); #else bdb_test_error(lock_detect(envst->envp, flags, atype, &aborted)); #endif return INT2NUM(aborted); } static VALUE bdb_env_lockstat(int argc, VALUE *argv, VALUE obj) { bdb_ENV *envst; DB_LOCK_STAT *statp; VALUE a, b; int flags; GetEnvDB(obj, envst); #if HAVE_ST_DB_ENV_LK_INFO if (!envst->envp->lk_info) { rb_raise(bdb_eLock, "lock region not open"); } if (argc != 0) { rb_raise(rb_eArgError, "invalid number of arguments (%d for 0)", argc); } bdb_test_error(lock_stat(envst->envp->lk_info, &statp, 0)); a = rb_hash_new(); rb_hash_aset(a, rb_tainted_str_new2("st_magic"), INT2NUM(statp->st_magic)); rb_hash_aset(a, rb_tainted_str_new2("st_version"), INT2NUM(statp->st_version)); rb_hash_aset(a, rb_tainted_str_new2("st_refcnt"), INT2NUM(statp->st_refcnt)); rb_hash_aset(a, rb_tainted_str_new2("st_numobjs"), INT2NUM(statp->st_numobjs)); rb_hash_aset(a, rb_tainted_str_new2("st_regsize"), INT2NUM(statp->st_regsize)); rb_hash_aset(a, rb_tainted_str_new2("st_maxlocks"), INT2NUM(statp->st_maxlocks)); rb_hash_aset(a, rb_tainted_str_new2("st_nmodes"), INT2NUM(statp->st_nmodes)); rb_hash_aset(a, rb_tainted_str_new2("st_nlockers"), INT2NUM(statp->st_nlockers)); rb_hash_aset(a, rb_tainted_str_new2("st_nconflicts"), INT2NUM(statp->st_nconflicts)); rb_hash_aset(a, rb_tainted_str_new2("st_nrequests"), INT2NUM(statp->st_nrequests)); rb_hash_aset(a, rb_tainted_str_new2("st_ndeadlocks"), INT2NUM(statp->st_ndeadlocks)); rb_hash_aset(a, rb_tainted_str_new2("st_region_wait"), INT2NUM(statp->st_region_wait)); rb_hash_aset(a, rb_tainted_str_new2("st_region_nowait"), INT2NUM(statp->st_region_nowait)); #elif HAVE_ST_DB_ENV_LOCK_STAT flags = 0; if (rb_scan_args(argc, argv, "01", &b) == 1) { flags = NUM2INT(b); } bdb_test_error(envst->envp->lock_stat(envst->envp, &statp, flags)); a = rb_hash_new(); #if HAVE_ST_DB_LOCK_STAT_ST_ID rb_hash_aset(a, rb_tainted_str_new2("st_lastid"), INT2NUM(statp->st_id)); #endif #if HAVE_ST_DB_LOCK_STAT_ST_LASTID rb_hash_aset(a, rb_tainted_str_new2("st_lastid"), INT2NUM(statp->st_lastid)); #endif rb_hash_aset(a, rb_tainted_str_new2("st_nmodes"), INT2NUM(statp->st_nmodes)); rb_hash_aset(a, rb_tainted_str_new2("st_maxlocks"), INT2NUM(statp->st_maxlocks)); rb_hash_aset(a, rb_tainted_str_new2("st_maxlockers"), INT2NUM(statp->st_maxlockers)); rb_hash_aset(a, rb_tainted_str_new2("st_maxobjects"), INT2NUM(statp->st_maxobjects)); rb_hash_aset(a, rb_tainted_str_new2("st_nlocks"), INT2NUM(statp->st_nlocks)); rb_hash_aset(a, rb_tainted_str_new2("st_maxnlocks"), INT2NUM(statp->st_maxnlocks)); rb_hash_aset(a, rb_tainted_str_new2("st_nlockers"), INT2NUM(statp->st_nlockers)); rb_hash_aset(a, rb_tainted_str_new2("st_maxnlockers"), INT2NUM(statp->st_maxnlockers)); rb_hash_aset(a, rb_tainted_str_new2("st_nobjects"), INT2NUM(statp->st_nobjects)); rb_hash_aset(a, rb_tainted_str_new2("st_maxnobjects"), INT2NUM(statp->st_maxnobjects)); rb_hash_aset(a, rb_tainted_str_new2("st_nrequests"), INT2NUM(statp->st_nrequests)); rb_hash_aset(a, rb_tainted_str_new2("st_nreleases"), INT2NUM(statp->st_nreleases)); #if HAVE_ST_DB_LOCK_STAT_ST_LOCK_NOWAIT rb_hash_aset(a, rb_tainted_str_new2("st_lock_nowait"), INT2NUM(statp->st_lock_nowait)); #endif #if HAVE_ST_DB_LOCK_STAT_ST_LOCK_WAIT rb_hash_aset(a, rb_tainted_str_new2("st_lock_wait"), INT2NUM(statp->st_lock_wait)); #endif #if HAVE_ST_DB_LOCK_STAT_ST_NNOWAITS rb_hash_aset(a, rb_tainted_str_new2("st_nnowaits"), INT2NUM(statp->st_nnowaits)); #endif #if HAVE_ST_DB_LOCK_STAT_ST_NCONFLICTS rb_hash_aset(a, rb_tainted_str_new2("st_nconflicts"), INT2NUM(statp->st_nconflicts)); #endif rb_hash_aset(a, rb_tainted_str_new2("st_ndeadlocks"), INT2NUM(statp->st_ndeadlocks)); rb_hash_aset(a, rb_tainted_str_new2("st_nlocktimeouts"), INT2NUM(statp->st_nlocktimeouts)); rb_hash_aset(a, rb_tainted_str_new2("st_ntxntimeouts"), INT2NUM(statp->st_ntxntimeouts)); rb_hash_aset(a, rb_tainted_str_new2("st_regsize"), INT2NUM(statp->st_regsize)); rb_hash_aset(a, rb_tainted_str_new2("st_region_wait"), INT2NUM(statp->st_region_wait)); rb_hash_aset(a, rb_tainted_str_new2("st_region_nowait"), INT2NUM(statp->st_region_nowait)); #if HAVE_ST_DB_LOCK_STAT_ST_OBJS_NOWAIT rb_hash_aset(a, rb_tainted_str_new2("st_objs_nowait"), INT2NUM(statp->st_objs_nowait)); #endif #if HAVE_ST_DB_LOCK_STAT_ST_OBJS_WAIT rb_hash_aset(a, rb_tainted_str_new2("st_objs_wait"), INT2NUM(statp->st_objs_wait)); #endif #if HAVE_ST_DB_LOCK_STAT_ST_LOCKERS_NOWAIT rb_hash_aset(a, rb_tainted_str_new2("st_lockers_nowait"), INT2NUM(statp->st_lockers_nowait)); #endif #if HAVE_ST_DB_LOCK_STAT_ST_LOCKERS_WAIT rb_hash_aset(a, rb_tainted_str_new2("st_lockers_wait"), INT2NUM(statp->st_lockers_wait)); #endif #if HAVE_ST_DB_LOCK_STAT_ST_LOCKS_NOWAIT rb_hash_aset(a, rb_tainted_str_new2("st_locks_nowait"), INT2NUM(statp->st_locks_nowait)); #endif #if HAVE_ST_DB_LOCK_STAT_ST_LOCKS_WAIT rb_hash_aset(a, rb_tainted_str_new2("st_locks_wait"), INT2NUM(statp->st_locks_wait)); #endif #else if (argc != 0) { rb_raise(rb_eArgError, "invalid number of arguments (%d for 0)", argc); } #if HAVE_LOCK_STAT_3 bdb_test_error(lock_stat(envst->envp, &statp, 0)); #else bdb_test_error(lock_stat(envst->envp, &statp)); #endif a = rb_hash_new(); rb_hash_aset(a, rb_tainted_str_new2("st_lastid"), INT2NUM(statp->st_lastid)); rb_hash_aset(a, rb_tainted_str_new2("st_nmodes"), INT2NUM(statp->st_nmodes)); rb_hash_aset(a, rb_tainted_str_new2("st_maxlocks"), INT2NUM(statp->st_maxlocks)); rb_hash_aset(a, rb_tainted_str_new2("st_nlockers"), INT2NUM(statp->st_nlockers)); rb_hash_aset(a, rb_tainted_str_new2("st_maxnlockers"), INT2NUM(statp->st_maxnlockers)); rb_hash_aset(a, rb_tainted_str_new2("st_nconflicts"), INT2NUM(statp->st_nconflicts)); rb_hash_aset(a, rb_tainted_str_new2("st_nrequests"), INT2NUM(statp->st_nrequests)); rb_hash_aset(a, rb_tainted_str_new2("st_ndeadlocks"), INT2NUM(statp->st_ndeadlocks)); rb_hash_aset(a, rb_tainted_str_new2("st_regsize"), INT2NUM(statp->st_regsize)); rb_hash_aset(a, rb_tainted_str_new2("st_region_wait"), INT2NUM(statp->st_region_wait)); rb_hash_aset(a, rb_tainted_str_new2("st_region_nowait"), INT2NUM(statp->st_region_nowait)); #endif free(statp); return a; } #if HAVE_ST_DB_ENV_LK_INFO #define GetLockid(obj, lockid, envst) \ { \ Data_Get_Struct(obj, bdb_LOCKID, lockid); \ GetEnvDB(lockid->env, envst); \ if (envst->envp->lk_info == 0) { \ rb_raise(bdb_eLock, "closed lockid"); \ } \ } #else #define GetLockid(obj, lockid, envst) \ { \ Data_Get_Struct(obj, bdb_LOCKID, lockid); \ GetEnvDB(lockid->env, envst); \ } #endif static void lock_mark(bdb_LOCK *lock) { rb_gc_mark(lock->env); } static void lock_free(bdb_LOCK *lock) { #if HAVE_ST_DB_ENV_LK_INFO bdb_ENV *envst; Data_Get_Struct(lock->env, bdb_ENV, envst); \ if (envst->envp && envst->envp->lk_info) { lock_close(envst->envp->lk_info); envst->envp = NULL; } #endif free(lock); } static VALUE bdb_lockid_get(int argc, VALUE *argv, VALUE obj) { bdb_LOCKID *lockid; bdb_ENV *envst; DB_LOCK lock; bdb_LOCK *lockst; DBT objet; unsigned int flags; int lock_mode; VALUE a, b, c, res; rb_secure(2); flags = 0; if (rb_scan_args(argc, argv, "21", &a, &b, &c) == 3) { if (c == Qtrue) { flags = DB_LOCK_NOWAIT; } else { flags = NUM2UINT(c); } } SafeStringValue(a); MEMZERO(&objet, DBT, 1); objet.data = StringValuePtr(a); objet.size = RSTRING_LEN(a); lock_mode = NUM2INT(b); GetLockid(obj, lockid, envst); #if HAVE_ST_DB_ENV_LK_INFO if (!envst->envp->lk_info) { rb_raise(bdb_eLock, "lock region not open"); } bdb_test_error(lock_get(envst->envp->lk_info, lockid->lock, flags, &objet, lock_mode, &lock)); #elif HAVE_ST_DB_ENV_LOCK_GET bdb_test_error(envst->envp->lock_get(envst->envp, lockid->lock, flags, &objet, lock_mode, &lock)); #else bdb_test_error(lock_get(envst->envp, lockid->lock, flags, &objet, lock_mode, &lock)); #endif res = Data_Make_Struct(bdb_cLock, bdb_LOCK, lock_mark, lock_free, lockst); #if HAVE_ST_DB_ENV_LK_INFO lockst->lock = lock; #else lockst->lock = ALLOC(DB_LOCK); MEMCPY(lockst->lock, &lock, DB_LOCK, 1); #endif lockst->env = lockid->env; return res; } #if HAVE_ST_DB_ENV_LK_INFO #define GetLock(obj, lock, envst) \ { \ Data_Get_Struct(obj, bdb_LOCK, lock); \ GetEnvDB(lock->env, envst); \ if (envst->envp->lk_info == 0) \ rb_raise(bdb_eLock, "closed lock"); \ } #else #define GetLock(obj, lock, envst) \ { \ Data_Get_Struct(obj, bdb_LOCK, lock); \ GetEnvDB(lock->env, envst); \ } #endif struct lockreq { DB_LOCKREQ *list; }; static VALUE bdb_lockid_each(VALUE obj, VALUE listobj) { VALUE key, value; DB_LOCKREQ *list; bdb_ENV *envst; struct lockreq *listst; char *options; Data_Get_Struct(listobj, struct lockreq, listst); list = listst->list; key = rb_ary_entry(obj, 0); value = rb_ary_entry(obj, 1); key = rb_obj_as_string(key); options = StringValuePtr(key); if (strcmp(options, "op") == 0) { list->op = NUM2INT(value); } else if (strcmp(options, "obj") == 0) { Check_Type(value, T_STRING); list->obj = ALLOC(DBT); MEMZERO(list->obj, DBT, 1); list->obj->data = StringValuePtr(value); list->obj->size = RSTRING_LEN(value); } else if (strcmp(options, "mode") == 0) { list->mode = NUM2INT(value); } else if (strcmp(options, "lock") == 0) { bdb_LOCK *lockst; if (!rb_obj_is_kind_of(value, bdb_cLock)) { rb_raise(bdb_eFatal, "BDB::Lock expected"); } GetLock(value, lockst, envst); #if HAVE_ST_DB_ENV_LK_INFO list->lock = lockst->lock; #else MEMCPY(&list->lock, lockst->lock, DB_LOCK, 1); #endif } #if HAVE_ST_DB_LOCKREQ_TIMEOUT else if (strcmp(options, "timeout") == 0) { list->timeout = rb_Integer(value); } #endif return Qnil; } static VALUE bdb_lockid_vec(int argc, VALUE *argv, VALUE obj) { DB_LOCKREQ *list; bdb_LOCKID *lockid; bdb_LOCK *lockst; bdb_ENV *envst; unsigned int flags; VALUE a, b, c, res; int i, n, err; VALUE listobj; struct lockreq *listst; flags = 0; if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { if (b == Qtrue) { flags = DB_LOCK_NOWAIT; } else { flags = NUM2UINT(b); } } Check_Type(a, T_ARRAY); list = ALLOCA_N(DB_LOCKREQ, RARRAY_LEN(a)); MEMZERO(list, DB_LOCKREQ, RARRAY_LEN(a)); listobj = Data_Make_Struct(obj, struct lockreq, 0, free, listst); for (i = 0; i < RARRAY_LEN(a); i++) { b = RARRAY_PTR(a)[i]; Check_Type(b, T_HASH); listst->list = &list[i]; rb_iterate(rb_each, b, bdb_lockid_each, listobj); } GetLockid(obj, lockid, envst); #if HAVE_ST_DB_ENV_LK_INFO if (!envst->envp->lk_info) { rb_raise(bdb_eLock, "lock region not open"); } err = lock_vec(envst->envp->lk_info, lockid->lock, flags, list, RARRAY_LEN(a), NULL); #elif HAVE_ST_DB_ENV_LOCK_VEC err = envst->envp->lock_vec(envst->envp, lockid->lock, flags, list, RARRAY_LEN(a), NULL); #else err = lock_vec(envst->envp, lockid->lock, flags, list, RARRAY_LEN(a), NULL); #endif if (err != 0) { for (i = 0; i < RARRAY_LEN(a); i++) { if (list[i].obj) free(list[i].obj); } res = (err == DB_LOCK_DEADLOCK)?bdb_eLock:bdb_eFatal; if (bdb_errcall) { bdb_errcall = 0; rb_raise(res, "%s -- %s", StringValuePtr(bdb_errstr), db_strerror(err)); } else rb_raise(res, "%s", db_strerror(err)); } res = rb_ary_new2(RARRAY_LEN(a)); n = 0; for (i = 0; i < RARRAY_LEN(a); i++) { if (list[i].op == DB_LOCK_GET) { c = Data_Make_Struct(bdb_cLock, bdb_LOCK, lock_mark, lock_free, lockst); #if HAVE_ST_DB_ENV_LK_INFO lockst->lock = list[i].lock; #else lockst->lock = ALLOC(DB_LOCK); MEMCPY(lockst->lock, &list[i].lock, DB_LOCK, 1); #endif lockst->env = lockid->env; rb_ary_push(res, c); n++; } else { rb_ary_push(res, Qnil); } } return res; } static VALUE bdb_lock_put(VALUE obj) { bdb_LOCK *lockst; bdb_ENV *envst; GetLock(obj, lockst, envst); #if HAVE_ST_DB_ENV_LK_INFO if (!envst->envp->lk_info) { rb_raise(bdb_eLock, "lock region not open"); } bdb_test_error(lock_put(envst->envp->lk_info, lockst->lock)); #elif HAVE_ST_DB_ENV_LOCK_PUT bdb_test_error(envst->envp->lock_put(envst->envp, lockst->lock)); #else bdb_test_error(lock_put(envst->envp, lockst->lock)); #endif return Qnil; } void bdb_init_lock() { rb_define_method(bdb_cEnv, "lock_id", bdb_env_lockid, 0); rb_define_method(bdb_cEnv, "lock", bdb_env_lockid, 0); rb_define_method(bdb_cEnv, "lock_stat", bdb_env_lockstat, -1); rb_define_method(bdb_cEnv, "lock_detect", bdb_env_lockdetect, -1); bdb_cLockid = rb_define_class_under(bdb_mDb, "Lockid", rb_cObject); #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_undef_alloc_func(bdb_cLockid); #else rb_undef_method(CLASS_OF(bdb_cLockid), "allocate"); #endif rb_undef_method(CLASS_OF(bdb_cLockid), "new"); rb_define_method(bdb_cLockid, "lock_get", bdb_lockid_get, -1); rb_define_method(bdb_cLockid, "get", bdb_lockid_get, -1); rb_define_method(bdb_cLockid, "lock_vec", bdb_lockid_vec, -1); rb_define_method(bdb_cLockid, "vec", bdb_lockid_vec, -1); rb_define_method(bdb_cLockid, "close", bdb_env_lockid_close, 0); bdb_cLock = rb_define_class_under(bdb_mDb, "Lock", rb_cObject); rb_undef_method(CLASS_OF(bdb_cLock), "allocate"); rb_undef_method(CLASS_OF(bdb_cLock), "new"); rb_define_method(bdb_cLock, "put", bdb_lock_put, 0); rb_define_method(bdb_cLock, "lock_put", bdb_lock_put, 0); rb_define_method(bdb_cLock, "release", bdb_lock_put, 0); rb_define_method(bdb_cLock, "delete", bdb_lock_put, 0); } ruby-bdb-0.6.6/src/log.c000066400000000000000000000473521154714021300147560ustar00rootroot00000000000000#include "bdb.h" static void mark_lsn(struct dblsnst *lsnst) { rb_gc_mark(lsnst->env); } static void free_lsn(struct dblsnst *lsnst) { if (BDB_VALID(lsnst->env, T_DATA)) { bdb_clean_env(lsnst->env, lsnst->self); } #if HAVE_TYPE_DB_LOGC if (lsnst->cursor && BDB_VALID(lsnst->env, T_DATA)) { bdb_ENV *envst; Data_Get_Struct(lsnst->env, bdb_ENV, envst); if (envst->envp) { lsnst->cursor->close(lsnst->cursor, 0); } lsnst->cursor = 0; } #endif if (lsnst->lsn) free(lsnst->lsn); free(lsnst); } VALUE bdb_makelsn(VALUE env) { bdb_ENV *envst; struct dblsnst *lsnst; VALUE res; GetEnvDB(env, envst); res = Data_Make_Struct(bdb_cLsn, struct dblsnst, mark_lsn, free_lsn, lsnst); lsnst->env = env; lsnst->lsn = ALLOC(DB_LSN); lsnst->self = res; return res; } static VALUE bdb_s_log_put_internal(VALUE obj, VALUE a, int flag) { bdb_ENV *envst; VALUE ret; DBT data; struct dblsnst *lsnst; GetEnvDB(obj, envst); if (TYPE(a) != T_STRING) a = rb_str_to_str(a); ret = bdb_makelsn(obj); Data_Get_Struct(ret, struct dblsnst, lsnst); data.data = StringValuePtr(a); data.size = RSTRING_LEN(a); #if HAVE_ST_DB_ENV_LG_INFO if (!envst->envp->lg_info) { rb_raise(bdb_eFatal, "log region not open"); } bdb_test_error(log_put(envst->envp->lg_info, lsnst->lsn, &data, flag)); #elif HAVE_ST_DB_ENV_LOG_PUT bdb_test_error(envst->envp->log_put(envst->envp, lsnst->lsn, &data, flag)); #else bdb_test_error(log_put(envst->envp, lsnst->lsn, &data, flag)); #endif return ret; } static VALUE bdb_s_log_put(int argc, VALUE *argv, VALUE obj) { VALUE a, b; int flag = 0; if (argc == 0 || argc > 2) { rb_raise(bdb_eFatal, "Invalid number of arguments"); } #if HAVE_CONST_DB_CHECKPOINT flag = DB_CHECKPOINT; #endif if (rb_scan_args(argc, argv, "11", &a, &b) == 2) { flag = NUM2INT(b); } return bdb_s_log_put_internal(obj, a, flag); } static VALUE bdb_s_log_checkpoint(VALUE obj, VALUE a) { #if HAVE_CONST_DB_CHECKPOINT return bdb_s_log_put_internal(obj, a, DB_CHECKPOINT); #else rb_warning("BDB::CHECKPOINT is obsolete"); return bdb_s_log_put_internal(obj, a, 0); #endif } static VALUE bdb_s_log_flush(int argc, VALUE *argv, VALUE obj) { bdb_ENV *envst; if (argc == 0) { GetEnvDB(obj, envst); #if HAVE_ST_DB_ENV_LG_INFO if (!envst->envp->lg_info) { rb_raise(bdb_eFatal, "log region not open"); } bdb_test_error(log_flush(envst->envp->lg_info, NULL)); #elif HAVE_ST_DB_ENV_LOG_FLUSH bdb_test_error(envst->envp->log_flush(envst->envp, NULL)); #else bdb_test_error(log_flush(envst->envp, NULL)); #endif return obj; } else if (argc == 1) { return bdb_s_log_put_internal(obj, argv[0], DB_FLUSH); } else { rb_raise(bdb_eFatal, "Invalid number of arguments"); } } static VALUE bdb_s_log_curlsn(VALUE obj, VALUE a) { #if HAVE_CONST_DB_CURLSN return bdb_s_log_put_internal(obj, a, DB_CURLSN); #else rb_warning("BDB::CURLSN is obsolete"); return bdb_s_log_put_internal(obj, a, 0); #endif } static VALUE bdb_env_log_stat(int argc, VALUE *argv, VALUE obj) { DB_LOG_STAT *bdb_stat; bdb_ENV *envst; VALUE res, b; int flags; GetEnvDB(obj, envst); #if HAVE_ST_DB_ENV_LG_INFO if (!envst->envp->lg_info) { rb_raise(bdb_eFatal, "log region not open"); } if (argc != 0) { rb_raise(rb_eArgError, "invalid number of arguments (%d for 0)", argc); } bdb_test_error(log_stat(envst->envp->lg_info, &bdb_stat, 0)); #elif HAVE_ST_DB_ENV_LOG_STAT flags = 0; if (rb_scan_args(argc, argv, "01", &b) == 1) { flags = NUM2INT(b); } bdb_test_error(envst->envp->log_stat(envst->envp, &bdb_stat, flags)); #else if (argc != 0) { rb_raise(rb_eArgError, "invalid number of arguments (%d for 0)", argc); } #if HAVE_DB_LOG_STAT_3 bdb_test_error(log_stat(envst->envp, &bdb_stat, 0)); #else bdb_test_error(log_stat(envst->envp, &bdb_stat)); #endif #endif res = rb_hash_new(); rb_hash_aset(res, rb_tainted_str_new2("st_magic"), INT2NUM(bdb_stat->st_magic)); rb_hash_aset(res, rb_tainted_str_new2("st_version"), INT2NUM(bdb_stat->st_version)); rb_hash_aset(res, rb_tainted_str_new2("st_regsize"), INT2NUM(bdb_stat->st_regsize)); rb_hash_aset(res, rb_tainted_str_new2("st_mode"), INT2NUM(bdb_stat->st_mode)); #if HAVE_ST_DB_LOG_STAT_ST_REFCNT rb_hash_aset(res, rb_tainted_str_new2("st_refcnt"), INT2NUM(bdb_stat->st_refcnt)); #endif #if HAVE_ST_DB_LOG_STAT_ST_LG_BSIZE rb_hash_aset(res, rb_tainted_str_new2("st_lg_bsize"), INT2NUM(bdb_stat->st_lg_bsize)); #endif #if HAVE_ST_DB_LOG_STAT_ST_LG_SIZE rb_hash_aset(res, rb_tainted_str_new2("st_lg_size"), INT2NUM(bdb_stat->st_lg_size)); rb_hash_aset(res, rb_tainted_str_new2("st_lg_max"), INT2NUM(bdb_stat->st_lg_size)); #else rb_hash_aset(res, rb_tainted_str_new2("st_lg_max"), INT2NUM(bdb_stat->st_lg_max)); #endif rb_hash_aset(res, rb_tainted_str_new2("st_w_mbytes"), INT2NUM(bdb_stat->st_w_mbytes)); rb_hash_aset(res, rb_tainted_str_new2("st_w_bytes"), INT2NUM(bdb_stat->st_w_bytes)); rb_hash_aset(res, rb_tainted_str_new2("st_wc_mbytes"), INT2NUM(bdb_stat->st_wc_mbytes)); rb_hash_aset(res, rb_tainted_str_new2("st_wc_bytes"), INT2NUM(bdb_stat->st_wc_bytes)); rb_hash_aset(res, rb_tainted_str_new2("st_wcount"), INT2NUM(bdb_stat->st_wcount)); #if HAVE_ST_DB_LOG_STAT_ST_WCOUNT_FILL rb_hash_aset(res, rb_tainted_str_new2("st_wcount_fill"), INT2NUM(bdb_stat->st_wcount_fill)); #endif rb_hash_aset(res, rb_tainted_str_new2("st_scount"), INT2NUM(bdb_stat->st_scount)); rb_hash_aset(res, rb_tainted_str_new2("st_cur_file"), INT2NUM(bdb_stat->st_cur_file)); rb_hash_aset(res, rb_tainted_str_new2("st_cur_offset"), INT2NUM(bdb_stat->st_cur_offset)); rb_hash_aset(res, rb_tainted_str_new2("st_region_wait"), INT2NUM(bdb_stat->st_region_wait)); rb_hash_aset(res, rb_tainted_str_new2("st_region_nowait"), INT2NUM(bdb_stat->st_region_nowait)); #if HAVE_ST_DB_LOG_STAT_ST_DISK_FILE rb_hash_aset(res, rb_tainted_str_new2("st_disk_file"), INT2NUM(bdb_stat->st_disk_file)); #endif #if HAVE_ST_DB_LOG_STAT_ST_DISK_OFFSET rb_hash_aset(res, rb_tainted_str_new2("st_disk_offset"), INT2NUM(bdb_stat->st_disk_offset)); #if HAVE_ST_DB_LOG_STAT_ST_FLUSHCOMMIT rb_hash_aset(res, rb_tainted_str_new2("st_flushcommit"), INT2NUM(bdb_stat->st_flushcommit)); #endif #if HAVE_ST_DB_LOG_STAT_ST_MAXCOMMITPERFLUSH rb_hash_aset(res, rb_tainted_str_new2("st_maxcommitperflush"), INT2NUM(bdb_stat->st_maxcommitperflush)); #endif #if HAVE_ST_DB_LOG_STAT_ST_MINCOMMITPERFLUSH rb_hash_aset(res, rb_tainted_str_new2("st_mincommitperflush"), INT2NUM(bdb_stat->st_mincommitperflush)); #endif #endif free(bdb_stat); return res; } #if ! HAVE_ST_DB_ENV_LOG_CURSOR static VALUE bdb_env_log_get(VALUE obj, VALUE a) { bdb_ENV *envst; DBT data; struct dblsnst *lsnst; VALUE res, lsn; int ret, flag; GetEnvDB(obj, envst); flag = NUM2INT(a); MEMZERO(&data, DBT, 1); data.flags |= DB_DBT_MALLOC; lsn = bdb_makelsn(obj); Data_Get_Struct(lsn, struct dblsnst, lsnst); #if HAVE_ST_DB_ENV_LG_INFO if (!envst->envp->lg_info) { rb_raise(bdb_eFatal, "log region not open"); } ret = bdb_test_error(log_get(envst->envp->lg_info, lsnst->lsn, &data, flag)); #else ret = bdb_test_error(log_get(envst->envp, lsnst->lsn, &data, flag)); #endif if (ret == DB_NOTFOUND) { return Qnil; } res = rb_tainted_str_new(data.data, data.size); free(data.data); return rb_assoc_new(res, lsn); } #else static VALUE bdb_log_cursor _((VALUE)); #endif #define BDB_LOG_INIT 0 #define BDB_LOG_SET 1 #define BDB_LOG_NEXT 2 static VALUE bdb_i_each_log_get(VALUE obj, int flag) { #if ! HAVE_ST_DB_ENV_LOG_CURSOR bdb_ENV *envst; #endif struct dblsnst *lsnst, *lsnst1; DBT data; VALUE lsn, lsn1; VALUE res; int ret, init, flags; init = BDB_LOG_INIT; #if ! HAVE_ST_DB_ENV_LOG_CURSOR GetEnvDB(obj, envst); #else lsn = obj; Data_Get_Struct(obj, struct dblsnst, lsnst); flag = lsnst->flags; if (lsnst->cursor == 0) { DB_LSN *lsn1; init = BDB_LOG_SET; lsn1 = lsnst->lsn; lsn = bdb_makelsn(lsnst->env); Data_Get_Struct(lsn, struct dblsnst, lsnst); MEMCPY(lsnst->lsn, lsn1, DB_LSN, 1); bdb_log_cursor(lsn); } #endif do { #if ! HAVE_ST_DB_ENV_LOG_CURSOR lsn = bdb_makelsn(obj); Data_Get_Struct(lsn, struct dblsnst, lsnst); #endif MEMZERO(&data, DBT, 1); data.flags |= DB_DBT_MALLOC; switch (init) { case BDB_LOG_INIT: flags = (flag == DB_NEXT)?DB_FIRST:DB_LAST; break; case BDB_LOG_SET: flags = DB_SET; break; default: flags = flag; break; } init = BDB_LOG_NEXT; #if HAVE_ST_DB_ENV_LG_INFO if (!envst->envp->lg_info) { rb_raise(bdb_eFatal, "log region not open"); } ret = bdb_test_error(log_get(envst->envp->lg_info, lsnst->lsn, &data, flags)); #elif HAVE_ST_DB_ENV_LOG_CURSOR ret = bdb_test_error(lsnst->cursor->get(lsnst->cursor, lsnst->lsn, &data, flags)); lsn1 = bdb_makelsn(lsnst->env); Data_Get_Struct(lsn1, struct dblsnst, lsnst1); MEMCPY(lsnst1->lsn, lsnst->lsn, DB_LSN, 1); #else ret = bdb_test_error(log_get(envst->envp, lsnst->lsn, &data, flags)); lsn1 = lsn; #endif if (ret == DB_NOTFOUND) { return Qnil; } res = rb_tainted_str_new(data.data, data.size); free(data.data); rb_yield(rb_assoc_new(res, lsn)); } while (1); return Qnil; } #if ! HAVE_ST_DB_ENV_LOG_CURSOR static VALUE bdb_env_log_each(VALUE obj) { return bdb_i_each_log_get(obj, DB_NEXT); } static VALUE bdb_env_log_hcae(VALUE obj) { return bdb_i_each_log_get(obj, DB_PREV); } #else static VALUE log_cursor_close(VALUE obj) { struct dblsnst *lsnst; Data_Get_Struct(obj, struct dblsnst, lsnst); if (lsnst->cursor) { bdb_test_error(lsnst->cursor->close(lsnst->cursor, 0)); lsnst->cursor = 0; } return Qnil; } static VALUE bdb_log_cursor_close(VALUE obj) { struct dblsnst *lsnst; Data_Get_Struct(obj, struct dblsnst, lsnst); bdb_clean_env(lsnst->env, obj); return log_cursor_close(obj); } static VALUE bdb_log_cursor(VALUE lsn) { bdb_ENV *envst; struct dblsnst *lsnst; Data_Get_Struct(lsn, struct dblsnst, lsnst); if (!lsnst->cursor) { GetEnvDB(lsnst->env, envst); bdb_test_error(envst->envp->log_cursor(envst->envp, &lsnst->cursor, 0)); bdb_ary_push(&envst->db_ary, lsn); } return lsn; } static VALUE bdb_env_log_cursor(VALUE obj) { return bdb_log_cursor(bdb_makelsn(obj)); } static VALUE bdb_env_i_get(VALUE obj) { bdb_ENV *envst; struct dblsnst *lsnst; log_cursor_close(obj); Data_Get_Struct(obj, struct dblsnst, lsnst); GetEnvDB(lsnst->env, envst); bdb_test_error(envst->envp->log_cursor(envst->envp, &lsnst->cursor, 0)); return bdb_i_each_log_get(obj, lsnst->flags); } static VALUE bdb_env_log_each(VALUE obj) { VALUE lsn; struct dblsnst *lsnst; lsn = bdb_makelsn(obj); Data_Get_Struct(lsn, struct dblsnst, lsnst); lsnst->flags = DB_NEXT; return rb_ensure(bdb_env_i_get, lsn, bdb_log_cursor_close, lsn); } static VALUE bdb_env_log_hcae(VALUE obj) { VALUE lsn; struct dblsnst *lsnst; lsn = bdb_makelsn(obj); Data_Get_Struct(lsn, struct dblsnst, lsnst); lsnst->flags = DB_PREV; return rb_ensure(bdb_env_i_get, lsn, bdb_log_cursor_close, lsn); } static VALUE bdb_log_i_get(VALUE obj) { struct dblsnst *lsnst; log_cursor_close(obj); Data_Get_Struct(obj, struct dblsnst, lsnst); return bdb_i_each_log_get(obj, lsnst->flags); } static VALUE bdb_log_each(VALUE lsn) { struct dblsnst *lsnst; Data_Get_Struct(lsn, struct dblsnst, lsnst); lsnst->flags = DB_NEXT; return rb_ensure(bdb_log_i_get, lsn, bdb_log_cursor_close, lsn); } static VALUE bdb_log_hcae(VALUE lsn) { struct dblsnst *lsnst; Data_Get_Struct(lsn, struct dblsnst, lsnst); lsnst->flags = DB_PREV; return rb_ensure(bdb_log_i_get, lsn, bdb_log_cursor_close, lsn); } #endif static VALUE bdb_env_log_archive(int argc, VALUE *argv, VALUE obj) { char **list, **file; bdb_ENV *envst; int flag; VALUE res; GetEnvDB(obj, envst); flag = 0; list = NULL; if (rb_scan_args(argc, argv, "01", &res)) { flag = NUM2INT(res); } #if HAVE_ST_DB_ENV_LG_INFO if (!envst->envp->lg_info) { rb_raise(bdb_eFatal, "log region not open"); } bdb_test_error(log_archive(envst->envp->lg_info, &list, flag, NULL)); #elif HAVE_ST_DB_ENV_LOG_ARCHIVE bdb_test_error(envst->envp->log_archive(envst->envp, &list, flag)); #else #if HAVE_DB_LOG_ARCHIVE_4 bdb_test_error(log_archive(envst->envp, &list, flag, NULL)); #else bdb_test_error(log_archive(envst->envp, &list, flag)); #endif #endif res = rb_ary_new(); for (file = list; file != NULL && *file != NULL; file++) { rb_ary_push(res, rb_tainted_str_new2(*file)); } if (list != NULL) free(list); return res; } #define GetLsn(obj, lsnst, envst) \ { \ Data_Get_Struct(obj, struct dblsnst, lsnst); \ GetEnvDB(lsnst->env, envst); \ } static VALUE bdb_lsn_env(VALUE obj) { struct dblsnst *lsnst; bdb_ENV *envst; GetLsn(obj, lsnst, envst); return lsnst->env; } static VALUE bdb_lsn_log_file(VALUE obj) { struct dblsnst *lsnst; bdb_ENV *envst; char name[2048]; GetLsn(obj, lsnst, envst); #if HAVE_ST_DB_ENV_LG_INFO if (!envst->envp->lg_info) { rb_raise(bdb_eFatal, "log region not open"); } bdb_test_error(log_file(envst->envp->lg_info, lsnst->lsn, name, 2048)); #elif HAVE_ST_DB_ENV_LOG_FILE bdb_test_error(envst->envp->log_file(envst->envp, lsnst->lsn, name, 2048)); #else bdb_test_error(log_file(envst->envp, lsnst->lsn, name, 2048)); #endif return rb_tainted_str_new2(name); } static VALUE bdb_lsn_log_flush(VALUE obj) { struct dblsnst *lsnst; bdb_ENV *envst; GetLsn(obj, lsnst, envst); #if HAVE_ST_DB_ENV_LG_INFO if (!envst->envp->lg_info) { rb_raise(bdb_eFatal, "log region not open"); } bdb_test_error(log_flush(envst->envp->lg_info, lsnst->lsn)); #elif HAVE_ST_DB_ENV_LOG_FLUSH bdb_test_error(envst->envp->log_flush(envst->envp, lsnst->lsn)); #else bdb_test_error(log_flush(envst->envp, lsnst->lsn)); #endif return obj; } static VALUE bdb_lsn_log_compare(VALUE obj, VALUE a) { struct dblsnst *lsnst1, *lsnst2; bdb_ENV *envst1, *envst2; if (!rb_obj_is_kind_of(a, bdb_cLsn)) { rb_raise(bdb_eFatal, "invalid argument for <=>"); } GetLsn(obj, lsnst1, envst1); GetLsn(a, lsnst2, envst2); return INT2NUM(log_compare(lsnst1->lsn, lsnst2->lsn)); } static VALUE bdb_lsn_log_get(int argc, VALUE *argv, VALUE obj) { struct dblsnst *lsnst; DBT data; VALUE res, a; int ret, flags; bdb_ENV *envst; #if HAVE_ST_DB_ENV_LOG_CURSOR DB_LOGC *cursor; #endif flags = DB_SET; if (rb_scan_args(argc, argv, "01", &a) == 1) { flags = NUM2INT(a); } GetLsn(obj, lsnst, envst); #if HAVE_ST_DB_ENV_LOG_CURSOR bdb_test_error(envst->envp->log_cursor(envst->envp, &cursor, 0)); #endif MEMZERO(&data, DBT, 1); data.flags |= DB_DBT_MALLOC; #if HAVE_ST_DB_ENV_LG_INFO if (!envst->envp->lg_info) { rb_raise(bdb_eFatal, "log region not open"); } ret = bdb_test_error(log_get(envst->envp->lg_info, lsnst->lsn, &data, flags)); #elif HAVE_ST_DB_ENV_LOG_CURSOR ret = cursor->get(cursor, lsnst->lsn, &data, flags); cursor->close(cursor, 0); ret = bdb_test_error(ret); #else ret = bdb_test_error(log_get(envst->envp, lsnst->lsn, &data, flags)); #endif if (ret == DB_NOTFOUND) { return Qnil; } res = rb_tainted_str_new(data.data, data.size); free(data.data); return res; } static VALUE bdb_log_register(VALUE obj, VALUE a) { #if ! (HAVE_ST_DB_ENV_LOG_REGISTER || HAVE_DB_LOG_REGISTER || HAVE_ST_DB_ENV_LG_INFO) rb_warn("log_register is obsolete"); return Qnil; #else bdb_DB *dbst; bdb_ENV *envst; if (TYPE(a) != T_STRING) { rb_raise(bdb_eFatal, "Need a filename"); } if (bdb_env_p(obj) == Qfalse) { rb_raise(bdb_eFatal, "Database must be open in an Env"); } Data_Get_Struct(obj, bdb_DB, dbst); Data_Get_Struct(dbst->env, bdb_ENV, envst); #if HAVE_ST_DB_ENV_LG_INFO if (!envst->envp->lg_info) { rb_raise(bdb_eFatal, "log region not open"); } bdb_test_error(log_register(envst->envp->lg_info, dbst->dbp, StringValuePtr(a), dbst->type, &envst->fidp)); #elif HAVE_ST_DB_ENV_LOG_REGISTER bdb_test_error(envst->envp->log_register(envst->envp, dbst->dbp, StringValuePtr(a))); #else #if HAVE_DB_LOG_REGISTER_4 bdb_test_error(log_register(envst->envp, dbst->dbp, StringValuePtr(a), &envst->fidp)); #else bdb_test_error(log_register(envst->envp, dbst->dbp, StringValuePtr(a))); #endif #endif return obj; #endif } static VALUE bdb_log_unregister(VALUE obj) { #if ! (HAVE_ST_DB_ENV_LOG_UNREGISTER || HAVE_DB_LOG_UNREGISTER || HAVE_ST_DB_ENV_LG_INFO) rb_warn("log_unregister is obsolete"); return Qnil; #else bdb_DB *dbst; bdb_ENV *envst; if (bdb_env_p(obj) == Qfalse) { rb_raise(bdb_eFatal, "Database must be open in an Env"); } Data_Get_Struct(obj, bdb_DB, dbst); Data_Get_Struct(dbst->env, bdb_ENV, envst); #if HAVE_ST_DB_ENV_LG_INFO if (!envst->envp->lg_info) { rb_raise(bdb_eFatal, "log region not open"); } bdb_test_error(log_unregister(envst->envp->lg_info, envst->fidp)); #elif HAVE_ST_DB_ENV_LOG_UNREGISTER bdb_test_error(envst->envp->log_unregister(envst->envp, dbst->dbp)); #else #if HAVE_DB_LOG_REGISTER_4 bdb_test_error(log_unregister(envst->envp, envst->fidp)); #else bdb_test_error(log_unregister(envst->envp, dbst->dbp)); #endif #endif return obj; #endif } void bdb_init_log() { rb_define_method(bdb_cEnv, "log_put", bdb_s_log_put, -1); rb_define_method(bdb_cEnv, "log_curlsn", bdb_s_log_curlsn, 0); rb_define_method(bdb_cEnv, "log_checkpoint", bdb_s_log_checkpoint, 1); rb_define_method(bdb_cEnv, "log_flush", bdb_s_log_flush, -1); rb_define_method(bdb_cEnv, "log_stat", bdb_env_log_stat, -1); rb_define_method(bdb_cEnv, "log_archive", bdb_env_log_archive, -1); #if ! HAVE_ST_DB_ENV_LOG_CURSOR rb_define_method(bdb_cEnv, "log_get", bdb_env_log_get, 1); #else rb_define_method(bdb_cEnv, "log_cursor", bdb_env_log_cursor, 0); #endif rb_define_method(bdb_cEnv, "log_each", bdb_env_log_each, 0); rb_define_method(bdb_cEnv, "log_reverse_each", bdb_env_log_hcae, 0); rb_define_method(bdb_cCommon, "log_register", bdb_log_register, 1); rb_define_method(bdb_cCommon, "log_unregister", bdb_log_unregister, 0); bdb_cLsn = rb_define_class_under(bdb_mDb, "Lsn", rb_cObject); rb_include_module(bdb_cLsn, rb_mComparable); #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_undef_alloc_func(bdb_cLsn); #else rb_undef_method(CLASS_OF(bdb_cLsn), "allocate"); #endif rb_undef_method(CLASS_OF(bdb_cLsn), "new"); rb_define_method(bdb_cLsn, "env", bdb_lsn_env, 0); #if HAVE_ST_DB_ENV_LOG_CURSOR rb_define_method(bdb_cLsn, "log_cursor", bdb_log_cursor, 0); rb_define_method(bdb_cLsn, "cursor", bdb_log_cursor, 0); rb_define_method(bdb_cLsn, "log_close", bdb_log_cursor_close, 0); rb_define_method(bdb_cLsn, "close", bdb_log_cursor_close, 0); rb_define_method(bdb_cLsn, "log_each", bdb_log_each, 0); rb_define_method(bdb_cLsn, "each", bdb_log_each, 0); rb_define_method(bdb_cLsn, "log_reverse_each", bdb_log_hcae, 0); rb_define_method(bdb_cLsn, "reverse_each", bdb_log_hcae, 0); #endif rb_define_method(bdb_cLsn, "log_get", bdb_lsn_log_get, -1); rb_define_method(bdb_cLsn, "get", bdb_lsn_log_get, -1); rb_define_method(bdb_cLsn, "log_compare", bdb_lsn_log_compare, 1); rb_define_method(bdb_cLsn, "compare", bdb_lsn_log_compare, 1); rb_define_method(bdb_cLsn, "<=>", bdb_lsn_log_compare, 1); rb_define_method(bdb_cLsn, "log_file", bdb_lsn_log_file, 0); rb_define_method(bdb_cLsn, "file", bdb_lsn_log_file, 0); rb_define_method(bdb_cLsn, "log_flush", bdb_lsn_log_flush, 0); rb_define_method(bdb_cLsn, "flush", bdb_lsn_log_flush, 0); } ruby-bdb-0.6.6/src/recnum.c000066400000000000000000000553571154714021300154720ustar00rootroot00000000000000#include "bdb.h" static ID id_cmp; static VALUE bdb_recnum_init(int argc, VALUE *argv, VALUE obj) { VALUE *nargv; VALUE array = rb_str_new2("array_base"); VALUE sarray = rb_str_new2("set_array_base"); if (!argc || TYPE(argv[argc - 1]) != T_HASH) { nargv = ALLOCA_N(VALUE, argc + 1); MEMCPY(nargv, argv, VALUE, argc); nargv[argc] = rb_hash_new(); argv = nargv; argc++; } rb_hash_aset(argv[argc - 1], array, INT2FIX(0)); if (rb_hash_aref(argv[argc - 1], sarray) != RHASH(argv[argc - 1])->ifnone) { rb_hash_aset(argv[argc - 1], sarray, INT2FIX(0)); } rb_hash_aset(argv[argc - 1], rb_str_new2("set_flags"), INT2FIX(DB_RENUMBER)); return bdb_init(argc, argv, obj); } static VALUE bdb_sary_subseq(VALUE obj, long beg, long len) { VALUE ary2, a; bdb_DB *dbst; long i; GetDB(obj, dbst); if (beg > dbst->len) return Qnil; if (beg < 0 || len < 0) return Qnil; if (beg + len > dbst->len) { len = dbst->len - beg; } if (len <= 0) return rb_ary_new2(0); ary2 = rb_ary_new2(len); for (i = 0; i < len; i++) { a = INT2NUM(i + beg); rb_ary_push(ary2, bdb_get(1, &a, obj)); } return ary2; } static VALUE bdb_sary_entry(VALUE obj, VALUE position) { bdb_DB *dbst; long offset; GetDB(obj, dbst); if (dbst->len == 0) return Qnil; offset = NUM2LONG(position); if (offset < 0) { offset += dbst->len; } if (offset < 0 || dbst->len <= offset) return Qnil; position = INT2NUM(offset); return bdb_get(1, &position, obj); } static VALUE bdb_sary_aref(int argc, VALUE *argv, VALUE obj) { VALUE arg1, arg2; long beg, len; bdb_DB *dbst; GetDB(obj, dbst); if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) { beg = NUM2LONG(arg1); len = NUM2LONG(arg2); if (beg < 0) { beg = dbst->len + beg; } return bdb_sary_subseq(obj, beg, len); } if (FIXNUM_P(arg1)) { return bdb_sary_entry(obj, arg1); } else if (TYPE(arg1) == T_BIGNUM) { rb_raise(rb_eIndexError, "index too big"); } else { switch (rb_range_beg_len(arg1, &beg, &len, dbst->len, 0)) { case Qfalse: break; case Qnil: return Qnil; default: return bdb_sary_subseq(obj, beg, len); } } return bdb_sary_entry(obj, arg1); } static VALUE bdb_intern_shift_pop(VALUE obj, int depart, int len) { bdb_DB *dbst; DB_TXN *txnid; DBC *dbcp; DBT key, data; int i, ret, flags; db_recno_t recno; VALUE res; rb_secure(4); INIT_TXN(txnid, obj, dbst); #if HAVE_DB_CURSOR_4 bdb_test_error(dbst->dbp->cursor(dbst->dbp, txnid, &dbcp, 0)); #else bdb_test_error(dbst->dbp->cursor(dbst->dbp, txnid, &dbcp)); #endif SET_PARTIAL(dbst, data); flags = TEST_INIT_LOCK(dbst); res = rb_ary_new2(len); for (i = 0; i < len; i++) { MEMZERO(&key, DBT, 1); INIT_RECNO(dbst, key, recno); MEMZERO(&data, DBT, 1); data.flags = DB_DBT_MALLOC; bdb_cache_error(dbcp->c_get(dbcp, &key, &data, depart | flags), dbcp->c_close(dbcp), ret); if (ret == DB_NOTFOUND) break; rb_ary_push(res, bdb_test_load(obj, &data, FILTER_VALUE)); bdb_cache_error(dbcp->c_del(dbcp, 0), dbcp->c_close(dbcp), ret); if (dbst->len > 0) dbst->len--; } dbcp->c_close(dbcp); if (RARRAY_LEN(res) == 0) return Qnil; else if (RARRAY_LEN(res) == 1) return RARRAY_PTR(res)[0]; else return res; } static void bdb_sary_replace(VALUE obj, VALUE beg, long len, long rpl) { long i, j, rlen; VALUE tmp[2]; bdb_DB *dbst; GetDB(obj, dbst); if (len < 0) rb_raise(rb_eIndexError, "negative length %ld", len); if (beg < 0) { beg += dbst->len; } if (beg < 0) { beg -= dbst->len; rb_raise(rb_eIndexError, "index %ld out of array", beg); } if (beg + len > dbst->len) { len = dbst->len - beg; } if (NIL_P(rpl)) { rpl = rb_ary_new2(0); } else if (TYPE(rpl) != T_ARRAY) { rpl = rb_ary_new3(1, rpl); } rlen = RARRAY_LEN(rpl); tmp[1] = Qnil; if (beg >= dbst->len) { for (i = dbst->len; i < beg; i++) { tmp[0] = INT2NUM(i); bdb_put(2, tmp, obj); dbst->len++; } for (i = beg, j = 0; j < RARRAY_LEN(rpl); i++, j++) { tmp[0] = INT2NUM(i); tmp[1] = RARRAY_PTR(rpl)[j]; bdb_put(2, tmp, obj); dbst->len++; } } else { if (len < rlen) { tmp[1] = Qnil; for (i = dbst->len - 1; i >= (beg + len); i--) { tmp[0] = INT2NUM(i); tmp[1] = bdb_get(1, tmp, obj); tmp[0] = INT2NUM(i + rlen - len); bdb_put(2, tmp, obj); } dbst->len += rlen - len; } for (i = beg, j = 0; j < rlen; i++, j++) { tmp[0] = INT2NUM(i); tmp[1] = RARRAY_PTR(rpl)[j]; bdb_put(2, tmp, obj); } if (len > rlen) { for (i = beg + len; i < dbst->len; i++) { tmp[0] = INT2NUM(i); tmp[1] = bdb_get(1, tmp, obj); tmp[0] = INT2NUM(i + rlen - len); bdb_put(2, tmp, obj); } bdb_intern_shift_pop(obj, DB_LAST, len - rlen); } } } static VALUE bdb_sary_aset(int argc, VALUE *argv, VALUE obj) { long beg, len; bdb_DB *dbst; GetDB(obj, dbst); if (argc == 3) { bdb_sary_replace(obj, NUM2LONG(argv[0]), NUM2LONG(argv[1]), argv[2]); return argv[2]; } if (argc != 2) { rb_raise(rb_eArgError, "wrong # of arguments(%d for 2)", argc); } if (FIXNUM_P(argv[0])) { beg = FIX2LONG(argv[0]); goto fixnum; } else if (rb_range_beg_len(argv[0], &beg, &len, dbst->len, 1)) { bdb_sary_replace(obj, beg, len, argv[1]); return argv[1]; } if (TYPE(argv[0]) == T_BIGNUM) { rb_raise(rb_eIndexError, "index too big"); } beg = NUM2LONG(argv[0]); fixnum: if (beg < 0) { beg += dbst->len; if (beg < 0) { rb_raise(rb_eIndexError, "index %ld out of array", beg - dbst->len); } } if (beg > dbst->len) { VALUE nargv[2]; int i; nargv[1] = Qnil; for (i = dbst->len; i < beg; i++) { nargv[0] = INT2NUM(i); bdb_put(2, nargv, obj); dbst->len++; } } argv[0] = INT2NUM(beg); bdb_put(2, argv, obj); dbst->len++; return argv[1]; } #if HAVE_RB_ARY_INSERT static VALUE bdb_sary_insert(int argc, VALUE *argv, VALUE obj) { long pos; if (argc < 2) { rb_raise(rb_eArgError, "wrong number of arguments(at least 2)"); } pos = NUM2LONG(argv[0]); if (pos == -1) { bdb_DB *dbst; GetDB(obj, dbst); pos = dbst->len; } else if (pos < 0) { pos++; } bdb_sary_replace(obj, pos, 0, rb_ary_new4(argc-1, argv+1)); return obj; } #endif static VALUE bdb_sary_at(VALUE obj, VALUE pos) { return bdb_sary_entry(obj, pos); } static VALUE bdb_sary_first(VALUE obj) { bdb_DB *dbst; VALUE tmp; GetDB(obj, dbst); tmp = INT2NUM(0); return bdb_get(1, &tmp, obj); } static VALUE bdb_sary_last(VALUE obj) { bdb_DB *dbst; VALUE tmp; GetDB(obj, dbst); if (!dbst->len) return Qnil; tmp = INT2NUM(dbst->len); return bdb_get(1, &tmp, obj); } static VALUE bdb_sary_fetch(int argc, VALUE *argv, VALUE obj) { VALUE pos, ifnone; bdb_DB *dbst; long idx; GetDB(obj, dbst); rb_scan_args(argc, argv, "11", &pos, &ifnone); idx = NUM2LONG(pos); if (idx < 0) { idx += dbst->len; } if (idx < 0 || dbst->len <= idx) { return ifnone; } pos = INT2NUM(idx); return bdb_get(1, &pos, obj); } static VALUE bdb_sary_concat(VALUE obj, VALUE y) { bdb_DB *dbst; long i; VALUE tmp[2]; y = rb_convert_type(y, T_ARRAY, "Array", "to_ary"); GetDB(obj, dbst); for (i = 0; i < RARRAY_LEN(y); i++) { tmp[0] = INT2NUM(dbst->len); tmp[1] = RARRAY_PTR(y)[i]; bdb_put(2, tmp, obj); dbst->len++; } return obj; } static VALUE bdb_sary_push(VALUE obj, VALUE y) { bdb_DB *dbst; VALUE tmp[2]; GetDB(obj, dbst); tmp[0] = INT2NUM(dbst->len); tmp[1] = y; bdb_put(2, tmp, obj); dbst->len++; return obj; } static VALUE bdb_sary_push_m(int argc, VALUE *argv, VALUE obj) { bdb_DB *dbst; long i; VALUE tmp[2]; if (argc == 0) { rb_raise(rb_eArgError, "wrong # of arguments(at least 1)"); } if (argc > 0) { GetDB(obj, dbst); for (i = 0; i < argc; i++) { tmp[0] = INT2NUM(dbst->len); tmp[1] = argv[i]; bdb_put(2, tmp, obj); dbst->len++; } } return obj; } static VALUE bdb_sary_s_create(int argc, VALUE *argv, VALUE obj) { VALUE res; res = rb_funcall2(obj, rb_intern("new"), 0, 0); if (argc < 0) { rb_raise(rb_eArgError, "negative number of arguments"); } if (argc > 0) { bdb_sary_push_m(argc, argv, res); } return res; } static VALUE bdb_sary_shift(VALUE obj) { VALUE res; bdb_DB *dbst; GetDB(obj, dbst); if (dbst->len == 0) return Qnil; res = bdb_intern_shift_pop(obj, DB_FIRST, 1); return res; } static VALUE bdb_sary_pop(VALUE obj) { VALUE res; bdb_DB *dbst; GetDB(obj, dbst); if (dbst->len == 0) return Qnil; res = bdb_intern_shift_pop(obj, DB_LAST, 1); return res; } static VALUE bdb_sary_unshift_m(int argc, VALUE *argv, VALUE obj) { bdb_DB *dbst; VALUE tmp[2]; long i; if (argc == 0) { rb_raise(rb_eArgError, "wrong # of arguments(at least 1)"); } if (argc > 0) { /* ++ */ GetDB(obj, dbst); for (i = dbst->len - 1; i >= 0; i++) { tmp[0] = INT2NUM(i); tmp[1] = bdb_get(1, tmp, obj); tmp[0] = INT2NUM(i + argc); bdb_put(2, tmp, obj); } for (i = 0; i < argc; i++) { tmp[0] = INT2NUM(i); tmp[1] = argv[i]; bdb_put(2, tmp, obj); dbst->len++; } } return obj; } static VALUE bdb_sary_length(VALUE obj) { bdb_DB *dbst; GetDB(obj, dbst); if (dbst->len < 0) rb_raise(bdb_eFatal, "Invalid BDB::Recnum"); return INT2NUM(dbst->len); } static VALUE bdb_sary_empty_p(VALUE obj) { bdb_DB *dbst; GetDB(obj, dbst); if (dbst->len < 0) rb_raise(bdb_eFatal, "Invalid BDB::Recnum"); return (dbst->len)?Qfalse:Qtrue; } static VALUE bdb_sary_rindex(VALUE obj, VALUE a) { return bdb_internal_value(obj, a, Qtrue, DB_PREV); } static VALUE bdb_sary_to_a(VALUE obj) { return bdb_to_type(obj, rb_ary_new(), Qfalse); } static VALUE bdb_sary_reverse_m(VALUE obj) { return bdb_to_type(obj, rb_ary_new(), Qnil); } static VALUE bdb_sary_reverse_bang(VALUE obj) { long i, j; bdb_DB *dbst; VALUE tmp[2], interm; GetDB(obj, dbst); if (dbst->len <= 1) return obj; i = 0; j = dbst->len - 1; while (i < j) { tmp[0] = INT2NUM(i); interm = bdb_get(1, tmp, obj); tmp[0] = INT2NUM(j); tmp[1] = bdb_get(1, tmp, obj); tmp[0] = INT2NUM(i); bdb_put(2, tmp, obj); tmp[0] = INT2NUM(j); tmp[1] = interm; bdb_put(2, tmp, obj); i++; j--; } return obj; } static VALUE bdb_sary_collect_bang(int argc, VALUE *argv, VALUE obj) { return bdb_each_kvc(argc, argv, obj, DB_NEXT, Qtrue, BDB_ST_VALUE); } static VALUE bdb_sary_collect(int argc, VALUE *argv, VALUE obj) { if (!rb_block_given_p()) { return bdb_sary_to_a(obj); } return bdb_each_kvc(argc, argv, obj, DB_NEXT, rb_ary_new(), BDB_ST_VALUE); } static VALUE bdb_sary_select(int argc, VALUE *argv, VALUE obj) { VALUE result; long i; if (rb_block_given_p()) { if (argc > 0) { rb_raise(rb_eArgError, "wrong number arguments(%d for 0)", argc); } return bdb_each_kvc(argc, argv, obj, DB_NEXT, rb_ary_new(), BDB_ST_SELECT); } #if HAVE_RB_ARY_VALUES_AT rb_warn("Recnum#select(index..) is deprecated; use Recnum#values_at"); #endif result = rb_ary_new(); for (i = 0; i < argc; i++) { rb_ary_push(result, bdb_sary_fetch(1, argv + i, obj)); } return result; } static VALUE bdb_sary_values_at(int argc, VALUE *argv, VALUE obj) { VALUE result; long i; result = rb_ary_new(); for (i = 0; i < argc; i++) { rb_ary_push(result, bdb_sary_fetch(1, argv + i, obj)); } return result; } static VALUE bdb_sary_indexes(int argc, VALUE *argv, VALUE obj) { #if HAVE_RB_ARY_VALUES_AT rb_warn("Recnum#%s is deprecated; use Recnum#values_at", #if HAVE_RB_FRAME_THIS_FUNC rb_id2name(rb_frame_this_func())); #else rb_id2name(rb_frame_last_func())); #endif #endif return bdb_sary_values_at(argc, argv, obj); } static VALUE bdb_sary_filter(int argc, VALUE *argv, VALUE obj) { rb_warn("BDB::Recnum#filter is deprecated; use BDB::Recnum#collect!"); return bdb_sary_collect_bang(argc, argv, obj); } static VALUE bdb_sary_delete(VALUE obj, VALUE item) { bdb_DB *dbst; long i1, i2; VALUE tmp, a; GetDB(obj, dbst); i2 = dbst->len; for (i1 = 0; i1 < dbst->len;) { tmp = INT2NUM(i1); a = bdb_get(1, &tmp, obj); if (rb_equal(a, item)) { bdb_del(obj, INT2NUM(i1)); dbst->len--; } else { i1++; } } if (dbst->len == i2) { if (rb_block_given_p()) { return rb_yield(item); } return Qnil; } return item; } static VALUE bdb_sary_delete_at_m(VALUE obj, VALUE a) { bdb_DB *dbst; long pos; VALUE tmp; VALUE del = Qnil; GetDB(obj, dbst); pos = NUM2INT(a); if (pos >= dbst->len) return Qnil; if (pos < 0) pos += dbst->len; if (pos < 0) return Qnil; tmp = INT2NUM(pos); del = bdb_get(1, &tmp, obj); bdb_del(obj, tmp); dbst->len--; return del; } static VALUE bdb_sary_reject_bang(VALUE obj) { bdb_DB *dbst; long i1, i2; VALUE tmp, a; GetDB(obj, dbst); i2 = dbst->len; for (i1 = 0; i1 < dbst->len;) { tmp = INT2NUM(i1); a = bdb_get(1, &tmp, obj); if (!RTEST(rb_yield(a))) { i1++; continue; } bdb_del(obj, tmp); dbst->len--; } if (dbst->len == i2) return Qnil; return obj; } static VALUE bdb_sary_delete_if(VALUE obj) { bdb_sary_reject_bang(obj); return obj; } static VALUE bdb_sary_replace_m(VALUE obj, VALUE obj2) { bdb_DB *dbst; GetDB(obj, dbst); obj2 = rb_convert_type(obj2, T_ARRAY, "Array", "to_ary"); bdb_sary_replace(obj, 0, dbst->len, obj2); return obj; } static VALUE bdb_sary_clear(int argc, VALUE *argv, VALUE obj) { bdb_DB *dbst; VALUE g; int flags = 0; if (argc && TYPE(argv[argc - 1]) == T_HASH) { VALUE f = argv[argc - 1]; if ((g = rb_hash_aref(f, rb_intern("flags"))) != RHASH(f)->ifnone || (g = rb_hash_aref(f, rb_str_new2("flags"))) != RHASH(f)->ifnone) { flags = NUM2INT(g); } argc--; } if (argc == 1) { flags = NUM2INT(argv[0]); } g = INT2FIX(flags); bdb_clear(1, &g, obj); GetDB(obj, dbst); dbst->len = 0; return obj; } static VALUE bdb_sary_fill(int argc, VALUE *argv, VALUE obj) { VALUE item, arg1, arg2, tmp[2]; long beg, len, i; bdb_DB *dbst; GetDB(obj, dbst); rb_scan_args(argc, argv, "12", &item, &arg1, &arg2); switch (argc) { case 1: len = dbst->len; beg = 0; break; case 2: if (rb_range_beg_len(arg1, &beg, &len, dbst->len, 1)) { break; } /* fall through */ case 3: beg = NIL_P(arg1)?0:NUM2LONG(arg1); if (beg < 0) { beg += dbst->len; if (beg < 0) beg = 0; } len = NIL_P(arg2)?dbst->len - beg:NUM2LONG(arg2); break; } tmp[1] = item; for (i = 0; i < len; i++) { tmp[0] = INT2NUM(i + beg); bdb_put(2, tmp, obj); if ((i + beg) >= dbst->len) dbst->len++; } return obj; } static VALUE bdb_sary_cmp(VALUE obj, VALUE obj2) { bdb_DB *dbst, *dbst2 = 0; VALUE a, a2, tmp, ary; long i, len; if (obj == obj2) return INT2FIX(0); GetDB(obj, dbst); len = dbst->len; if (!rb_obj_is_kind_of(obj2, bdb_cRecnum)) { obj2 = rb_convert_type(obj2, T_ARRAY, "Array", "to_ary"); if (len > RARRAY_LEN(obj2)) { len = RARRAY_LEN(obj2); } ary = Qtrue; } else { GetDB(obj2, dbst2); len = dbst->len; if (len > dbst2->len) { len = dbst2->len; } ary = Qfalse; } for (i = 0; i < len; i++) { tmp = INT2NUM(i); a = bdb_get(1, &tmp, obj); if (ary) { a2 = RARRAY_PTR(obj2)[i]; } else { a2 = bdb_get(1, &tmp, obj2); } tmp = rb_funcall(a, id_cmp, 1, a2); if (tmp != INT2FIX(0)) { return tmp; } } len = dbst->len - ary?RARRAY_LEN(obj2):dbst2->len; if (len == 0) return INT2FIX(0); if (len > 0) return INT2FIX(1); return INT2FIX(-1); } static VALUE bdb_sary_slice_bang(int argc, VALUE *argv, VALUE obj) { VALUE arg1, arg2; long pos, len; bdb_DB *dbst; GetDB(obj, dbst); if (rb_scan_args(argc, argv, "11", &arg1, &arg2) == 2) { pos = NUM2LONG(arg1); len = NUM2LONG(arg2); delete_pos_len: if (pos < 0) { pos = dbst->len + pos; } arg2 = bdb_sary_subseq(obj, pos, len); bdb_sary_replace(obj, pos, len, Qnil); return arg2; } if (!FIXNUM_P(arg1) && rb_range_beg_len(arg1, &pos, &len, dbst->len, 1)) { goto delete_pos_len; } pos = NUM2LONG(arg1); if (pos >= dbst->len) return Qnil; if (pos < 0) pos += dbst->len; if (pos < 0) return Qnil; arg1 = INT2NUM(pos); arg2 = bdb_sary_at(obj, arg1); if (bdb_del(obj, arg1) != Qnil) dbst->len--; return arg2; } static VALUE bdb_sary_plus(VALUE obj, VALUE y) { return rb_ary_plus(bdb_sary_to_a(obj), y); } static VALUE bdb_sary_times(VALUE obj, VALUE y) { return rb_funcall(bdb_sary_to_a(obj), rb_intern("*"), 1, y); } static VALUE bdb_sary_diff(VALUE obj, VALUE y) { return rb_funcall(bdb_sary_to_a(obj), rb_intern("-"), 1, y); } static VALUE bdb_sary_and(VALUE obj, VALUE y) { return rb_funcall(bdb_sary_to_a(obj), rb_intern("&"), 1, y); } static VALUE bdb_sary_or(VALUE obj, VALUE y) { return rb_funcall(bdb_sary_to_a(obj), rb_intern("|"), 1, y); } static VALUE bdb_sary_compact(VALUE obj) { return rb_funcall(bdb_sary_to_a(obj), rb_intern("compact!"), 0, 0); } static VALUE bdb_sary_compact_bang(VALUE obj) { bdb_DB *dbst; long i, j; VALUE tmp; GetDB(obj, dbst); j = dbst->len; for (i = 0; i < dbst->len; ) { tmp = INT2NUM(i); tmp = bdb_get(1, &tmp, obj); if (NIL_P(tmp)) { bdb_del(obj, INT2NUM(i)); dbst->len--; } else { i++; } } if (dbst->len == j) return Qnil; return obj; } static VALUE bdb_sary_nitems(VALUE obj) { bdb_DB *dbst; long i, j; VALUE tmp; GetDB(obj, dbst); j = 0; for (i = 0; i < dbst->len; ) { tmp = INT2NUM(i); tmp = bdb_get(1, &tmp, obj); if (!NIL_P(tmp)) j++; } return INT2NUM(j); } void bdb_init_recnum() { id_cmp = rb_intern("<=>"); bdb_cRecnum = rb_define_class_under(bdb_mDb, "Recnum", bdb_cCommon); rb_define_singleton_method(bdb_cRecnum, "[]", bdb_sary_s_create, -1); rb_define_private_method(bdb_cRecnum, "initialize", bdb_recnum_init, -1); rb_define_method(bdb_cRecnum, "[]", bdb_sary_aref, -1); rb_define_method(bdb_cRecnum, "get", bdb_sary_aref, -1); rb_define_method(bdb_cRecnum, "db_get", bdb_sary_aref, -1); rb_define_method(bdb_cRecnum, "[]=", bdb_sary_aset, -1); rb_define_method(bdb_cRecnum, "put", bdb_sary_aset, -1); rb_define_method(bdb_cRecnum, "db_put", bdb_sary_aset, -1); rb_define_method(bdb_cRecnum, "store", bdb_sary_aset, -1); rb_define_method(bdb_cRecnum, "at", bdb_sary_at, 1); rb_define_method(bdb_cRecnum, "fetch", bdb_sary_fetch, -1); rb_define_method(bdb_cRecnum, "first", bdb_sary_first, 0); rb_define_method(bdb_cRecnum, "last", bdb_sary_last, 0); rb_define_method(bdb_cRecnum, "concat", bdb_sary_concat, 1); rb_define_method(bdb_cRecnum, "<<", bdb_sary_push, 1); rb_define_method(bdb_cRecnum, "push", bdb_sary_push_m, -1); rb_define_method(bdb_cRecnum, "pop", bdb_sary_pop, 0); rb_define_method(bdb_cRecnum, "shift", bdb_sary_shift, 0); rb_define_method(bdb_cRecnum, "unshift", bdb_sary_unshift_m, -1); #if HAVE_RB_ARY_INSERT rb_define_method(bdb_cRecnum, "insert", bdb_sary_insert, -1); #endif rb_define_method(bdb_cRecnum, "each", bdb_each_value, -1); rb_define_method(bdb_cRecnum, "each_index", bdb_each_key, -1); rb_define_method(bdb_cRecnum, "reverse_each", bdb_each_eulav, -1); rb_define_method(bdb_cRecnum, "length", bdb_sary_length, 0); rb_define_alias(bdb_cRecnum, "size", "length"); rb_define_method(bdb_cRecnum, "empty?", bdb_sary_empty_p, 0); rb_define_method(bdb_cRecnum, "index", bdb_index, 1); rb_define_method(bdb_cRecnum, "rindex", bdb_sary_rindex, 1); rb_define_method(bdb_cRecnum, "indexes", bdb_sary_indexes, -1); rb_define_method(bdb_cRecnum, "indices", bdb_sary_indexes, -1); rb_define_method(bdb_cRecnum, "reverse", bdb_sary_reverse_m, 0); rb_define_method(bdb_cRecnum, "reverse!", bdb_sary_reverse_bang, 0); rb_define_method(bdb_cRecnum, "collect", bdb_sary_collect, -1); rb_define_method(bdb_cRecnum, "collect!", bdb_sary_collect_bang, -1); #if HAVE_RB_ARY_VALUES_AT rb_define_method(bdb_cRecnum, "map", bdb_sary_collect, 0); rb_define_method(bdb_cRecnum, "select", bdb_sary_select, -1); rb_define_method(bdb_cRecnum, "values_at", bdb_sary_values_at, -1); #endif rb_define_method(bdb_cRecnum, "map!", bdb_sary_collect_bang, -1); rb_define_method(bdb_cRecnum, "filter", bdb_sary_filter, -1); rb_define_method(bdb_cRecnum, "delete", bdb_sary_delete, 1); rb_define_method(bdb_cRecnum, "delete_at", bdb_sary_delete_at_m, 1); rb_define_method(bdb_cRecnum, "delete_if", bdb_sary_delete_if, 0); rb_define_method(bdb_cRecnum, "reject!", bdb_sary_reject_bang, 0); rb_define_method(bdb_cRecnum, "replace", bdb_sary_replace_m, 1); rb_define_method(bdb_cRecnum, "clear", bdb_sary_clear, -1); rb_define_method(bdb_cRecnum, "fill", bdb_sary_fill, -1); rb_define_method(bdb_cRecnum, "include?", bdb_has_value, 1); rb_define_method(bdb_cRecnum, "<=>", bdb_sary_cmp, 1); rb_define_method(bdb_cRecnum, "slice", bdb_sary_aref, -1); rb_define_method(bdb_cRecnum, "slice!", bdb_sary_slice_bang, -1); /* rb_define_method(bdb_cRecnum, "assoc", bdb_sary_assoc, 1); rb_define_method(bdb_cRecnum, "rassoc", bdb_sary_rassoc, 1); */ rb_define_method(bdb_cRecnum, "+", bdb_sary_plus, 1); rb_define_method(bdb_cRecnum, "*", bdb_sary_times, 1); rb_define_method(bdb_cRecnum, "-", bdb_sary_diff, 1); rb_define_method(bdb_cRecnum, "&", bdb_sary_and, 1); rb_define_method(bdb_cRecnum, "|", bdb_sary_or, 1); /* rb_define_method(bdb_cRecnum, "uniq", bdb_sary_uniq, 0); rb_define_method(bdb_cRecnum, "uniq!", bdb_sary_uniq_bang, 0); */ rb_define_method(bdb_cRecnum, "compact", bdb_sary_compact, 0); rb_define_method(bdb_cRecnum, "compact!", bdb_sary_compact_bang, 0); /* rb_define_method(bdb_cRecnum, "flatten", bdb_sary_flatten, 0); rb_define_method(bdb_cRecnum, "flatten!", bdb_sary_flatten_bang, 0); */ rb_define_method(bdb_cRecnum, "nitems", bdb_sary_nitems, 0); rb_define_method(bdb_cRecnum, "stat", bdb_tree_stat, -1); rb_define_method(bdb_cRecnum, "to_a", bdb_sary_to_a, 0); rb_define_method(bdb_cRecnum, "to_ary", bdb_sary_to_a, 0); /* RECNO */ rb_define_method(bdb_cRecno, "shift", bdb_sary_shift, 0); rb_define_method(bdb_cRecno, "to_a", bdb_sary_to_a, 0); rb_define_method(bdb_cRecno, "to_ary", bdb_sary_to_a, 0); rb_define_method(bdb_cRecno, "pop", bdb_sary_pop, 0); /* QUEUE */ #if HAVE_CONST_DB_QUEUE rb_define_method(bdb_cQueue, "to_a", bdb_sary_to_a, 0); rb_define_method(bdb_cQueue, "to_ary", bdb_sary_to_a, 0); #endif } ruby-bdb-0.6.6/src/sequence.c000066400000000000000000000206441154714021300160000ustar00rootroot00000000000000#include "bdb.h" #if HAVE_TYPE_DB_SEQUENCE static VALUE bdb_cSeq; static void bdb_seq_free(bdb_SEQ *seqst) { if (seqst->seqp) { seqst->seqp->close(seqst->seqp, 0); seqst->seqp = NULL; } free(seqst); } static void bdb_seq_mark(bdb_SEQ *seqst) { rb_gc_mark(seqst->db); rb_gc_mark(seqst->txn); rb_gc_mark(seqst->orig); } static VALUE bdb_seq_close(VALUE obj) { bdb_SEQ *seqst; GetSEQ(obj, seqst); seqst->seqp->close(seqst->seqp, 0); seqst->seqp = NULL; return Qnil; } static VALUE bdb_seq_txn_dup(VALUE obj, VALUE a) { bdb_SEQ *seq0, *seq1; bdb_TXN *txnst; VALUE res; GetSEQ(obj, seq0); GetTxnDB(a, txnst); res = Data_Make_Struct(obj, bdb_SEQ, bdb_seq_mark, bdb_seq_free, seq1); MEMCPY(seq1, seq0, bdb_SEQ, 1); seq1->txn = a; seq1->txnid = txnst->txnid; seq1->orig = obj; return res; } static VALUE bdb_seq_txn_close(VALUE obj, VALUE commit, VALUE real) { bdb_SEQ *seqst; if (!real) { Data_Get_Struct(obj, bdb_SEQ, seqst); seqst->seqp = NULL; } else { bdb_seq_close(obj); } return Qnil; } static VALUE bdb_seq_i_options(VALUE obj, VALUE seqobj) { VALUE key, value; bdb_SEQ *seqst; char *options; key = rb_ary_entry(obj, 0); value = rb_ary_entry(obj, 1); key = rb_obj_as_string(key); options = StringValuePtr(key); Data_Get_Struct(seqobj, bdb_SEQ, seqst); if (strcmp(options, "set_cachesize") == 0) { if (seqst->seqp->set_cachesize(seqst->seqp, NUM2INT(value))) { seqst->seqp->remove(seqst->seqp, 0, 0); rb_raise(rb_eArgError, "Invalid value (%d) for set_cachesize", NUM2INT(value)); } } else if (strcmp(options, "set_flags") == 0) { if (seqst->seqp->set_flags(seqst->seqp, NUM2INT(value))) { seqst->seqp->remove(seqst->seqp, 0, 0); rb_raise(rb_eArgError, "Invalid value (%d) for set_flags", NUM2INT(value)); } } else if (strcmp(options, "set_range") == 0) { Check_Type(value, T_ARRAY); if (RARRAY_LEN(value) != 2) { rb_raise(bdb_eFatal, "expected 2 values for range"); } if (seqst->seqp->set_range(seqst->seqp, NUM2LONG(RARRAY_PTR(value)[0]), NUM2LONG(RARRAY_PTR(value)[1]))) { seqst->seqp->remove(seqst->seqp, 0, 0); rb_raise(rb_eArgError, "Invalid value (%ld, %ld) for set_range", NUM2LONG(RARRAY_PTR(value)[0]), NUM2LONG(RARRAY_PTR(value)[1])); } } else { rb_warning("Unknown option %s", options); } return Qnil; } static VALUE bdb_seq_open(int argc, VALUE *argv, VALUE obj) { VALUE a, b, c, res; int flags = 0, count; bdb_DB *dbst; DB_TXN *txnid; DBT key; db_seq_t value; db_recno_t recno; bdb_SEQ *seqst; VALUE options = Qnil; INIT_TXN(txnid, obj, dbst); res = Data_Make_Struct(bdb_cSeq, bdb_SEQ, bdb_seq_mark, bdb_seq_free, seqst); seqst->db = obj; if (argc && TYPE(argv[argc - 1]) == T_HASH) { options = argv[argc - 1]; argc--; } count = rb_scan_args(argc, argv, "12", &a, &b, &c); bdb_test_error(db_sequence_create(&seqst->seqp, dbst->dbp, 0)); switch (count) { case 3: value = NUM2LONG(c); if (seqst->seqp->initial_value(seqst->seqp, value)) { seqst->seqp->remove(seqst->seqp, 0, 0); rb_raise(rb_eArgError, "invalid initial value"); } /* ... */ case 2: if (!NIL_P(flags)) { flags = NUM2INT(b); } break; } if (!NIL_P(options)) { rb_iterate(rb_each, options, bdb_seq_i_options, res); } a = bdb_test_recno(obj, &key, &recno, a); if (seqst->seqp->open(seqst->seqp, txnid, &key, flags)) { seqst->seqp->remove(seqst->seqp, txnid, 0); rb_raise(rb_eArgError, "can't open the sequence"); } seqst->txn = dbst->txn; seqst->txnid = txnid; if (rb_block_given_p()) { return rb_ensure(rb_yield, res, bdb_seq_close, res); } return res; } static VALUE bdb_seq_s_open(int argc, VALUE *argv, VALUE obj) { VALUE args[4]; if (argc <= 0 || argc > 3) { rb_raise(rb_eArgError, "Invalid number of arguments %d", argc); } args[0] = argv[0]; args[1] = INT2NUM(DB_CREATE | DB_EXCL); if (argc > 1) { args[2] = argv[1]; if (argc > 2) { args[3] = argv[2]; } } return bdb_seq_open(argc + 1, args, obj); } static VALUE bdb_seq_remove(int argc, VALUE *argv, VALUE obj) { bdb_SEQ *seqst; VALUE a; int flags = 0; GetSEQ(obj, seqst); if (rb_scan_args(argc, argv, "01", &a)) { flags = NUM2INT(a); } if (seqst->seqp->remove(seqst->seqp, seqst->txnid, flags)) { rb_raise(rb_eArgError, "invalid argument"); } seqst->seqp = NULL; return Qnil; } static VALUE bdb_seq_get(int argc, VALUE *argv, VALUE obj) { bdb_SEQ *seqst; int delta = 1, flags = 0; VALUE a, b; db_seq_t val; GetSEQ(obj, seqst); switch (rb_scan_args(argc, argv, "02", &a, &b)) { case 2: flags = NUM2INT(b); /* ... */ case 1: delta = NUM2INT(a); } bdb_test_error(seqst->seqp->get(seqst->seqp, seqst->txnid, delta, &val, flags)); return LONG2NUM(val); } static VALUE bdb_seq_cachesize(VALUE obj) { bdb_SEQ *seqst; int size; GetSEQ(obj, seqst); bdb_test_error(seqst->seqp->get_cachesize(seqst->seqp, &size)); return INT2NUM(size); } static VALUE bdb_seq_flags(VALUE obj) { bdb_SEQ *seqst; unsigned int flags; GetSEQ(obj, seqst); bdb_test_error(seqst->seqp->get_flags(seqst->seqp, &flags)); return INT2NUM(flags); } static VALUE bdb_seq_range(VALUE obj) { bdb_SEQ *seqst; db_seq_t deb, fin; GetSEQ(obj, seqst); bdb_test_error(seqst->seqp->get_range(seqst->seqp, &deb, &fin)); return rb_assoc_new(LONG2NUM(deb), LONG2NUM(fin)); } static VALUE bdb_seq_stat(int argc, VALUE *argv, VALUE obj) { bdb_SEQ *seqst; int flags = 0; VALUE a, res; DB_SEQUENCE_STAT sta; GetSEQ(obj, seqst); if (rb_scan_args(argc, argv, "01", &a)) { flags = NUM2INT(a); } bdb_test_error(seqst->seqp->stat(seqst->seqp, (void *)&sta, flags)); res = rb_hash_new(); rb_hash_aset(res, rb_str_new2("wait"), INT2NUM(sta.st_wait)); rb_hash_aset(res, rb_str_new2("nowait"), INT2NUM(sta.st_nowait)); rb_hash_aset(res, rb_str_new2("current"), INT2NUM(sta.st_current)); rb_hash_aset(res, rb_str_new2("value"), INT2NUM(sta.st_value)); rb_hash_aset(res, rb_str_new2("last_value"), INT2NUM(sta.st_last_value)); rb_hash_aset(res, rb_str_new2("min"), INT2NUM(sta.st_min)); rb_hash_aset(res, rb_str_new2("max"), INT2NUM(sta.st_max)); rb_hash_aset(res, rb_str_new2("cache_size"), INT2NUM(sta.st_cache_size)); rb_hash_aset(res, rb_str_new2("flags"), INT2NUM(sta.st_flags)); return res; } static VALUE bdb_seq_db(VALUE obj) { bdb_SEQ *seqst; GetSEQ(obj, seqst); return seqst->db; } static VALUE bdb_seq_key(VALUE obj) { bdb_SEQ *seqst; DBT key; GetSEQ(obj, seqst); bdb_test_error(seqst->seqp->get_key(seqst->seqp, &key)); return bdb_test_load_key(seqst->db, &key); } #endif void bdb_init_sequence() { #if HAVE_TYPE_DB_SEQUENCE bdb_cSeq = rb_define_class_under(bdb_mDb, "Sequence", rb_cObject); #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_undef_alloc_func(bdb_cSeq); #else rb_undef_method(CLASS_OF(bdb_cSeq), "allocate"); #endif rb_undef_method(CLASS_OF(bdb_cSeq), "new"); rb_define_method(bdb_cCommon, "open_sequence", bdb_seq_open, -1); rb_define_method(bdb_cCommon, "create_sequence", bdb_seq_s_open, -1); rb_define_method(bdb_cSeq, "get", bdb_seq_get, -1); rb_define_method(bdb_cSeq, "stat", bdb_seq_stat, -1); rb_define_method(bdb_cSeq, "close", bdb_seq_close, 0); rb_define_method(bdb_cSeq, "remove", bdb_seq_remove, -1); rb_define_method(bdb_cSeq, "range", bdb_seq_range, 0); rb_define_method(bdb_cSeq, "cachesize", bdb_seq_cachesize, 0); rb_define_method(bdb_cSeq, "flags", bdb_seq_flags, 0); rb_define_method(bdb_cSeq, "db", bdb_seq_db, 0); rb_define_method(bdb_cSeq, "key", bdb_seq_key, 0); rb_define_private_method(bdb_cSeq, "__txn_close__", bdb_seq_txn_close, 2); rb_define_private_method(bdb_cSeq, "__txn_dup__", bdb_seq_txn_dup, 1); #endif } ruby-bdb-0.6.6/src/transaction.c000066400000000000000000000576241154714021300165250ustar00rootroot00000000000000#include "bdb.h" static ID id_txn_close; static VALUE txn_close_i(VALUE ary[]) { if (bdb_respond_to(ary[0], id_txn_close)) { rb_funcall(ary[0], id_txn_close, 2, ary[1], ary[2]); } return Qnil; } static void clean_ary(bdb_TXN *txnst, VALUE result) { VALUE *ary, tmp[3]; int i, len; tmp[0] = Qnil; tmp[1] = result; tmp[2] = Qtrue; if (txnst->db_ary.ptr) { txnst->db_ary.mark = Qtrue; ary = txnst->db_ary.ptr; len = txnst->db_ary.len; for (i = 0; i < len; i++) { tmp[0] = ary[i]; txn_close_i(tmp); } txnst->db_ary.mark = Qfalse; txnst->db_ary.ptr = 0; txnst->db_ary.total = txnst->db_ary.len = 0; free(ary); } tmp[2] = Qfalse; if (txnst->db_assoc.ptr) { txnst->db_assoc.mark = Qtrue; ary = txnst->db_assoc.ptr; len = txnst->db_assoc.len; for (i = 0; i < len; i++) { tmp[0] = ary[i]; txn_close_i(tmp); } txnst->db_assoc.mark = Qfalse; txnst->db_assoc.ptr = 0; txnst->db_assoc.total = txnst->db_assoc.len = 0; free(ary); } } static VALUE txn_free(bdb_TXN *txnst) { if (txnst->txnid && txnst->parent == NULL) { #if HAVE_ST_DB_TXN_ABORT #if HAVE_DBXML_INTERFACE if (txnst->txn_cxx_abort) bdb_test_error(txnst->txn_cxx_abort(txnst->txn_cxx) ); else #endif bdb_test_error(txnst->txnid->abort(txnst->txnid)); #else txn_abort(txnst->txnid); #endif txnst->txnid = NULL; } #if HAVE_DBXML_INTERFACE if (txnst->txn_cxx_free) txnst->txn_cxx_free(&(txnst->txn_cxx)); if (txnst->txn_cxx) free(txnst->txn_cxx); #endif clean_ary(txnst, Qfalse); return Qnil; } static void bdb_txn_free(bdb_TXN *txnst) { txn_free(txnst); free(txnst); } static void bdb_txn_mark(bdb_TXN *txnst) { rb_gc_mark(txnst->marshal); rb_gc_mark(txnst->mutex); #if HAVE_DBXML_INTERFACE rb_gc_mark(txnst->man); #endif bdb_ary_mark(&txnst->db_ary); bdb_ary_mark(&txnst->db_assoc); } static VALUE bdb_txn_assoc(int argc, VALUE *argv, VALUE obj) { int i; VALUE ary, a; bdb_TXN *txnst; ary = rb_ary_new(); GetTxnDB(obj, txnst); for (i = 0; i < argc; i++) { a = rb_funcall(argv[i], rb_intern("__txn_dup__"), 1, obj); bdb_ary_push(&txnst->db_assoc, a); rb_ary_push(ary, a); } switch (RARRAY_LEN(ary)) { case 0: return Qnil; case 1: return RARRAY_PTR(ary)[0]; default: return ary; } } static void bdb_txn_close_all(VALUE obj, VALUE result) { bdb_TXN *txnst; bdb_ENV *envst; GetTxnDB(obj, txnst); GetEnvDB(txnst->env, envst); bdb_clean_env(txnst->env, obj); clean_ary(txnst, result); } #define THROW 1 #define COMMIT 2 #define ROLLBACK 3 static VALUE bdb_txn_commit(int argc, VALUE *argv, VALUE obj) { bdb_TXN *txnst; VALUE a; int flags; rb_secure(4); flags = 0; if (rb_scan_args(argc, argv, "01", &a) == 1) { flags = NUM2INT(a); } GetTxnDB(obj, txnst); bdb_txn_close_all(obj, Qtrue); #if HAVE_ST_DB_TXN_COMMIT #if HAVE_DBXML_INTERFACE if (txnst->txn_cxx_commit) bdb_test_error(txnst->txn_cxx_commit(txnst->txn_cxx, flags) ); else #endif bdb_test_error(txnst->txnid->commit(txnst->txnid, flags)); #else #if HAVE_TXN_COMMIT_2 bdb_test_error(txn_commit(txnst->txnid, flags)); #else bdb_test_error(txn_commit(txnst->txnid)); #endif #endif txnst->txnid = NULL; if (txnst->status == THROW) { txnst->status = COMMIT; rb_throw("__bdb__begin", Data_Wrap_Struct(bdb_cTxnCatch, 0, 0, txnst)); } return Qtrue; } static VALUE bdb_txn_abort(VALUE obj) { bdb_TXN *txnst; GetTxnDB(obj, txnst); bdb_txn_close_all(obj, Qfalse); #if HAVE_ST_DB_TXN_ABORT #if HAVE_DBXML_INTERFACE if (txnst->txn_cxx_abort) bdb_test_error(txnst->txn_cxx_abort(txnst->txn_cxx) ); else #endif bdb_test_error(txnst->txnid->abort(txnst->txnid)); #else bdb_test_error(txn_abort(txnst->txnid)); #endif txnst->txnid = NULL; if (txnst->status == THROW) { txnst->status = ROLLBACK; rb_throw("__bdb__begin", Data_Wrap_Struct(bdb_cTxnCatch, 0, 0, txnst)); } return Qtrue; } static VALUE bdb_txn_unlock(VALUE txnv) { bdb_TXN *txnst; Data_Get_Struct(txnv, bdb_TXN, txnst); if (txnst->mutex != Qnil) { rb_funcall2(txnst->mutex, rb_intern("unlock"), 0, 0); } return Qnil; } static VALUE bdb_catch(VALUE val, VALUE args, VALUE self) { rb_yield(args); return Qtrue; } static VALUE bdb_txn_lock(VALUE obj) { VALUE result; bdb_TXN *txnst; VALUE txnv; if (TYPE(obj) == T_ARRAY) { txnv = RARRAY_PTR(obj)[0]; } else { txnv = obj; } Data_Get_Struct(txnv, bdb_TXN, txnst); if (!NIL_P(txnst->mutex)) { rb_funcall2(txnst->mutex, rb_intern("lock"), 0, 0); } txnst->status = THROW; result = rb_catch("__bdb__begin", bdb_catch, obj); if (rb_obj_is_kind_of(result, bdb_cTxnCatch)) { bdb_TXN *txn1; Data_Get_Struct(result, bdb_TXN, txn1); if (txn1 == txnst) { return Qnil; } txnst->status = 0; bdb_txn_close_all(txnv, txn1->status == COMMIT); txnst->txnid = NULL; return result; } txnst->status = 0; if (txnst->txnid) { if (txnst->options & BDB_TXN_COMMIT) { bdb_txn_commit(0, 0, txnv); } else { bdb_txn_abort(txnv); } } return Qnil; } struct dbtxnopt { int flags; VALUE mutex; VALUE timeout, txn_timeout, lock_timeout; }; static VALUE bdb_txn_i_options(VALUE obj, VALUE dbstobj) { struct dbtxnopt *opt = (struct dbtxnopt *)dbstobj; VALUE key, value; char *options; key = rb_ary_entry(obj, 0); value = rb_ary_entry(obj, 1); key = rb_obj_as_string(key); options = StringValuePtr(key); if (strcmp(options, "flags") == 0) { opt->flags = NUM2INT(value); } else if (strcmp(options, "mutex") == 0) { if (rb_respond_to(value, rb_intern("lock")) && rb_respond_to(value, rb_intern("unlock"))) { if (!rb_block_given_p()) { rb_warning("a mutex is useless without a block"); } else { opt->mutex = value; } } else { rb_raise(bdb_eFatal, "mutex must respond to #lock and #unlock"); } } #if HAVE_ST_DB_TXN_SET_TIMEOUT else if (strcmp(options, "timeout") == 0) { opt->timeout = value; } else if (strcmp(options, "txn_timeout") == 0) { opt->txn_timeout = value; } else if (strcmp(options, "lock_timeout") == 0) { opt->lock_timeout = value; } #endif return Qnil; } #if HAVE_ST_DB_TXN_SET_TIMEOUT static VALUE bdb_txn_set_timeout _((VALUE, VALUE)); static VALUE bdb_txn_set_txn_timeout _((VALUE, VALUE)); static VALUE bdb_txn_set_lock_timeout _((VALUE, VALUE)); #endif VALUE bdb_env_rslbl_begin(VALUE origin, int argc, VALUE *argv, VALUE obj) { bdb_TXN *txnst, *txnstpar; DB_TXN *txn, *txnpar; DB_ENV *envp; bdb_ENV *envst; VALUE txnv, b, env; int flags, commit; VALUE marshal, options; struct dbtxnopt opt; txnpar = 0; flags = commit = 0; envst = 0; env = 0; options = Qnil; opt.flags = 0; opt.mutex = opt.timeout = opt.txn_timeout = opt.lock_timeout = Qnil; if (argc > 0 && TYPE(argv[argc - 1]) == T_HASH) { options = argv[argc - 1]; argc--; rb_iterate(rb_each, options, bdb_txn_i_options, (VALUE)&opt); flags = opt.flags; if (flags & BDB_TXN_COMMIT) { commit = 1; flags &= ~BDB_TXN_COMMIT; } } if (argc > 0 && FIXNUM_P(argv[0])) { flags = NUM2INT(argv[0]); if (flags & BDB_TXN_COMMIT) { commit = 1; flags &= ~BDB_TXN_COMMIT; } argc--; argv++; } if (rb_obj_is_kind_of(obj, bdb_cTxn)) { GetTxnDB(obj, txnstpar); txnpar = txnstpar->txnid; env = txnstpar->env; GetEnvDB(env, envst); envp = envst->envp; marshal = txnstpar->marshal; } else { GetEnvDB(obj, envst); env = obj; envp = envst->envp; marshal = envst->marshal; } #if HAVE_ST_DB_ENV_TX_INFO if (envp->tx_info == NULL) { rb_raise(bdb_eFatal, "Transaction Manager not enabled"); } bdb_test_error(txn_begin(envp->tx_info, txnpar, &txn)); #else #if HAVE_ST_DB_ENV_TXN_BEGIN if (origin == Qfalse) { bdb_test_error(envp->txn_begin(envp, txnpar, &txn, flags)); } #if HAVE_DBXML_INTERFACE else { txn = ((struct txn_rslbl *)origin)->txn; } #endif #else bdb_test_error(txn_begin(envp, txnpar, &txn, flags)); #endif #endif txnv = Data_Make_Struct(bdb_cTxn, bdb_TXN, bdb_txn_mark, bdb_txn_free, txnst); txnst->env = env; txnst->marshal = marshal; txnst->txnid = txn; txnst->parent = txnpar; txnst->status = 0; txnst->options = envst->options & BDB_INIT_LOCK; txnst->mutex = opt.mutex; bdb_ary_unshift(&envst->db_ary, txnv); if (commit) { txnst->options |= BDB_TXN_COMMIT; } #if HAVE_DBXML_INTERFACE if (origin != Qfalse) { txnst->txn_cxx = ((struct txn_rslbl *)origin)->txn_cxx; txnst->txn_cxx_free = ((struct txn_rslbl *)origin)->txn_cxx_free; txnst->txn_cxx_abort = ((struct txn_rslbl *)origin)->txn_cxx_abort; txnst->txn_cxx_commit = ((struct txn_rslbl *)origin)->txn_cxx_commit; txnst->txn_cxx_discard = ((struct txn_rslbl *)origin)->txn_cxx_discard; txnst->man = ((struct txn_rslbl *)origin)->man; } #endif b = bdb_txn_assoc(argc, argv, txnv); #if HAVE_ST_DB_TXN_SET_TIMEOUT if (!NIL_P(options)) { bdb_txn_set_timeout(txnv, opt.timeout); bdb_txn_set_txn_timeout(txnv, opt.txn_timeout); bdb_txn_set_lock_timeout(txnv, opt.lock_timeout); } #endif { VALUE tmp; if (b == Qnil) { tmp = txnv; } else { tmp = rb_ary_new(); rb_ary_push(tmp, txnv); if (TYPE(b) == T_ARRAY) { long i; for (i = 0; i < RARRAY_LEN(b); i++) { rb_ary_push(tmp, RARRAY_PTR(b)[i]); } } else { rb_ary_push(tmp, b); } } if (rb_block_given_p()) { int state = 0; tmp = rb_protect(bdb_txn_lock, tmp, &state); if (!NIL_P(txnst->mutex)) { bdb_txn_unlock(txnv); } if (state) { txnst->status = ROLLBACK; bdb_txn_abort(txnv); rb_jump_tag(state); } if (!NIL_P(tmp)) { rb_throw("__bdb__begin", tmp); } return Qnil; } return tmp; } } static VALUE bdb_env_begin(int argc, VALUE *argv, VALUE obj) { return bdb_env_rslbl_begin(Qfalse, argc, argv, obj); } static VALUE bdb_txn_id(VALUE obj) { bdb_TXN *txnst; int res; GetTxnDB(obj, txnst); #if HAVE_ST_DB_TXN_ID res = txnst->txnid->id(txnst->txnid); #else res = txn_id(txnst->txnid); #endif return INT2FIX(res); } static VALUE #if HAVE_ST_DB_TXN_PREPARE || HAVE_TXN_PREPARE bdb_txn_prepare(VALUE obj, VALUE txnid) #else bdb_txn_prepare(VALUE obj) #endif { bdb_TXN *txnst; unsigned char id; GetTxnDB(obj, txnst); #if HAVE_ST_DB_TXN_PREPARE id = (unsigned char)NUM2INT(txnid); bdb_test_error(txnst->txnid->prepare(txnst->txnid, &id)); #else #if HAVE_TXN_PREPARE_2 id = (unsigned char)NUM2INT(txnid); bdb_test_error(txn_prepare(txnst->txnid, &id)); #else bdb_test_error(txn_prepare(txnst->txnid)); #endif #endif return Qtrue; } static VALUE bdb_env_check(int argc, VALUE *argv, VALUE obj) { unsigned int kbyte, min, flag; bdb_ENV *envst; VALUE a, b, c; kbyte = min = flag = 0; a = b = Qnil; #if HAVE_ST_DB_ENV_TXN_CHECKPOINT || HAVE_TXN_CHECKPOINT_4 switch (rb_scan_args(argc, argv, "03", &a, &b, &c)) { case 3: flag = NUM2INT(c); case 2: min = NUM2UINT(b); } #else if (rb_scan_args(argc, argv, "02", &a, &b) == 2) { min = NUM2UINT(b); } #endif if (!NIL_P(a)) kbyte = NUM2UINT(a); GetEnvDB(obj, envst); #if HAVE_ST_DB_ENV_TX_INFO if (envst->envp->tx_info == NULL) { rb_raise(bdb_eFatal, "Transaction Manager not enabled"); } bdb_test_error(txn_checkpoint(envst->envp->tx_info, kbyte, min)); #else #if HAVE_ST_DB_ENV_TXN_CHECKPOINT bdb_test_error(envst->envp->txn_checkpoint(envst->envp, kbyte, min, flag)); #else #if HAVE_TXN_CHECKPOINT_4 bdb_test_error(txn_checkpoint(envst->envp, kbyte, min, flag)); #else bdb_test_error(txn_checkpoint(envst->envp, kbyte, min)); #endif #endif #endif return Qnil; } #if HAVE_ST_DB_ENV_TXN_RECOVER || HAVE_TXN_RECOVER static VALUE bdb_env_recover(VALUE obj) { unsigned int flags; long retp; unsigned char id; DB_PREPLIST preplist[1]; bdb_ENV *envst; bdb_TXN *txnst; VALUE txnv; if (!rb_block_given_p()) { rb_raise(bdb_eFatal, "call out of an iterator"); } rb_secure(4); GetEnvDB(obj, envst); txnv = Data_Make_Struct(bdb_cTxn, bdb_TXN, bdb_txn_mark, bdb_txn_free, txnst); txnst->env = obj; txnst->marshal = envst->marshal; txnst->options = envst->options & BDB_INIT_LOCK; flags = DB_FIRST; while (1) { #if HAVE_ST_DB_ENV_TXN_RECOVER bdb_test_error(envst->envp->txn_recover(envst->envp, preplist, 1, &retp, flags)); #else bdb_test_error(txn_recover(envst->envp, preplist, 1, &retp, flags)); #endif if (retp == 0) break; txnst->txnid = preplist[0].txn; id = (unsigned char)preplist[0].gid[0]; rb_yield(rb_assoc_new(txnv, INT2NUM(id))); flags = DB_NEXT; } return obj; } #endif #if HAVE_ST_DB_TXN_DISCARD || HAVE_TXN_DISCARD static VALUE bdb_txn_discard(VALUE obj) { bdb_TXN *txnst; int flags; rb_secure(4); flags = 0; GetTxnDB(obj, txnst); #if HAVE_ST_DB_TXN_DISCARD #if HAVE_DBXML_INTERFACE if (txnst->txn_cxx_discard) bdb_test_error(txnst->txn_cxx_discard(txnst->txn_cxx, flags) ); else #endif bdb_test_error(txnst->txnid->discard(txnst->txnid, flags)); #else bdb_test_error(txn_discard(txnst->txnid, flags)); #endif txnst->txnid = NULL; return Qtrue; } #endif static VALUE bdb_env_stat(int argc, VALUE *argv, VALUE obj) { bdb_ENV *envst; VALUE a, b; DB_TXN_STAT *bdb_stat; int flags; #if HAVE_ST_DB_ENV_TXN_STAT flags = 0; if (rb_scan_args(argc, argv, "01", &b) == 1) { flags = NUM2INT(b); } #else if (argc != 0) { rb_raise(rb_eArgError, "invalid number of arguments (%d for 0)", argc); } #endif GetEnvDB(obj, envst); #if HAVE_ST_DB_ENV_TX_INFO if (envst->envp->tx_info == NULL) { rb_raise(bdb_eFatal, "Transaction Manager not enabled"); } bdb_test_error(txn_stat(envst->envp->tx_info, &bdb_stat, malloc)); #else #if HAVE_ST_DB_ENV_TXN_STAT bdb_test_error(envst->envp->txn_stat(envst->envp, &bdb_stat, flags)); #else #if HAVE_TXN_STAT_3 bdb_test_error(txn_stat(envst->envp, &bdb_stat, malloc)); #else bdb_test_error(txn_stat(envst->envp, &bdb_stat)); #endif #endif #endif a = rb_hash_new(); rb_hash_aset(a, rb_tainted_str_new2("st_time_ckp"), INT2NUM(bdb_stat->st_time_ckp)); rb_hash_aset(a, rb_tainted_str_new2("st_last_txnid"), INT2NUM(bdb_stat->st_last_txnid)); rb_hash_aset(a, rb_tainted_str_new2("st_maxtxns"), INT2NUM(bdb_stat->st_maxtxns)); rb_hash_aset(a, rb_tainted_str_new2("st_naborts"), INT2NUM(bdb_stat->st_naborts)); rb_hash_aset(a, rb_tainted_str_new2("st_nbegins"), INT2NUM(bdb_stat->st_nbegins)); rb_hash_aset(a, rb_tainted_str_new2("st_ncommits"), INT2NUM(bdb_stat->st_ncommits)); rb_hash_aset(a, rb_tainted_str_new2("st_nactive"), INT2NUM(bdb_stat->st_nactive)); #if HAVE_ST_DB_TXN_STAT_ST_MAXNACTIVE rb_hash_aset(a, rb_tainted_str_new2("st_maxnactive"), INT2NUM(bdb_stat->st_maxnactive)); #endif #if HAVE_ST_DB_TXN_STAT_ST_REGSIZE rb_hash_aset(a, rb_tainted_str_new2("st_regsize"), INT2NUM(bdb_stat->st_regsize)); #endif #if HAVE_ST_DB_TXN_STAT_ST_REGION_WAIT rb_hash_aset(a, rb_tainted_str_new2("st_region_wait"), INT2NUM(bdb_stat->st_region_wait)); #endif #if HAVE_ST_DB_TXN_STAT_ST_REGION_NOWAIT rb_hash_aset(a, rb_tainted_str_new2("st_region_nowait"), INT2NUM(bdb_stat->st_region_nowait)); #endif #if HAVE_ST_DB_TXN_STAT_ST_LAST_CKP { struct dblsnst *lsnst; VALUE ary, hash, lsn; int i; #if HAVE_ST_DB_TXN_STAT_ST_NRESTORES rb_hash_aset(a, rb_tainted_str_new2("st_nrestores"), INT2NUM(bdb_stat->st_nrestores)); #endif lsn = bdb_makelsn(obj); Data_Get_Struct(lsn, struct dblsnst, lsnst); MEMCPY(lsnst->lsn, &bdb_stat->st_last_ckp, DB_LSN, 1); rb_hash_aset(a, rb_tainted_str_new2("st_last_ckp"), lsn); #if HAVE_ST_DB_TXN_STAT_ST_PENDING_CKP lsn = bdb_makelsn(obj); Data_Get_Struct(lsn, struct dblsnst, lsnst); MEMCPY(lsnst->lsn, &bdb_stat->st_pending_ckp, DB_LSN, 1); rb_hash_aset(a, rb_tainted_str_new2("st_pending_ckp"), lsn); #endif ary = rb_ary_new2(bdb_stat->st_nactive); for (i = 0; i < bdb_stat->st_nactive; i++) { hash = rb_hash_new(); rb_hash_aset(hash, rb_tainted_str_new2("txnid"), INT2NUM(bdb_stat->st_txnarray[i].txnid)); #if HAVE_ST_DB_TXN_ACTIVE_PARENTID rb_hash_aset(hash, rb_tainted_str_new2("parentid"), INT2NUM(bdb_stat->st_txnarray[i].parentid)); #endif lsn = bdb_makelsn(obj); Data_Get_Struct(lsn, struct dblsnst, lsnst); MEMCPY(lsnst->lsn, &bdb_stat->st_txnarray[i].lsn, DB_LSN, 1); rb_hash_aset(hash, rb_tainted_str_new2("lsn"), lsn); #if HAVE_ST_DB_TXN_ACTIVE_TID rb_hash_aset(hash, rb_tainted_str_new2("thread_id"), INT2NUM(bdb_stat->st_txnarray[i].tid)); #endif #if HAVE_ST_DB_TXN_ACTIVE_NAME rb_hash_aset(hash, rb_tainted_str_new2("name"), rb_tainted_str_new2(bdb_stat->st_txnarray[i].name)); #endif rb_ary_push(ary, hash); } } #endif free(bdb_stat); return a; } #if HAVE_ST_DB_TXN_SET_TIMEOUT static VALUE bdb_txn_set_txn_timeout(VALUE obj, VALUE a) { bdb_TXN *txnst; if (!NIL_P(a)) { GetTxnDB(obj, txnst); bdb_test_error(txnst->txnid->set_timeout(txnst->txnid, NUM2UINT(a), DB_SET_TXN_TIMEOUT)); } return obj; } static VALUE bdb_txn_set_lock_timeout(VALUE obj, VALUE a) { bdb_TXN *txnst; if (!NIL_P(a)) { GetTxnDB(obj, txnst); bdb_test_error(txnst->txnid->set_timeout(txnst->txnid, NUM2UINT(a), DB_SET_LOCK_TIMEOUT)); } return obj; } static VALUE bdb_txn_set_timeout(VALUE obj, VALUE a) { if (!NIL_P(a)) { if (TYPE(a) == T_ARRAY) { if (RARRAY_LEN(a) >= 1 && !NIL_P(RARRAY_PTR(a)[0])) { bdb_txn_set_txn_timeout(obj, RARRAY_PTR(a)[0]); } if (RARRAY_LEN(a) == 2 && !NIL_P(RARRAY_PTR(a)[1])) { bdb_txn_set_lock_timeout(obj, RARRAY_PTR(a)[1]); } } else { bdb_txn_set_txn_timeout(obj, a); } } return obj; } #endif #if HAVE_ST_DB_ENV_DBREMOVE static VALUE bdb_env_dbremove(int argc, VALUE *argv, VALUE obj) { VALUE a, b, c; char *file, *database; int flags; bdb_ENV *envst; bdb_TXN *txnst; DB_TXN *txnid; rb_secure(2); a = b = c = Qnil; file = database = NULL; flags = 0; rb_scan_args(argc, argv, "03", &a, &b, &c); if (!NIL_P(a)) { SafeStringValue(a); file = StringValuePtr(a); } if (!NIL_P(b)) { SafeStringValue(b); database = StringValuePtr(b); } if (!NIL_P(c)) { flags = NUM2INT(c); } txnid = NULL; if (rb_obj_is_kind_of(obj, bdb_cTxn)) { GetTxnDB(obj, txnst); txnid = txnst->txnid; GetEnvDB(txnst->env, envst); } else { GetEnvDB(obj, envst); } #if HAVE_CONST_DB_AUTO_COMMIT if (txnid == NULL && (envst->options & BDB_AUTO_COMMIT)) { flags |= DB_AUTO_COMMIT; } #endif bdb_test_error(envst->envp->dbremove(envst->envp, txnid, file, database, flags)); return Qnil; } #endif #if HAVE_ST_DB_ENV_DBRENAME static VALUE bdb_env_dbrename(int argc, VALUE *argv, VALUE obj) { VALUE a, b, c, d; char *file, *database, *newname; int flags; bdb_ENV *envst; bdb_TXN *txnst; DB_TXN *txnid; rb_secure(2); a = b = c = Qnil; file = database = newname = NULL; flags = 0; if (rb_scan_args(argc, argv, "22", &a, &b, &c, &d) == 2) { c = b; b = d = Qnil; } if (!NIL_P(a)) { SafeStringValue(a); file = StringValuePtr(a); } if (!NIL_P(b)) { SafeStringValue(b); database = StringValuePtr(b); } if (!NIL_P(c)) { SafeStringValue(c); newname = StringValuePtr(c); } else { rb_raise(bdb_eFatal, "newname not specified"); } if (!NIL_P(d)) { flags = NUM2INT(d); } txnid = NULL; if (rb_obj_is_kind_of(obj, bdb_cTxn)) { GetTxnDB(obj, txnst); txnid = txnst->txnid; GetEnvDB(txnst->env, envst); } else { GetEnvDB(obj, envst); } #if HAVE_CONST_DB_AUTO_COMMIT if (txnid == NULL && (envst->options & BDB_AUTO_COMMIT)) { flags |= DB_AUTO_COMMIT; } #endif bdb_test_error(envst->envp->dbrename(envst->envp, txnid, file, database, newname, flags)); return Qnil; } #endif #if HAVE_ST_DB_TXN_SET_NAME static VALUE bdb_txn_set_name(VALUE obj, VALUE a) { bdb_TXN *txnst; GetTxnDB(obj, txnst); bdb_test_error(txnst->txnid->set_name(txnst->txnid, StringValuePtr(a))); return a; } static VALUE bdb_txn_get_name(VALUE obj) { bdb_TXN *txnst; const char *name; GetTxnDB(obj, txnst); bdb_test_error(txnst->txnid->get_name(txnst->txnid, &name)); return rb_tainted_str_new2(name); } #endif void bdb_init_transaction() { id_txn_close = rb_intern("__txn_close__"); bdb_cTxn = rb_define_class_under(bdb_mDb, "Txn", rb_cObject); bdb_cTxnCatch = rb_define_class_under(bdb_mDb, "DBTxnCatch", bdb_cTxn); #ifdef HAVE_RB_DEFINE_ALLOC_FUNC rb_undef_alloc_func(bdb_cTxn); #else rb_undef_method(CLASS_OF(bdb_cTxn), "allocate"); #endif rb_undef_method(CLASS_OF(bdb_cTxn), "new"); rb_define_method(bdb_cEnv, "begin", bdb_env_begin, -1); rb_define_method(bdb_cEnv, "txn_begin", bdb_env_begin, -1); rb_define_method(bdb_cEnv, "transaction", bdb_env_begin, -1); rb_define_method(bdb_cEnv, "stat", bdb_env_stat, -1); rb_define_method(bdb_cEnv, "txn_stat", bdb_env_stat, -1); rb_define_method(bdb_cEnv, "checkpoint", bdb_env_check, -1); rb_define_method(bdb_cEnv, "txn_checkpoint", bdb_env_check, -1); #if HAVE_ST_DB_ENV_TXN_RECOVER || HAVE_TXN_RECOVER rb_define_method(bdb_cEnv, "txn_recover", bdb_env_recover, 0); rb_define_method(bdb_cEnv, "recover", bdb_env_recover, 0); #endif rb_define_method(bdb_cTxn, "begin", bdb_env_begin, -1); rb_define_method(bdb_cTxn, "txn_begin", bdb_env_begin, -1); rb_define_method(bdb_cTxn, "transaction", bdb_env_begin, -1); rb_define_method(bdb_cTxn, "commit", bdb_txn_commit, -1); rb_define_method(bdb_cTxn, "txn_commit", bdb_txn_commit, -1); rb_define_method(bdb_cTxn, "close", bdb_txn_commit, -1); rb_define_method(bdb_cTxn, "txn_close", bdb_txn_commit, -1); rb_define_method(bdb_cTxn, "abort", bdb_txn_abort, 0); rb_define_method(bdb_cTxn, "txn_abort", bdb_txn_abort, 0); rb_define_method(bdb_cTxn, "id", bdb_txn_id, 0); rb_define_method(bdb_cTxn, "txn_id", bdb_txn_id, 0); #if HAVE_ST_DB_TXN_DISCARD || HAVE_TXN_DISCARD rb_define_method(bdb_cTxn, "discard", bdb_txn_discard, 0); rb_define_method(bdb_cTxn, "txn_discard", bdb_txn_discard, 0); #endif #if HAVE_ST_DB_TXN_PREPARE || HAVE_TXN_PREPARE rb_define_method(bdb_cTxn, "prepare", bdb_txn_prepare, 1); rb_define_method(bdb_cTxn, "txn_prepare", bdb_txn_prepare, 1); #else rb_define_method(bdb_cTxn, "prepare", bdb_txn_prepare, 0); rb_define_method(bdb_cTxn, "txn_prepare", bdb_txn_prepare, 0); #endif rb_define_method(bdb_cTxn, "assoc", bdb_txn_assoc, -1); rb_define_method(bdb_cTxn, "txn_assoc", bdb_txn_assoc, -1); rb_define_method(bdb_cTxn, "associate", bdb_txn_assoc, -1); rb_define_method(bdb_cTxn, "open_db", bdb_env_open_db, -1); #if HAVE_ST_DB_TXN_SET_TIMEOUT rb_define_method(bdb_cTxn, "set_timeout", bdb_txn_set_timeout, 1); rb_define_method(bdb_cTxn, "set_txn_timeout", bdb_txn_set_txn_timeout, 1); rb_define_method(bdb_cTxn, "set_lock_timeout", bdb_txn_set_lock_timeout, 1); rb_define_method(bdb_cTxn, "timeout=", bdb_txn_set_timeout, 1); rb_define_method(bdb_cTxn, "txn_timeout=", bdb_txn_set_txn_timeout, 1); rb_define_method(bdb_cTxn, "lock_timeout=", bdb_txn_set_lock_timeout, 1); #endif #if HAVE_ST_DB_ENV_DBREMOVE rb_define_method(bdb_cEnv, "dbremove", bdb_env_dbremove, -1); rb_define_method(bdb_cTxn, "dbremove", bdb_env_dbremove, -1); #endif #if HAVE_ST_DB_ENV_DBRENAME rb_define_method(bdb_cEnv, "dbrename", bdb_env_dbrename, -1); rb_define_method(bdb_cTxn, "dbrename", bdb_env_dbrename, -1); #endif #if HAVE_ST_DB_TXN_SET_NAME rb_define_method(bdb_cTxn, "name", bdb_txn_get_name, 0); rb_define_method(bdb_cTxn, "name=", bdb_txn_set_name, 1); #endif } ruby-bdb-0.6.6/tests/000077500000000000000000000000001154714021300143715ustar00rootroot00000000000000ruby-bdb-0.6.6/tests/btree.rb000077500000000000000000000430311154714021300160230ustar00rootroot00000000000000#!/usr/bin/ruby $LOAD_PATH.unshift *%w{../src src tests} require 'bdb' require 'runit_' $VERBOSE = nil module BDB class BTCompare < Btree def bdb_bt_compare(a, b) a <=> b end end class AZ < Btree def bdb_store_key(a) "xx_" + a end def bdb_fetch_key(a) a.sub(/^xx_/, '') end def bdb_store_value(a) "yy_" + a end def bdb_fetch_value(a) a.sub(/^yy_/, '') end end end def clean Dir.foreach('tmp') do |x| if FileTest.file?("tmp/#{x}") File.unlink("tmp/#{x}") end end end $bdb, $env = nil, nil clean print "\nVERSION of BDB is #{BDB::VERSION}\n" Inh = defined?(RUNIT) ? RUNIT : Test::Unit class TestBtree < Inh::TestCase def test_00_error assert_raises(BDB::Fatal, "invalid name") do BDB::Btree.new(".", nil, "a") end assert_raises(BDB::Fatal, "invalid Env") do BDB::Btree.open("tmp/aa", nil, "env" => 1) end assert_raises(TypeError) { BDB::Btree.new("tmp/aa", nil, "set_cachesize" => "a") } assert_raises(TypeError) { BDB::Btree.new("tmp/aa", nil, "set_pagesize" => "a") } assert_raises(TypeError) { BDB::Btree.new("tmp/aa", nil, "set_bt_minkey" => "a") } assert_raises(BDB::Fatal) { BDB::Btree.new("tmp/aa", nil, "set_bt_compare" => "a") } assert_raises(BDB::Fatal) { BDB::Btree.new("tmp/aa", nil, "set_bt_prefix" => "a") } assert_raises(BDB::Fatal) { BDB::Btree.new("tmp/aa", nil, "set_fetch_key" => "a") } assert_raises(BDB::Fatal) { BDB::Btree.new("tmp/aa", nil, "set_store_key" => "a") } assert_raises(BDB::Fatal) { BDB::Btree.new("tmp/aa", nil, "set_fetch_value" => "a") } assert_raises(BDB::Fatal) { BDB::Btree.new("tmp/aa", nil, "set_store_value" => "a") } assert_raises(TypeError) { BDB::Btree.new("tmp/aa", nil, "set_lorder" => "a") } end def test_01_init assert_kind_of(BDB::Btree, $bdb = BDB::Btree.new("tmp/aa", nil, "a"), "") end def test_02_get_set assert_equal(true, $bdb.empty?, "") assert_equal("alpha", $bdb["alpha"] = "alpha", "") assert_equal("alpha", $bdb["alpha"], "") assert_equal(nil, $bdb["gamma"] = nil, "") assert_equal(nil, $bdb["gamma"], "") assert($bdb.key?("alpha"), "") assert_equal(false, $bdb.key?("unknown"), "") assert($bdb.value?("alpha"), "") assert_equal(false, $bdb.value?("unknown"), "") assert_equal(false, $bdb.put("alpha", "gamma", BDB::NOOVERWRITE), "") assert_equal("beta", $bdb.fetch("xxx", "beta"), "") assert_equal("xxx", $bdb.fetch("xxx") {|x| x}, "") assert_raises(IndexError) { $bdb.fetch("xxx") } assert_raises(ArgumentError) { $bdb.fetch("xxx", "beta") {} } assert_equal("alpha", $bdb["alpha"], "") assert($bdb.both?("alpha", "alpha"), "") assert_equal(["alpha", "alpha"], $bdb.get("alpha", "alpha", BDB::GET_BOTH), "") assert(! $bdb.both?("alpha", "beta"), "") assert(! $bdb.get("alpha", "beta", BDB::GET_BOTH), "") assert(! $bdb.both?("unknown", "alpha"), "") assert_equal([1, 2, 3], $bdb["array"] = [1, 2, 3], "") assert_equal([1, 2, 3].to_s, $bdb["array"], "") assert_equal({"a" => "b"}, $bdb["hash"] = {"a" => "b"}, "") assert_equal({"a" => "b"}.to_s, $bdb["hash"], "") assert($bdb.sync, "") end def test_03_delete size = $bdb.size i = 0 $bdb.each do |key, value| assert_equal($bdb, $bdb.delete(key), "") i += 1 end assert(size == i, "") assert_equal(0, $bdb.size, "") $hash = {} (33 .. 126).each do |i| key = i.to_s * 5 $bdb[key] = i.to_s * 7 $hash[key] = i.to_s * 7 assert_equal($bdb[key], $hash[key], "") end assert_equal($bdb.size, $hash.size, "") assert_raises(ArgumentError) { $bdb.select("xxx") {}} assert_equal([], $bdb.select { false }, "") arr0 = [] $bdb.each_key {|key| arr0 << key } assert_equal($hash.keys.sort, arr0.sort, "") arr1 = [] $bdb.reverse_each_key {|key| arr1 << key } assert_equal($hash.keys.sort, arr1.sort, "") assert_equal(arr0, arr1.reverse, "") assert_equal($hash.invert, $bdb.invert, "") $bdb.each do |key, value| if rand > 0.5 assert_equal($bdb, $bdb.delete(key), "") $hash.delete(key) end end assert_equal($bdb.size, $hash.size, "") $bdb.each do |key, value| assert_equal($hash[key], value, "") end $hash.each do |key, value| assert($bdb.key?(key), "") assert_equal($bdb, $bdb.delete(key), "") end end def test_04_cursor array = ["a", "b", "c", "d", "e", "f", "g", "h", "i"] array.each do |x| assert_equal(x, $bdb[x] = x, "") end assert(array.size == $bdb.size, "") arr = [] $bdb.each_value do |x| arr << x end assert_equal(array, arr.sort, "") arr = [] $bdb.reverse_each_value do |x| arr << x end assert_equal(array, arr.sort, "") arr = [] $bdb.each_value("d") do |x| arr << x end assert_equal(array - ["a", "b", "c"], arr.sort, "") arr = [] $bdb.reverse_each_value("g") do |x| arr << x end assert_equal(array - ["h", "i"], arr.sort, "") arr = $bdb.reject {|k, v| k == "e" || v == "i" } has = array.reject {|k, v| k == "e" || k == "i" } assert_equal(has, arr.keys.sort, "") $bdb.reject! {|k, v| k == "e" || v == "i" } array.reject! {|k, v| k == "e" || k == "i" } assert_equal(array, $bdb.keys.sort, "") assert_equal(array, $bdb.values.sort, "") end def test_05_reopen assert_equal(nil, $bdb.close, "") assert_kind_of(BDB::Btree, $bdb = BDB::Btree.open("tmp/aa", nil, "w", "set_flags" => BDB::DUP, "set_dup_compare" => lambda {|a, b| a <=> b}), "") assert_equal(0, $bdb.size, "") end def test_06_dup assert_equal("a", $bdb["0"] = "a", "") assert_equal("b", $bdb["0"] = "b", "") assert_equal("c", $bdb["0"] = "c", "") assert_equal("d", $bdb["0"] = "d", "") assert_equal("aa", $bdb["1"] = "aa", "") assert_equal("bb", $bdb["1"] = "bb", "") assert_equal("cc", $bdb["1"] = "cc", "") assert_equal("aaa", $bdb["2"] = "aaa", "") assert_equal("bbb", $bdb["2"] = "bbb", "") assert_equal("aaaa", $bdb["3"] = "aaaa", "") rep = [["a", "b", "c", "d"], ['aa', 'bb', 'cc'], ['aaa', 'bbb'], ['aaaa']] if BDB::VERSION_MAJOR > 2 || BDB::VERSION_MINOR >= 6 for i in [0, 1, 2, 3] k0, v0 = [], [] $bdb.duplicates(i.to_s, false).each {|v| v0 << v} assert_equal(v0.sort, rep[i], "") k0, v0 = [], [] $bdb.each_dup(i.to_s) {|k, v| k0 << k; v0 << v} assert_equal(k0, [i.to_s] * (4 - i), "") assert_equal(v0.sort, rep[i], "") v0 = [] $bdb.each_dup_value(i.to_s) {|v| v0 << v} assert_equal(v0.sort, rep[i], "") end assert_equal(4, $bdb.count("0"), "") assert_equal(3, $bdb.count("1"), "") assert_equal(2, $bdb.count("2"), "") assert_equal(1, $bdb.count("3"), "") assert_equal(0, $bdb.count("4"), "") assert_equal(["a", "b", "c", "d"], $bdb.get_dup("0").sort, "") assert_equal(["aa", "bb", "cc"], $bdb.get_dup("1").sort, "") assert_equal(["aaa", "bbb"], $bdb.get_dup("2").sort, "") assert_equal(["aaaa"], $bdb.get_dup("3"), "") assert_equal([], $bdb.get_dup("4"), "") end end def test_07_in_memory assert_equal(nil, $bdb.close, "") assert_kind_of(BDB::Btree, $bdb = BDB::Btree.open, "") assert_equal(0, $bdb.size, "") end def test_08_in_memory_get_set assert_equal("aa", $bdb["bb"] = "aa", "") assert_equal("cc", $bdb["bb"] = "cc", "") assert_equal("cc", $bdb["bb"], "") assert_equal(nil, $bdb.close, "") end def test_09_partial_get assert_kind_of(BDB::Btree, $bdb = BDB::Btree.open("tmp/aa", nil, "w"), "") { "red" => "boat", "green"=> "house", "blue" => "sea", }.each do |x, y| assert_equal(y, $bdb[x] = y, "") end pon, off, len = $bdb.set_partial(0, 2) assert_equal(false, pon, "") assert_equal(0, off, "") assert_equal(0, len, "") assert_equal("bo", $bdb["red"], "") assert_equal("ho", $bdb["green"], "") assert_equal("se", $bdb["blue"], "") pon, off, len = $bdb.set_partial(3, 2) assert(pon, "") assert_equal(0, off, "") assert_equal(2, len, "") assert_equal("t", $bdb["red"], "") assert_equal("se", $bdb["green"], "") assert_equal(nil, $bdb["blue"], "") pon, off, len = $bdb.partial_clear assert(pon, "") assert_equal(3, off, "") assert_equal(2, len, "") assert_equal("boat", $bdb["red"], "") assert_equal("house", $bdb["green"], "") assert_equal("sea", $bdb["blue"], "") end def test_10_partial_set $bdb.set_partial(0, 2) assert_equal("", $bdb["red"] = "", "") assert_equal("AB", $bdb["green"] = "AB", "") assert_equal("XYZ", $bdb["blue"] = "XYZ", "") assert_equal("KLM", $bdb["yellow"] = "KLM", "") pon, off, len = $bdb.clear_partial assert(pon, "") assert_equal(0, off, "") assert_equal(2, len, "") assert_equal("at", $bdb["red"], "") assert_equal("ABuse", $bdb["green"], "") assert_equal("XYZa", $bdb["blue"], "") assert_equal("KLM", $bdb["yellow"], "") pon, off, len = $bdb.set_partial(3, 2) assert(!pon, "") assert_equal(0, off, "") assert_equal(0, len, "") assert_equal("PPP", $bdb["red"] = "PPP", "") assert_equal("Q", $bdb["green"] = "Q", "") assert_equal("XYZ", $bdb["blue"] = "XYZ", "") assert_equal("TU", $bdb["yellow"] = "TU", "") pon, off, len = $bdb.clear_partial assert(pon, "") assert_equal(3, off, "") assert_equal(2, len, "") assert_equal("at\0PPP", $bdb["red"], "") assert_equal("ABuQ", $bdb["green"], "") assert_equal("XYZXYZ", $bdb["blue"], "") assert_equal("KLMTU", $bdb["yellow"], "") $bdb.close end def test_11_recnum assert_kind_of(BDB::Btree, $bdb = BDB::Btree.open("tmp/aa", nil, "w", "set_flags" => BDB::RECNUM), "") assert_equal(0, $bdb.size, "") arr = ["A 0", "B 1", "C 2", "D 3", "E 4", "F 5", "G 6"] i = 0 arr.each do |x| assert_equal(x, $bdb[i] = x, "") i += 1; end i = 0 $bdb.each_value do |x| assert_equal(arr[i], x, "") i += 1 end $bdb.delete(3); assert_equal(arr.size - 1, $bdb.size, "") assert_equal(nil, $bdb[3], "") $bdb.close end def test_12_unknown $bdb = nil assert_kind_of(BDB::Btree, unknown = BDB::Unknown.open("tmp/aa", nil, "r"), "") unknown.close end def test_13_env clean assert_kind_of(BDB::Env, $env = BDB::Env.open("tmp", BDB::CREATE|BDB::INIT_TRANSACTION)) assert_kind_of(BDB::Btree, $bdb = BDB::Btree.open("aa", nil, "a", "env" => $env), "") end def test_14_txn_commit assert_kind_of(BDB::Txn, txn = $env.begin, "") assert_kind_of(BDB::Btree, db = txn.assoc($bdb), "") assert_equal("aa", db["aa"] = "aa", "") assert_equal("bb", db["bb"] = "bb", "") assert_equal("cc", db["cc"] = "cc", "") assert_equal(3, db.size, "") assert(txn.commit, "") assert_equal(3, $bdb.size, "") end def test_15_txn_abort assert_kind_of(BDB::Txn, txn = $env.begin, "") assert_kind_of(BDB::Btree, db = txn.assoc($bdb), "") assert_equal("aa", db["aa1"] = "aa", "") assert_equal("bb", db["bb1"] = "bb", "") assert_equal("cc", db["cc1"] = "cc", "") assert_equal(6, db.size, "") assert(txn.abort, "") assert_equal(3, $bdb.size, "") end =begin def test_16_txn_abort2 if BDB::VERSION_MAJOR == 2 && BDB::VERSION_MINOR < 7 $stderr.print "skipping test for this version" return "pass" end $env.begin($bdb) do |txn, db| db["aa1"] = "aa" db["bb1"] = "bb" assert_equal(5, db.size, "") txn.begin(db) do |txn1, db1| db1["cc1"] = "cc" assert_equal(6, db1.size, "") txn.abort assert_fail("") end assert_fail("") end assert_equal(3, $bdb.size, "") end def test_17_txn_commit2 if BDB::VERSION_MAJOR == 2 && BDB::VERSION_MINOR < 7 $stderr.print "skipping test for this version" return "pass" end $env.begin($bdb) do |txn, db| db["aa1"] = "aa" db["bb1"] = "bb" assert_equal(5, db.size, "") txn.begin(db) do |txn1, db1| db1["cc1"] = "cc" assert_equal(6, db1.size, "") txn.commit assert_fail("") end assert_fail("") end assert_equal(6, $bdb.size, "") assert_equal(nil, $bdb.close, "") $env.close end =end def intern_btree_delete $hash = {} File.foreach("examples/wordtest") do |line| line.chomp! $hash[line] = line.reverse $bdb[line] = line.reverse end $bdb.each do |k, v| assert_equal($hash[k], v, "") end $bdb.delete_if {|k, v| k[0] == ?a} $hash.delete_if {|k, v| k[0] == ?a} assert_equal($bdb.size, $hash.size, "") $bdb.each do |k, v| assert_equal($hash[k], v, "") end end def test_18_btree_delete clean assert_kind_of(BDB::BTCompare, $bdb = BDB::BTCompare.open("tmp/aa", nil, "w", "set_pagesize" => 1024, "set_cachesize" => [0, 32 * 1024, 0]), "") intern_btree_delete $bdb.close end def test_19_btree_delete clean assert_kind_of(BDB::Btree, $bdb = BDB::Btree.open("tmp/aa", nil, "w", "set_bt_compare" => proc {|a, b| a <=> b}, "set_pagesize" => 1024, "set_cachesize" => [0, 32 * 1024, 0]), "") intern_btree_delete end def test_20_index lines = $hash.keys array = [] 10.times do h = lines[rand(lines.size - 1)] array.push h assert_equal($hash.index(h.reverse), $bdb.index(h.reverse), "") end assert_equal($hash.indexes(array), $bdb.indexes(array), "") array.each do |k| assert($bdb.has_both?(k, k.reverse), "") end end def test_21_convert h = $bdb.to_hash h.each do |k, v| assert_equal(v, $hash[k], "") end $hash.each do |k, v| assert_equal(v, h[k], "") end h1 = $hash.to_a h2 = $bdb.to_a assert_equal(h1.size, h2.size, "") h1.each do |k| assert(h2.include?(k), "") end end if BDB::VERSION_MAJOR == 3 && BDB::VERSION_MINOR >= 3 def test_22_blurb $bdb.each(nil, 10) do |k, v| assert_equal($hash[k], v, "") end $bdb.each_key(nil, 10) do |k| assert($hash.key?(k), "") end $hash.each_key do |k| assert(!!$bdb.key?(k), "") end end end def test_23_sh val = 'a' .. 'zz' assert_equal(nil, $bdb.close, "") File::unlink('tmp/aa') if FileTest.file?('tmp/aa') assert_kind_of(BDB::Btree, $bdb = BDB::AZ.open("tmp/aa", nil, "w"), "") val.each do |l| assert_equal(l, $bdb[l] = l, "") end $bdb.each do |k, v| assert_equal(k, v, "") end assert_equal(nil, $bdb.close, "") assert_kind_of(BDB::Btree, $bdb = BDB::Btree.open("tmp/aa"), "") val.each do |l| assert_equal("yy_#{l}", $bdb["xx_#{l}"], "") end $bdb.each do |k, v| assert_equal("xx_", k[0, 3], "") assert_equal("yy_", v[0, 3], "") end assert_equal(nil, $bdb.close, "") clean end end if defined?(RUNIT) RUNIT::CUI::TestRunner.run(TestBtree.suite) end ruby-bdb-0.6.6/tests/hash.rb000077500000000000000000000373341154714021300156560ustar00rootroot00000000000000#!/usr/bin/ruby $LOAD_PATH.unshift *%w{../src src tests} require 'bdb' require 'runit_' $VERBOSE = nil module BDB class HashRuby < Hash def bdb_h_hash a a.hash end end class AZ < Hash def bdb_store_key(a) "xx_" + a end def bdb_fetch_key(a) a.sub(/^xx_/, '') end def bdb_store_value(a) "yy_" + a end def bdb_fetch_value(a) a.sub(/^yy_/, '') end end end def clean Dir.foreach('tmp') do |x| if FileTest.file?("tmp/#{x}") File.unlink("tmp/#{x}") end end end $bdb, $env = nil, nil clean print "\nVERSION of BDB is #{BDB::VERSION}\n" Inh = defined?(RUNIT) ? RUNIT : Test::Unit class TestHash < Inh::TestCase def test_00_error assert_raises(BDB::Fatal, "invalid name") do BDB::Hash.new(".", nil, "a") end assert_raises(BDB::Fatal, "invalid Env") do BDB::Hash.open("tmp/aa", nil, "env" => 1) end assert_raises(BDB::Fatal) { BDB::Hash.open("tmp/aa", nil, "set_h_hash" => "a") } assert_raises(TypeError) { BDB::Hash.open("tmp/aa", nil, "set_h_ffactor" => "a") } assert_raises(TypeError) { BDB::Hash.open("tmp/aa", nil, "set_h_nelem" => "a") } end def test_01_init assert_kind_of(BDB::Hash, $bdb = BDB::Hash.new("tmp/aa", nil, "a"), "") end def test_02_get_set assert_equal("alpha", $bdb["alpha"] = "alpha", "") assert_equal("alpha", $bdb["alpha"], "") assert_equal(nil, $bdb["gamma"] = nil, "") assert_equal(nil, $bdb["gamma"], "") assert($bdb.key?("alpha"), "") assert_equal(false, $bdb.key?("unknown"), "") assert($bdb.value?("alpha"), "") assert_equal(false, $bdb.value?("unknown"), "") assert_equal(false, $bdb.put("alpha", "gamma", BDB::NOOVERWRITE), "") assert_equal("beta", $bdb.fetch("xxx", "beta"), "") assert_equal("xxx", $bdb.fetch("xxx") {|x| x}, "") assert_raises(IndexError) { $bdb.fetch("xxx") } assert_raises(ArgumentError) { $bdb.fetch("xxx", "beta") {} } assert_equal("alpha", $bdb["alpha"], "") assert($bdb.both?("alpha", "alpha"), "") assert_equal(["alpha", "alpha"], $bdb.get("alpha", "alpha", BDB::GET_BOTH), "") assert(! $bdb.both?("alpha", "beta"), "") assert(! $bdb.get("alpha", "beta", BDB::GET_BOTH), "") assert(! $bdb.both?("unknown", "alpha"), "") assert_equal([1, 2, 3], $bdb["array"] = [1, 2, 3], "") assert_equal([1, 2, 3].to_s, $bdb["array"], "") assert_equal({"a" => "b"}, $bdb["hash"] = {"a" => "b"}, "") assert_equal({"a" => "b"}.to_s, $bdb["hash"], "") assert($bdb.sync, "") end def test_03_delete size = $bdb.size i = 0 $bdb.each do |key, value| assert_equal($bdb, $bdb.delete(key), "") i += 1 end assert(size == i, "") assert_equal(0, $bdb.size, "") $hash = {} (33 .. 126).each do |i| key = i.to_s * 5 $bdb[key] = i.to_s * 7 $hash[key] = i.to_s * 7 assert_equal($bdb[key], $hash[key], "") end assert_equal($bdb.size, $hash.size, "") assert_raises(ArgumentError) { $bdb.select("xxx") {}} assert_equal([], $bdb.select { false }, "") arr0 = [] $bdb.each_key {|key| arr0 << key } assert_equal($hash.keys.sort, arr0.sort, "") arr1 = [] $bdb.reverse_each_key {|key| arr1 << key } assert_equal($hash.keys.sort, arr1.sort, "") assert_equal(arr0, arr1.reverse, "") assert_equal($hash.invert, $bdb.invert, "") $bdb.each do |key, value| if rand < 0.5 assert_equal($bdb, $bdb.delete(key), "") $hash.delete(key) end end assert_equal($bdb.size, $hash.size, "") $bdb.each do |key, value| assert_equal($hash[key], value, "") end $bdb.each do |key, value| assert($hash.key?(key), "") assert_equal($bdb, $bdb.delete(key), "") end end def test_04_cursor array = ["a", "b", "c", "d", "e", "f", "g", "h", "i"] array.each do |x| assert_equal(x, $bdb[x] = x, "") end assert(array.size == $bdb.size, "") arr = [] $bdb.each_value do |x| arr << x end assert_equal(array, arr.sort, "") arr = [] $bdb.reverse_each_value do |x| arr << x end assert_equal(array, arr.sort, "") arr = $bdb.reject {|k, v| k == "e" || v == "i" } has = array.reject {|k, v| k == "e" || k == "i" } assert_equal(has, arr.keys.sort, "") $bdb.reject! {|k, v| k == "e" || v == "i" } array.reject! {|k, v| k == "e" || k == "i" } assert_equal(array, $bdb.keys.sort, "") assert_equal(array, $bdb.values.sort, "") end def test_05_reopen assert_equal(nil, $bdb.close, "") assert_kind_of(BDB::Hash, $bdb = BDB::Hash.open("tmp/aa", nil, "w", "set_flags" => BDB::DUP, "set_dup_compare" => lambda {|a, b| a <=> b}), "") assert_equal(0, $bdb.size, "") end def test_06_dup assert_equal("a", $bdb["0"] = "a", "") assert_equal("b", $bdb["0"] = "b", "") assert_equal("c", $bdb["0"] = "c", "") assert_equal("d", $bdb["0"] = "d", "") assert_equal("aa", $bdb["1"] = "aa", "") assert_equal("bb", $bdb["1"] = "bb", "") assert_equal("cc", $bdb["1"] = "cc", "") assert_equal("aaa", $bdb["2"] = "aaa", "") assert_equal("bbb", $bdb["2"] = "bbb", "") assert_equal("aaaa", $bdb["3"] = "aaaa", "") if BDB::VERSION_MAJOR > 2 || BDB::VERSION_MINOR >= 6 assert_equal(4, $bdb.count("0"), "") assert_equal(3, $bdb.count("1"), "") assert_equal(2, $bdb.count("2"), "") assert_equal(1, $bdb.count("3"), "") assert_equal(0, $bdb.count("4"), "") assert_equal(["a", "b", "c", "d"], $bdb.get_dup("0").sort, "") assert_equal(["aa", "bb", "cc"], $bdb.get_dup("1").sort, "") assert_equal(["aaa", "bbb"], $bdb.get_dup("2").sort, "") assert_equal(["aaaa"], $bdb.get_dup("3"), "") assert_equal([], $bdb.get_dup("4"), "") end end def test_07_in_memory assert_equal(nil, $bdb.close, "") assert_kind_of(BDB::Hash, $bdb = BDB::Hash.open(nil, nil), "") assert_equal(0, $bdb.size, "") end def test_08_in_memory_get_set assert_equal("aa", $bdb["bb"] = "aa", "") assert_equal("cc", $bdb["bb"] = "cc", "") assert_equal("cc", $bdb["bb"], "") assert_equal(nil, $bdb.close, "") end def test_09_partial_get assert_kind_of(BDB::Hash, $bdb = BDB::Hash.open("tmp/aa", nil, "w"), "") { "red" => "boat", "green"=> "house", "blue" => "sea", }.each do |x, y| assert_equal(y, $bdb[x] = y, "") end pon, off, len = $bdb.set_partial(0, 2) assert_equal(false, pon, "") assert_equal(0, off, "") assert_equal(0, len, "") assert_equal("bo", $bdb["red"], "") assert_equal("ho", $bdb["green"], "") assert_equal("se", $bdb["blue"], "") pon, off, len = $bdb.set_partial(3, 2) assert(pon, "") assert_equal(0, off, "") assert_equal(2, len, "") assert_equal("t", $bdb["red"], "") assert_equal("se", $bdb["green"], "") assert_equal(nil, $bdb["blue"], "") pon, off, len = $bdb.partial_clear assert(pon, "") assert_equal(3, off, "") assert_equal(2, len, "") assert_equal("boat", $bdb["red"], "") assert_equal("house", $bdb["green"], "") assert_equal("sea", $bdb["blue"], "") end def test_10_partial_set $bdb.set_partial(0, 2) assert_equal("", $bdb["red"] = "", "") assert_equal("AB", $bdb["green"] = "AB", "") assert_equal("XYZ", $bdb["blue"] = "XYZ", "") assert_equal("KLM", $bdb["yellow"] = "KLM", "") pon, off, len = $bdb.clear_partial assert(pon, "") assert_equal(0, off, "") assert_equal(2, len, "") assert_equal("at", $bdb["red"], "") assert_equal("ABuse", $bdb["green"], "") assert_equal("XYZa", $bdb["blue"], "") assert_equal("KLM", $bdb["yellow"], "") pon, off, len = $bdb.set_partial(3, 2) assert(!pon, "") assert_equal(0, off, "") assert_equal(0, len, "") assert_equal("PPP", $bdb["red"] = "PPP", "") assert_equal("Q", $bdb["green"] = "Q", "") assert_equal("XYZ", $bdb["blue"] = "XYZ", "") assert_equal("TU", $bdb["yellow"] = "TU", "") pon, off, len = $bdb.clear_partial assert(pon, "") assert_equal(3, off, "") assert_equal(2, len, "") assert_equal("at\0PPP", $bdb["red"], "") assert_equal("ABuQ", $bdb["green"], "") assert_equal("XYZXYZ", $bdb["blue"], "") assert_equal("KLMTU", $bdb["yellow"], "") end def test_11_unknown $bdb.close $bdb = nil assert_kind_of(BDB::Hash, unknown = BDB::Unknown.open("tmp/aa", nil, "r"), "") unknown.close end def test_12_env clean assert_kind_of(BDB::Env, $env = BDB::Env.open("tmp", BDB::CREATE|BDB::INIT_TRANSACTION)) assert_kind_of(BDB::Hash, $bdb = BDB::Hash.open("aa", nil, "a", "env" => $env), "") end def test_13_txn_commit assert_kind_of(BDB::Txn, txn = $env.begin, "") assert_kind_of(BDB::Hash, db = txn.assoc($bdb), "") assert_equal(true, db.txn?, "") assert_equal(txn, db.txn, "") assert_equal(true, db.env?, "") assert_equal($env, db.env, "") assert_equal("aa", db["aa"] = "aa", "") assert_equal("bb", db["bb"] = "bb", "") assert_equal("cc", db["cc"] = "cc", "") assert_equal(3, db.size, "") assert(txn.commit, "") assert_equal(3, $bdb.size, "") end def test_14_txn_abort assert_kind_of(BDB::Txn, txn = $env.begin, "") assert_kind_of(BDB::Hash, db = txn.assoc($bdb), "") assert_equal("aa", db["aa1"] = "aa", "") assert_equal("bb", db["bb1"] = "bb", "") assert_equal("cc", db["cc1"] = "cc", "") assert_equal(6, db.size, "") assert(txn.abort, "") assert_equal(3, $bdb.size, "") end def test_15_txn_abort2 if BDB::VERSION_MAJOR == 2 && BDB::VERSION_MINOR < 7 $stderr.print "skipping test for this version" return "pass" end $env.begin($bdb) do |txn, db| db["aa1"] = "aa" db["bb1"] = "bb" assert_equal(5, db.size, "") txn.begin(db) do |txn1, db1| db1["cc1"] = "cc" assert_equal(6, db1.size, "") txn.abort assert_fail("") end assert_fail("") end assert_equal(3, $bdb.size, "") end def test_16_txn_commit2 if BDB::VERSION_MAJOR == 2 && BDB::VERSION_MINOR < 7 $stderr.print "skipping test for this version" return "pass" end $env.begin($bdb) do |txn, db| db["aa1"] = "aa" db["bb1"] = "bb" assert_equal(5, db.size, "") txn.begin(db) do |txn1, db1| db1["cc1"] = "cc" assert_equal(6, db1.size, "") txn.commit assert_fail("") end assert_fail("") end assert_equal(6, $bdb.size, "") end def intern_hash_delete $hash = {} File.foreach("examples/wordtest") do |line| line.chomp! $hash[line] = line.reverse $bdb[line] = line.reverse end $bdb.each do |k, v| assert_equal($hash[k], v, "") end $bdb.delete_if {|k, v| k[0] == ?a} $hash.delete_if {|k, v| k[0] == ?a} assert_equal($bdb.size, $hash.size, "") $bdb.each do |k, v| assert_equal($hash[k], v, "") end end def test_17_hash_delete assert_equal(true, $bdb.env?, "") assert_equal($env, $bdb.env, "") assert_equal(nil, $bdb.close, "") $env.close clean assert_kind_of(BDB::HashRuby, $bdb = BDB::HashRuby.open("tmp/aa", nil, "w", "set_pagesize" => 1024, "set_cachesize" => [0, 32 * 1024, 0]), "") assert_equal(false, $bdb.env?, "") assert_equal(nil, $bdb.env, "") intern_hash_delete $bdb.close end def test_18_hash_delete assert_kind_of(BDB::Hash, $bdb = BDB::Hash.open("tmp/aa", nil, "w", "set_h_hash" => proc {|a| a.hash }, "set_pagesize" => 1024, "set_cachesize" => [0, 32 * 1024, 0])) intern_hash_delete end def test_18_index lines = $hash.keys array = [] 10.times do h = lines[rand(lines.size - 1)] array.push h assert_equal($hash.index(h.reverse), $bdb.index(h.reverse), "") end assert_equal($hash.indexes(*array), $bdb.indexes(*array), "") array.each do |k| assert($bdb.has_both?(k, k.reverse), "") end end def test_19_convert h = $bdb.to_hash h.each do |k, v| assert_equal(v, $hash[k], "") end $hash.each do |k, v| assert_equal(v, h[k], "") end h1 = $hash.to_a h2 = $bdb.to_a assert_equal(h1.size, h2.size, "") h1.each do |k| assert(h2.include?(k), "") end end if BDB::VERSION_MAJOR == 3 && BDB::VERSION_MINOR >= 3 def test_20_blurb $bdb.each(nil, 10) do |k, v| assert_equal($hash[k], v, "") end $bdb.each_key(nil, 10) do |k| assert($hash.key?(k), "") end $hash.each_key do |k| assert(!!$bdb.key?(k), "") end end end def test_21_sh val = 'a' .. 'zz' assert_equal(nil, $bdb.close, "") File::unlink('tmp/aa') if FileTest.file?('tmp/aa') assert_kind_of(BDB::Hash, $bdb = BDB::AZ.open("tmp/aa", nil, "w"), "") val.each do |l| assert_equal(l, $bdb[l] = l, "") end $bdb.each do |k, v| assert_equal(k, v, "") end assert_equal(nil, $bdb.close, "") assert_kind_of(BDB::Hash, $bdb = BDB::Hash.open("tmp/aa"), "") val.each do |l| assert_equal("yy_#{l}", $bdb["xx_#{l}"], "") end $bdb.each do |k, v| assert_equal("xx_", k[0, 3], "") assert_equal("yy_", v[0, 3], "") end assert_equal(nil, $bdb.close, "") clean end end if defined?(RUNIT) RUNIT::CUI::TestRunner.run(TestHash.suite) end ruby-bdb-0.6.6/tests/lock.rb000066400000000000000000000157671154714021300156660ustar00rootroot00000000000000#!/usr/bin/ruby $LOAD_PATH.unshift *%w{../src src tests} require 'bdb' require 'runit_' def clean Dir.foreach('tmp') do |x| if FileTest.file?("tmp/#{x}") File.unlink("tmp/#{x}") end end end $env, $db = nil, nil $object = "OBJECT" $matrix = [ [0, 0, 0], [0, 0, 1], [0, 1, 1] ] clean print "\nVERSION of BDB is #{BDB::VERSION}\n" Inh = defined?(RUNIT) ? RUNIT : Test::Unit class TestLock < Inh::TestCase def test_01_error assert_raises(BDB::Fatal) do BDB::Env.open("tmp", BDB::CREATE | BDB::INIT_LOCK, "set_lk_conflicts" => [[0, 0, 0]]) end assert_raises(BDB::Fatal) do BDB::Env.open("tmp", BDB::CREATE | BDB::INIT_LOCK, "set_lk_conflicts" => [[0], [2]]) end =begin assert_raises(TypeError) do BDB::Env.open("tmp", BDB::CREATE | BDB::INIT_LOCK, "set_lk_max" => "a") end =end end def test_02_init assert_kind_of(BDB::Env, $env = BDB::Env.open("tmp", BDB::CREATE | BDB::INIT_LOCK, "set_lk_conflicts" => $matrix, "set_lk_max" => 1000)) end def test_03_get_put assert_kind_of(BDB::Lockid, $lockid = $env.lock) [BDB::LOCK_NG, BDB::LOCK_READ, BDB::LOCK_WRITE].each do |mode| assert_kind_of(BDB::Lock, lock = $lockid.lock_get("object #{mode}", mode)) assert_equal(nil, lock.put, "") end end def test_04_multiple $locks = [] [BDB::LOCK_NG, BDB::LOCK_READ, BDB::LOCK_WRITE].each do |mode| assert_kind_of(BDB::Lock, lock = $lockid.lock_get($object, mode)) $locks << lock end intern = [] 10.times do assert_kind_of(BDB::Lock, lock = $lockid.lock_get($object, BDB::LOCK_WRITE, true)) intern << lock end intern.each do |lock| assert_equal(nil, lock.release) end end def test_05_newlock assert_kind_of(BDB::Lockid, lockid = $env.lock) [BDB::LOCK_READ, BDB::LOCK_WRITE].each do |mode| assert_raises(BDB::LockGranted) { lockid.lock_get($object, mode, true) } end assert_equal(nil, lockid.close) end def test_06_release $locks.each do |lock| assert_equal(nil, lock.release, "") end assert_equal(nil, $lockid.close) end def test_07_renew assert_kind_of(BDB::Lockid, lockid = $env.lock) [BDB::LOCK_READ, BDB::LOCK_WRITE].each do |mode| assert_kind_of(BDB::Lock, lock = lockid.lock_get($object, mode, true)) assert_equal(nil, lock.put, "") end assert_equal(nil, lockid.close) assert_equal(nil, $env.close) end def test_08_transaction clean if BDB::VERSION_NUMBER <= 30110 puts "skipping test for this version" return end assert_kind_of(BDB::Env, $env = BDB::Env.open("tmp", BDB::CREATE | BDB::INIT_TRANSACTION)) assert_kind_of(BDB::Queue, $db = $env.open_db(BDB::Queue, "aa", nil, "a", "set_re_len" => 10)) assert_kind_of(BDB::Txn, txn1 = $env.begin("flags" => BDB::TXN_NOWAIT)) assert_kind_of(BDB::Queue, db1 = txn1.assoc($db)) assert_equal(1, inc = db1.push("record1")[0], "") assert_kind_of(BDB::Txn, txn2 = $env.begin("flags" => BDB::TXN_NOWAIT)) assert_kind_of(BDB::Queue, db2 = txn2.assoc($db)) if BDB::VERSION_MAJOR >= 4 && BDB::VERSION_MINOR >= 2 assert_raises(BDB::LockDead) { db2[inc] } else assert_raises(BDB::LockGranted) { db2[inc] } end assert_equal(true, txn1.commit, "") if BDB::VERSION_MAJOR >= 4 assert_equal(1, $env.lock_stat["st_nlocks"], "") end assert_equal(true, txn2.commit, "") if BDB::VERSION_MAJOR >= 4 assert_equal(1, $env.lock_stat["st_nlocks"], "") end end def test_forward(meth1, meth2) assert_kind_of(BDB::Txn, txn1 = $env.begin("flags" => BDB::TXN_NOWAIT)) assert_kind_of(BDB::Queue, db1 = txn1.assoc($db)) ind1, = db1.push("record1") assert_kind_of(Numeric, ind1) if BDB::VERSION_MAJOR >= 4 assert_equal(2, $env.lock_stat["st_nlocks"], "") end assert_kind_of(BDB::Txn, txn2 = $env.begin("flags" => BDB::TXN_NOWAIT)) assert_kind_of(BDB::Queue, db2 = txn2.assoc($db)) ind2, = db2.push("record2") assert_kind_of(Numeric, ind2) if BDB::VERSION_MAJOR >= 4 assert_equal(3, $env.lock_stat["st_nlocks"], "") end txn1.send(meth1) if BDB::VERSION_MAJOR >= 4 assert_equal(2, $env.lock_stat["st_nlocks"], "") end assert_equal("record2", db2[ind2], "") if meth1 == "abort" assert_equal(nil, db2[ind1], "") else assert_equal("record1", db2[ind1], "") end txn2.send(meth2) if BDB::VERSION_MAJOR >= 4 assert_equal(1, $env.lock_stat["st_nlocks"], "") end if meth1 == "commit" assert_equal("record1", $db[ind1], "") else assert_equal(nil, $db[ind1], "") end if meth2 == "commit" assert_equal("record2", $db[ind2], "") else assert_equal(nil, $db[ind2], "") end end def test_09_forward if BDB::VERSION_NUMBER <= 30114 puts "skipping test for this version" return end ["commit", "abort"].each do |t1| ["commit", "abort"].each do |t2| test_forward(t1, t2) end end end def test_reverse(meth1, meth2) assert_kind_of(BDB::Txn, txn1 = $env.begin("flags" => BDB::TXN_NOWAIT)) assert_kind_of(BDB::Queue, db1 = txn1.assoc($db)) ind1, = db1.push("record1") assert_kind_of(Numeric, ind1) if BDB::VERSION_MAJOR >= 4 assert_equal(2, $env.lock_stat["st_nlocks"], "") end assert_kind_of(BDB::Txn, txn2 = $env.begin("flags" => BDB::TXN_NOWAIT)) assert_kind_of(BDB::Queue, db2 = txn2.assoc($db)) ind2, = db2.push("record2") assert_kind_of(Numeric, ind2) if BDB::VERSION_MAJOR >= 4 assert_equal(3, $env.lock_stat["st_nlocks"], "") end txn2.send(meth2) if BDB::VERSION_MAJOR >= 4 assert_equal(2, $env.lock_stat["st_nlocks"], "") end assert_equal("record1", db1[ind1], "") if meth2 == "abort" assert_equal(nil, db1[ind2], "") else assert_equal("record2", db1[ind2], "") end txn1.send(meth1) if BDB::VERSION_MAJOR >= 4 assert_equal(1, $env.lock_stat["st_nlocks"], "") end if meth1 == "commit" assert_equal("record1", $db[ind1], "") else assert_equal(nil, $db[ind1], "") end if meth2 == "commit" assert_equal("record2", $db[ind2], "") else assert_equal(nil, $db[ind2], "") end end def test_10_reverse if BDB::VERSION_NUMBER <= 30114 puts "skipping test for this version" return end ["commit", "abort"].each do |t1| ["commit", "abort"].each do |t2| test_reverse(t1, t2) end end end end if defined?(RUNIT) RUNIT::CUI::TestRunner.run(TestLog.suite) end ruby-bdb-0.6.6/tests/log.rb000077500000000000000000000062771154714021300155160ustar00rootroot00000000000000#!/usr/bin/ruby $LOAD_PATH.unshift *%w{../src src tests} require 'bdb' require 'runit_' def clean Dir.foreach('tmp') do |x| if FileTest.file?("tmp/#{x}") File.unlink("tmp/#{x}") end end end $env = nil clean print "\nVERSION of BDB is #{BDB::VERSION}\n" Inh = defined?(RUNIT) ? RUNIT : Test::Unit class TestLog < Inh::TestCase def test_01_init assert_kind_of(BDB::Env, $env = BDB::Env.open("tmp", BDB::CREATE | BDB::INIT_LOG, "thread" => false) , "") end def test_02_push $lsn = [] 100.times do |i| assert_kind_of(BDB::Lsn, lsn = $env.log_put("test #{i}"), "") $lsn.push lsn end assert_equal($env, $env.log_flush, "") assert_equal(100, $lsn.size, "lsn size") assert_equal($env, $lsn[0].env, "") log = Dir["tmp/log*"][0].sub(/\Atmp./,'') assert_equal([log], $env.log_archive(BDB::ARCH_LOG), "") assert_equal("tmp/#{log}", $lsn[0].file, "") assert_equal($lsn[0], $lsn[0].flush, "") end def test_03_each i = 0 $env.log_each do |r, l| assert_equal($lsn[i], l, "lsn ==") assert_equal("test #{i}", r, "value ==") i += 1 end assert_equal(100, i, "") end def test_04_reverse_each i = 99 $env.log_reverse_each do |r, l| assert_equal($lsn[i], l, "lsn == reverse") assert_equal("test #{i}", r, "value == reverse") i -= 1 end assert_equal(-1, i, "") end def test_05_each if $lsn[0].respond_to?(:each) i = 24 $lsn[24].log_each do |r, l| assert_equal($lsn[i], l, "lsn ==") assert_equal("test #{i}", r, "value ==") i += 1 end assert_equal(100, i, "") end end def test_06_reverse_each if $lsn[0].respond_to?(:reverse_each) i = 55 $lsn[55].log_reverse_each do |r, l| assert_equal($lsn[i], l, "lsn == reverse") assert_equal("test #{i}", r, "value == reverse") i -= 1 end assert_equal(-1, i, "") end end def test_07_random begin 1000.times do nb = rand($lsn.size) assert_equal("test #{nb}", $lsn[nb].log_get, "") end ensure $env.close end end def test_08_reinit clean assert_kind_of(BDB::Env, $env = BDB::Env.open("tmp", BDB::CREATE | BDB::INIT_LOG | BDB::INIT_TXN, "thread" => false, :set_lg_bsize => 10000, "set_lg_max" => 45000), "") end def test_09_put $lsn = [] $rec = [] 500.times do |i| assert_kind_of(BDB::Lsn, j = $env.log_put("init %d" % i), "") if (i % 25) == 0 $rec.push "init %d" % i $lsn.push j end end end def test_10_log_get l = nil $lsn.each_with_index do |ls, i| if l assert(ls > l, "") end assert_equal(ls.log_get, $rec[i], "") l = ls end end def test_11_file if BDB::VERSION_MAJOR < 4 log_file = Dir.glob("tmp/*") $lsn.each do |ls| assert(log_file.include?(ls.log_file), "") end end end def test_12_end $env.close clean end end if defined?(RUNIT) RUNIT::CUI::TestRunner.run(TestLog.suite) end ruby-bdb-0.6.6/tests/marshal.rb000066400000000000000000000253251154714021300163540ustar00rootroot00000000000000#!/usr/bin/ruby $LOAD_PATH.unshift *%w{../src src tests} require 'bdb' require 'runit_' def clean Dir.foreach('tmp') do |x| if FileTest.file?("tmp/#{x}") File.unlink("tmp/#{x}") end end end module BDB class AZ < Btree def bdb_store_key(a) "xx_" + a end def bdb_fetch_key(a) a.sub(/^xx_/, '') end def bdb_store_value(a) "yy_" + a end def bdb_fetch_value(a) a.sub(/^yy_/, '') end end end $bdb, $env = nil, nil clean print "\nVERSION of BDB is #{BDB::VERSION}\n" Inh = defined?(RUNIT) ? RUNIT : Test::Unit class TestBtree < Inh::TestCase def test_00_error assert_raises(BDB::Fatal, "invalid name") do BDB::Btree.new(".", nil, "a") end assert_raises(BDB::Fatal, "invalid Env") do BDB::Btree.open("tmp/aa", nil, "env" => 1) end end def test_01_init assert_kind_of(BDB::Btree, $bdb = BDB::Btree.new("tmp/aa", nil, "a", "marshal" => Marshal), "") end def test_02_get_set assert_equal([12, "alpha"], $bdb["alpha"] = [12, "alpha"], "") assert_equal([12, "alpha"], $bdb["alpha"].to_orig, "") assert_equal(nil, $bdb["gamma"] = nil, "") assert_equal(nil, $bdb["gamma"].to_orig, "") assert($bdb.key?("alpha"), "") assert_equal(false, $bdb.key?("unknown"), "") assert($bdb.value?(nil), "") assert($bdb.value?([12, "alpha"]), "") assert_equal(false, $bdb.value?("unknown"), "") assert_equal(false, $bdb.put("alpha", "gamma", BDB::NOOVERWRITE), "") assert_equal([12, "alpha"], $bdb["alpha"].to_orig, "") assert($bdb.both?("alpha", [12, "alpha"]), "") assert_equal(["alpha", [12, "alpha"]], $bdb.get("alpha", [12, "alpha"], BDB::GET_BOTH), "") assert(! $bdb.both?("alpha", "beta"), "") assert(! $bdb.get("alpha", "beta", BDB::GET_BOTH), "") assert(! $bdb.both?("unknown", "alpha"), "") assert_equal([1, 2, [3, 4]], $bdb["array"] = [1, 2, [3, 4]], "") assert_equal([1, 2, [3, 4]], $bdb["array"].to_orig, "") assert_equal({"a" => "b"}, $bdb["hash"] = {"a" => "b"}, "") assert_equal({"a" => "b"}, $bdb["hash"].to_orig, "") assert($bdb.sync, "") end def test_03_delete size = $bdb.size i = 0 $bdb.each do |key, value| assert_equal($bdb, $bdb.delete(key), "") i += 1 end assert(size == i, "") assert_equal(0, $bdb.size, "") end def test_04_cursor cat = Struct.new("Cat", :name, :age, :life) array = ["abc", [1, 3], {"aa" => 12}, [2, {"bb" => "cc"}, 4], cat.new("cat", 15, 7)] array.each do |x| assert_equal(x, $bdb[x] = x, "") end assert(array.size == $bdb.size, "") $bdb.each_value do |x| assert(array.index(x) != nil) end $bdb.reverse_each_value do |x| assert(array.index(x) != nil) end end def test_05_reopen assert_equal(nil, $bdb.close, "") assert_kind_of(BDB::Btree, $bdb = BDB::Btree.open("tmp/aa", nil, "w", "set_flags" => BDB::DUP, "marshal" => Marshal), "") assert_equal(0, $bdb.size, "") end def test_06_dup array = [[[0, "a"], [1, "b"], [2, "c"], [3, "d"]], [{"aa" => 0}, {"bb" => 1}, {"cc" => 2}], [["aaa", 12], [12, "bbb"]], ["aaaa"]] ind = 0 array.each do |arr| arr.each do |i| assert_equal(i, $bdb[ind.to_s] = i, "") end ind += 1 end if BDB::VERSION_MAJOR > 2 || BDB::VERSION_MINOR >= 6 assert_equal(4, $bdb.count("0"), "") assert_equal(3, $bdb.count("1"), "") assert_equal(2, $bdb.count("2"), "") assert_equal(1, $bdb.count("3"), "") assert_equal(0, $bdb.count("4"), "") array.size.times do |i| $bdb.get_dup(i.to_s) do |val| assert(array[i].index(val) != nil) end end assert_equal([], $bdb.get_dup("4"), "") end end def test_07_in_memory assert_equal(nil, $bdb.close, "") assert_kind_of(BDB::Btree, $bdb = BDB::Btree.open("marshal" => Marshal), "") assert_equal(0, $bdb.size, "") end def test_08_in_memory_get_set assert_equal([1, 2, [3, 4]], $bdb["array"] = [1, 2, [3, 4]], "") assert_equal([1, 2, [3, 4]], $bdb["array"].to_orig, "") assert_equal({"a" => "b"}, $bdb["hash"] = {"a" => "b"}, "") assert_equal({"a" => "b"}, $bdb["hash"].to_orig, "") assert_equal("cc", $bdb["bb"] = "cc", "") assert_equal("cc", $bdb["bb"].to_orig, "") assert_equal(nil, $bdb.close, "") end def test_09_modify assert_kind_of(BDB::Btree, $bdb = BDB::Btree.open("tmp/aa", nil, "w", "marshal" => Marshal), "") array = [1, "a", {"a" => 12}] assert_equal(array, $bdb["a"] = array, "") arr = $bdb["a"] arr.push [1, 2]; array.push [1, 2] assert_equal(array, $bdb["a"].to_orig, "") $bdb["a"][-1] = 4; array[-1] = 4 assert_equal(array, $bdb["a"].to_orig, "") $bdb["a"][-1] = ["abc", 4]; array[-1] = ["abc", 4] assert_equal(array, $bdb["a"].to_orig, "") assert_equal(nil, $bdb.close, "") clean end def test_10_recnum assert_kind_of(BDB::Btree, $bdb = BDB::Btree.open("tmp/aa", nil, "w", "set_flags" => BDB::RECNUM, "marshal" => Marshal), "") assert_equal(0, $bdb.size, "") arr = ["A 0", "B 1", "C 2", "D 3", "E 4", "F 5", "G 6"] i = 0 arr.each do |x| x = x.split assert_equal(x, $bdb[i] = x, "") i += 1; end i = 0 $bdb.each_value do |x| assert_equal(arr[i].split, x, "") i += 1 end $bdb.delete(3); assert_equal(arr.size - 1, $bdb.size, "") assert_equal(nil, $bdb[3], "") end def test_11_unknown $bdb.close $bdb = nil assert_kind_of(BDB::Btree, unknown = BDB::Unknown.open("tmp/aa", nil, "r", "marshal" => Marshal), "") unknown.close end def test_12_env clean assert_kind_of(BDB::Env, $env = BDB::Env.open("tmp", BDB::CREATE|BDB::INIT_TRANSACTION)) assert_kind_of(BDB::Btree, $bdb = BDB::Btree.open("aa", nil, "a", "env" => $env, "marshal" => Marshal), "") end def test_13_txn_commit assert_kind_of(BDB::Txn, txn = $env.begin, "") assert_kind_of(BDB::Btree, db = txn.assoc($bdb), "") assert_equal(["a", "b"], db["aa"] = ["a", "b"], "") assert_equal({"bb" => "cc"}, db["bb"] = {"bb" => "cc"}, "") assert_equal("cc", db["cc"] = "cc", "") db["aa"][0] = "e" db["aa"][1] = "f" assert_equal(["e", "f"], db["aa"].to_orig, ""); db["bb"]["bb"] = "dd" db["bb"]["cc"] = "ee" assert_equal({"bb" => "dd", "cc" => "ee"}, db["bb"].to_orig, ""); assert_equal(3, db.size, "") assert(txn.commit, "") assert_equal(3, $bdb.size, "") assert_equal(["e", "f"], $bdb["aa"].to_orig, ""); assert_equal({"bb" => "dd", "cc" => "ee"}, $bdb["bb"].to_orig, ""); end def test_14_txn_abort assert_kind_of(BDB::Txn, txn = $env.begin, "") assert_kind_of(BDB::Btree, db = txn.assoc($bdb), "") assert_equal("aa", db["aa1"] = "aa", "") assert_equal("bb", db["bb1"] = "bb", "") assert_equal("cc", db["cc1"] = "cc", "") db["aa"].push [1, 2] assert_equal(["e", "f", [1, 2]], db["aa"].to_orig, ""); db["bb"]["dd"] = [3, 4] assert_equal({"bb" => "dd", "cc" => "ee", "dd" => [3, 4]}, db["bb"].to_orig, ""); assert_equal(6, db.size, "") assert(txn.abort, "") assert_equal(["e", "f"], $bdb["aa"].to_orig, ""); assert_equal({"bb" => "dd", "cc" => "ee"}, $bdb["bb"].to_orig, ""); assert_equal(3, $bdb.size, "") end def test_15_txn_abort2 if BDB::VERSION_MAJOR == 2 && BDB::VERSION_MINOR < 7 $stderr.print "skipping test for this version" return "pass" end $env.begin($bdb) do |txn, db| db["aa1"] = "aa" db["bb1"] = "bb" assert_equal(5, db.size, "") txn.begin(db) do |txn1, db1| db1["cc1"] = "cc" db1["aa"].push({"a" => "c"}) assert_equal(["e", "f", {"a" => "c"}], db["aa"].to_orig, ""); assert_equal(6, db1.size, "") txn.abort assert_fail("") end assert_fail("") end assert_equal(["e", "f"], $bdb["aa"].to_orig, ""); assert_equal(3, $bdb.size, "") end def test_16_txn_commit2 if BDB::VERSION_MAJOR == 2 && BDB::VERSION_MINOR < 7 $stderr.print "skipping test for this version" return "pass" end $env.begin($bdb) do |txn, db| db["aa1"] = "aa" db["bb1"] = "bb" assert_equal(5, db.size, "") txn.begin(db) do |txn1, db1| db1["cc1"] = "cc" db1["aa"].push({"a" => "c"}) res = db["aa"].to_orig assert_equal(["e", "f", {"a" => "c"}], res, ""); assert_equal(6, db1.size, "") txn.commit assert_fail("") end assert_fail("") end res = $bdb["aa"].to_orig assert_equal(["e", "f", {"a" => "c"}], res, ""); assert_equal(6, $bdb.size, "") end def test_17_sh val = 'a' .. 'zz' assert_equal(nil, $bdb.close, "") $bdb = BDB::AZ.open("tmp/aa", nil, "w") assert_kind_of(BDB::Btree, $bdb, "") val.each do |l| $bdb[l] = l end $bdb.each do |k, v| assert_equal(k, v, "") end assert_equal(nil, $bdb.close, "") assert_kind_of(BDB::Btree, $bdb = BDB::Btree.open("tmp/aa"), "") val.each do |l| assert_equal("yy_#{l}", $bdb["xx_#{l}"], "") end $bdb.each do |k, v| assert_equal("xx_", k[0, 3], "") assert_equal("yy_", v[0, 3], "") end assert_equal(nil, $bdb.close, "") clean end end if defined?(RUNIT) RUNIT::CUI::TestRunner.run(TestBtree.suite) end ruby-bdb-0.6.6/tests/queue.rb000077500000000000000000000221031154714021300160430ustar00rootroot00000000000000#!/usr/bin/ruby $LOAD_PATH.unshift *%w{../src src tests} require 'bdb' print "\nVERSION of BDB is #{BDB::VERSION}\n" if BDB::VERSION_MAJOR < 3 print "\t\tno test for this version\n" exit end require 'runit_' def clean Dir.foreach('tmp') do |x| if FileTest.file?("tmp/#{x}") File.unlink("tmp/#{x}") end end end $bdb, $env = nil, nil clean Inh = defined?(RUNIT) ? RUNIT : Test::Unit class TestQueue < Inh::TestCase def test_00_error assert_raises(BDB::Fatal, "invalid name") do BDB::Queue.open("tmp/aa", nil, "env" => 1) end assert_raises(BDB::Fatal, "invalid name") do BDB::Queue.open("tmp/aa", nil, "env" => 1) end end def test_01_init assert_kind_of(BDB::Queue, $bdb = BDB::Queue.new("tmp/aa", nil, "a"), "") end def test_02_get_set assert_equal("alpha", $bdb[1] = "alpha", "") assert_equal("alpha", $bdb[1], "") assert_equal(nil, $bdb[2] = nil, "") assert_equal(nil, $bdb[2], "") assert($bdb.key?(1), "") assert_equal(false, $bdb.key?(3), "") assert($bdb.value?("alpha"), "") assert_equal(false, $bdb.value?("unknown"), "") assert_equal(false, $bdb.put(1, "gamma", BDB::NOOVERWRITE), "") assert_equal("alpha", $bdb[1], "") # assert($bdb.both?(1, "alpha"), "") assert(! $bdb.both?(1, "beta"), "") assert(! $bdb.both?(3, "alpha"), "") assert_equal([1, 2, 3], $bdb[4] = [1, 2, 3], "") assert_equal([1, 2, 3].to_s, $bdb[4], "") assert_equal({"a" => "b"}, $bdb[5] = {"a" => "b"}, "") assert_equal({"a" => "b"}.to_s, $bdb[5], "") assert($bdb.sync, "") end def test_03_delete size = $bdb.size i = 0 $bdb.each do |key, value| assert_equal($bdb, $bdb.delete(key), "") i += 1 end assert(size == i, "") assert_equal(0, $bdb.size, "") end def test_04_cursor array = ["a", "b", "c", "d", "e", "f", "g", "h", "i"] i = 1 array.each do |x| assert_equal(x, $bdb[i] = x, "") i += 1 end assert(array.size == $bdb.size, "") arr = [] $bdb.each_value do |x| arr << x end assert_equal(array, arr.sort, "") arr = [] $bdb.reverse_each_value do |x| arr << x end assert_equal(array, arr.sort, "") end def test_05_reopen assert_equal(nil, $bdb.close, "") assert_kind_of(BDB::Queue, $bdb = BDB::Queue.open("tmp/aa", nil, "w", "set_array_base" => 0), "") assert_equal(0, $bdb.size, "") end def test_06_push assert_equal(nil, $bdb.close, "") assert_kind_of(BDB::Queue, $bdb = BDB::Queue.open("tmp/aa", nil, "w", "set_array_base" => 0), "") assert_kind_of(Array, $bdb.push("a"), "") assert_equal($bdb, $bdb << "b", "") assert_equal(2, $bdb.size, "") assert_equal("a", $bdb[0], "<[0]>") assert_equal("b", $bdb[1], "<[1]>") assert_equal([0, "a"], $bdb.shift, "") assert_equal([1, "b"], $bdb.shift, "") assert_equal(0, $bdb.size, "") end def test_07_in_memory assert_equal(nil, $bdb.close, "") assert_kind_of(BDB::Queue, $bdb = BDB::Queue.open(nil, nil), "") assert_equal(0, $bdb.size, "") end def test_08_in_memory_get_set assert_equal("aa", $bdb[1] = "aa", "") assert_equal("cc", $bdb[1] = "cc", "") assert_equal("cc", $bdb[1], "") assert_equal(nil, $bdb.close, "") end def test_09_partial_get assert_kind_of(BDB::Queue, $bdb = BDB::Queue.open("tmp/aa", nil, "w"), "") { 2 => "boat", 6 => "house", 12 => "sea", }.each do |x, y| assert_equal(y, $bdb[x] = y, "") end pon, off, len = $bdb.set_partial(0, 2) assert_equal(false, pon, "") assert_equal(0, off, "") assert_equal(0, len, "") assert_equal("bo", $bdb[2], "") assert_equal("ho", $bdb[6], "") assert_equal("se", $bdb[12], "") pon, off, len = $bdb.set_partial(3, 2) assert(pon, "") assert_equal(0, off, "") assert_equal(2, len, "") assert_equal("t", $bdb[2], "") assert_equal("se", $bdb[6], "") assert_equal(nil, $bdb[12], "") pon, off, len = $bdb.partial_clear assert(pon, "") assert_equal(3, off, "") assert_equal(2, len, "") assert_equal("boat", $bdb[2], "") assert_equal("house", $bdb[6], "") assert_equal("sea", $bdb[12], "") end def test_10_partial_set $bdb.set_partial(0, 2) assert_equal(" ", $bdb[2] = " ", "") assert_equal("AB", $bdb[6] = "AB", "") assert_equal("XY", $bdb[12] = "XY", "") assert_equal("KL", $bdb[10] = "KL", "") pon, off, len = $bdb.clear_partial assert(pon, "") assert_equal(0, off, "") assert_equal(2, len, "") assert_equal(" at", $bdb[2], "") assert_equal("ABuse", $bdb[6], "") assert_equal("XYa", $bdb[12], "") assert_equal("KL", $bdb[10], "") pon, off, len = $bdb.set_partial(3, 2) assert(!pon, "") assert_equal(0, off, "") assert_equal(0, len, "") assert_equal("PP", $bdb[2] = "PP", "") assert_equal("Q ", $bdb[6] = "Q ", "") assert_equal("XY", $bdb[12] = "XY", "") assert_equal("TU", $bdb[10] = "TU", "") pon, off, len = $bdb.clear_partial assert(pon, "") assert_equal(3, off, "") assert_equal(2, len, "") assert_equal(" aPP", $bdb[2], "") assert_equal("ABuQ", $bdb[6], "") assert_equal("XYaXY", $bdb[12], "") assert_equal("KL TU", $bdb[10], "") end def test_11_unknown $bdb.close $bdb = nil assert_kind_of(BDB::Queue, unknown = BDB::Unknown.open("tmp/aa", nil, "r"), "") unknown.close end def test_12_env Dir.foreach('tmp') do |x| if FileTest.file?("tmp/#{x}") File.unlink("tmp/#{x}") end end assert_kind_of(BDB::Env, $env = BDB::Env.open("tmp", BDB::CREATE|BDB::INIT_TRANSACTION)) assert_kind_of(BDB::Queue, $bdb = BDB::Queue.open("aa", nil, "a", "env" => $env), "") end def test_13_txn_commit assert_kind_of(BDB::Txn, txn = $env.begin, "") assert_kind_of(BDB::Queue, db = txn.assoc($bdb), "") assert_equal("aa", db[1] = "aa", "") assert_equal("bb", db[2] = "bb", "") assert_equal("cc", db[3] = "cc", "") assert_equal(3, db.size, "") assert(txn.commit, "") assert_equal(3, $bdb.size, "") end def test_14_txn_abort assert_kind_of(BDB::Txn, txn = $env.begin, "") assert_kind_of(BDB::Queue, db = txn.assoc($bdb), "") assert_equal("aa", db[4] = "aa", "") assert_equal("bb", db[5] = "bb", "") assert_equal("cc", db[6] = "cc", "") assert_equal(6, db.size, "") assert(txn.abort, "") assert_equal(3, $bdb.size, "") end def test_15_txn_abort2 if BDB::VERSION_MAJOR == 2 && BDB::VERSION_MINOR < 7 $stderr.print "skipping test for this version" return "pass" end $env.begin($bdb) do |txn, db| db[4] = "aa" db[5] = "bb" assert_equal(5, db.size, "") txn.begin(db) do |txn1, db1| db1[6] = "cc" assert_equal(6, db1.size, "") txn.abort assert_fail("") end assert_fail("") end assert_equal(3, $bdb.size, "") end def test_16_txn_commit2 if BDB::VERSION_MAJOR == 2 && BDB::VERSION_MINOR < 7 $stderr.print "skipping test for this version" return "pass" end $env.begin($bdb) do |txn, db| db[4] = "aa" db[5] = "bb" assert_equal(5, db.size, "") txn.begin(db) do |txn1, db1| db1[6] = "cc" assert_equal(6, db1.size, "") txn.commit assert_fail("") end assert_fail("") end assert_equal(6, $bdb.size, "") end end if defined?(RUNIT) RUNIT::CUI::TestRunner.run(TestQueue.suite) end ruby-bdb-0.6.6/tests/recno.rb000077500000000000000000000326631154714021300160410ustar00rootroot00000000000000#!/usr/bin/ruby $LOAD_PATH.unshift *%w{../src src tests} require 'bdb' require 'runit_' def clean Dir.foreach('tmp') do |x| if FileTest.file?("tmp/#{x}") File.unlink("tmp/#{x}") end end end $bdb, $env = nil, nil clean print "\nVERSION of BDB is #{BDB::VERSION}\n" Inh = defined?(RUNIT) ? RUNIT : Test::Unit class TestRecno < Inh::TestCase def test_00_error assert_raises(BDB::Fatal, "invalid name") do BDB::Recno.open("tmp/aa", nil, "env" => 1) end assert_raises(BDB::Fatal, "invalid name") do BDB::Recno.open("tmp/aa", nil, "env" => 1) end end def test_01_init assert_kind_of(BDB::Recno, $bdb = BDB::Recno.new("tmp/aa", nil, "a"), "") end def test_02_get_set assert_equal("alpha", $bdb[1] = "alpha", "") assert_equal("alpha", $bdb[1], "") assert_equal(nil, $bdb[2] = nil, "") assert_equal(nil, $bdb[2], "") assert($bdb.key?(1), "") assert_equal(false, $bdb.key?(3), "") assert($bdb.value?("alpha"), "") assert_equal(false, $bdb.value?("unknown"), "") assert_equal(false, $bdb.put(1, "gamma", BDB::NOOVERWRITE), "") assert_equal("alpha", $bdb[1], "") assert($bdb.both?(1, "alpha"), "") assert(! $bdb.both?(1, "beta"), "") assert(! $bdb.both?(3, "alpha"), "") assert_equal([1, 2, 3], $bdb[4] = [1, 2, 3], "") assert_equal([1, 2, 3].to_s, $bdb[4], "") assert_equal({"a" => "b"}, $bdb[5] = {"a" => "b"}, "") assert_equal({"a" => "b"}.to_s, $bdb[5], "") assert($bdb.sync, "") end def test_03_delete size = $bdb.size i = 0 $bdb.each_index do |key| assert_equal($bdb, $bdb.delete(key), "") i += 1 end assert(size == i, "") assert_equal(0, $bdb.size, "") end def test_04_cursor array = ["a", "b", "c", "d", "e", "f", "g", "h", "i"] i = 1 array.each do |x| assert_equal(x, $bdb[i] = x, "") i += 1 end assert(array.size == $bdb.size, "") arr = [] $bdb.each_value do |x| arr << x end assert_equal(array, arr.sort, "") arr = [] $bdb.reverse_each_value do |x| arr << x end assert_equal(array, arr.sort, "") arr = [] $bdb.each_value(4) do |x| arr << x end assert_equal(array - ["a", "b", "c"], arr.sort, "") arr = [] $bdb.reverse_each_value(7) do |x| arr << x end assert_equal(array - ["h", "i"], arr.sort, "") arr = $bdb.reject {|k, v| k == 5 || v == "i" } has = array.reject {|k| k == "e" || k == "i" } assert_equal(has, arr.values.sort, "") end def test_05_reopen assert_equal(nil, $bdb.close, "") assert_kind_of(BDB::Recno, $bdb = BDB::Recno.open("tmp/aa", nil, "w", "set_flags" => BDB::RENUMBER, "set_array_base" => 0), "") assert_equal(0, $bdb.size, "") end def test_06_renumber array = ["a", "b", "c", "d", "e", "f", "g", "h", "i"] array.each_index do |x| assert_equal(array[x], $bdb[x] = array[x], "") end assert_equal($bdb, $bdb.delete(2), "") assert_equal($bdb, $bdb.delete(5), "") array.delete_at(2) array.delete_at(5) array.each_index do |x| assert_equal(array[x], $bdb[x], "") end end def test_07_in_memory assert_equal(nil, $bdb.close, "") assert_kind_of(BDB::Recno, $bdb = BDB::Recno.open(nil, nil), "") assert_equal(0, $bdb.size, "") end def test_08_in_memory_get_set assert_equal("aa", $bdb[1] = "aa", "") assert_equal("cc", $bdb[1] = "cc", "") assert_equal("cc", $bdb[1], "") assert_equal(nil, $bdb.close, "") end def test_09_partial_get assert_kind_of(BDB::Recno, $bdb = BDB::Recno.open("tmp/aa", nil, "w"), "") { 2 => "boat", 6 => "house", 12 => "sea", }.each do |x, y| assert_equal(y, $bdb[x] = y, "") end pon, off, len = $bdb.set_partial(0, 2) assert_equal(false, pon, "") assert_equal(0, off, "") assert_equal(0, len, "") assert_equal("bo", $bdb[2], "") assert_equal("ho", $bdb[6], "") assert_equal("se", $bdb[12], "") pon, off, len = $bdb.set_partial(3, 2) assert(pon, "") assert_equal(0, off, "") assert_equal(2, len, "") assert_equal("t", $bdb[2], "") assert_equal("se", $bdb[6], "") assert_equal(nil, $bdb[12], "") pon, off, len = $bdb.partial_clear assert(pon, "") assert_equal(3, off, "") assert_equal(2, len, "") assert_equal("boat", $bdb[2], "") assert_equal("house", $bdb[6], "") assert_equal("sea", $bdb[12], "") end def test_10_partial_set $bdb.set_partial(0, 2) assert_equal("", $bdb[2] = "", "") assert_equal("AB", $bdb[6] = "AB", "") assert_equal("XYZ", $bdb[12] = "XYZ", "") assert_equal("KLM", $bdb[10] = "KLM", "") pon, off, len = $bdb.clear_partial assert(pon, "") assert_equal(0, off, "") assert_equal(2, len, "") assert_equal("at", $bdb[2], "") assert_equal("ABuse", $bdb[6], "") assert_equal("XYZa", $bdb[12], "") assert_equal("KLM", $bdb[10], "") pon, off, len = $bdb.set_partial(3, 2) assert(!pon, "") assert_equal(0, off, "") assert_equal(0, len, "") assert_equal("PPP", $bdb[2] = "PPP", "") assert_equal("Q", $bdb[6] = "Q", "") assert_equal("XYZ", $bdb[12] = "XYZ", "") assert_equal("TU", $bdb[10] = "TU", "") pon, off, len = $bdb.clear_partial assert(pon, "") assert_equal(3, off, "") assert_equal(2, len, "") assert_equal("at\0PPP", $bdb[2], "") assert_equal("ABuQ", $bdb[6], "") assert_equal("XYZXYZ", $bdb[12], "") assert_equal("KLMTU", $bdb[10], "") end =begin def test_11_unknown $bdb.close $bdb = nil assert_kind_of(BDB::Recno, BDB::Unknown.open("tmp/aa", nil, "r"), "") end =end def test_12_env $bdb.close Dir.foreach('tmp') do |x| if FileTest.file?("tmp/#{x}") File.unlink("tmp/#{x}") end end assert_kind_of(BDB::Env, $env = BDB::Env.open("tmp", BDB::CREATE|BDB::INIT_TRANSACTION)) assert_kind_of(BDB::Recno, $bdb = BDB::Recno.open("aa", nil, "a", "env" => $env), "") end def test_13_txn_commit assert_kind_of(BDB::Txn, txn = $env.begin, "") assert_kind_of(BDB::Recno, db = txn.assoc($bdb), "") assert_equal("aa", db[1] = "aa", "") assert_equal("bb", db[2] = "bb", "") assert_equal("cc", db[3] = "cc", "") assert_equal(3, db.size, "") assert(txn.commit, "") assert_equal(3, $bdb.size, "") end def test_14_txn_abort assert_kind_of(BDB::Txn, txn = $env.begin, "") assert_kind_of(BDB::Recno, db = txn.assoc($bdb), "") assert_equal("aa", db[4] = "aa", "") assert_equal("bb", db[5] = "bb", "") assert_equal("cc", db[6] = "cc", "") assert_equal(6, db.size, "") assert(txn.abort, "") assert_equal(3, $bdb.size, "") end def test_15_txn_abort2 if BDB::VERSION_MAJOR == 2 && BDB::VERSION_MINOR < 7 $stderr.print "skipping test for this version" return "pass" end $env.begin($bdb) do |txn, db| db[4] = "aa" db[5] = "bb" assert_equal(5, db.size, "") txn.begin(db) do |txn1, db1| db1[6] = "cc" assert_equal(6, db1.size, "") txn.abort assert_fail("") end assert_fail("") end assert_equal(3, $bdb.size, "") end def test_16_txn_commit2 if BDB::VERSION_MAJOR == 2 && BDB::VERSION_MINOR < 7 $stderr.print "skipping test for this version" return "pass" end $env.begin($bdb) do |txn, db| db[4] = "aa" db[5] = "bb" assert_equal(5, db.size, "") txn.begin(db) do |txn1, db1| db1[6] = "cc" assert_equal(6, db1.size, "") txn.commit assert_fail("") end assert_fail("") end assert_equal(6, $bdb.size, "") end def test_17_file begin File.truncate("tmp/bb", 0) rescue f = File.open("tmp/bb", "w") ensure f.close if f end assert_kind_of(BDB::Recno, $bdb = BDB::Recno.open("tmp/aa", nil, "w", "set_array_base" => 0, "set_re_source" => "tmp/bb"), "") $bdb[0] = "abcd" $bdb[1] = "efgh" $bdb[4] = "ijkl" $bdb.close begin lines = File.readlines("tmp/bb").join rescue assert_fail("") end assert_equal("abcd\nefgh\n\n\nijkl\n", lines, "") end def test_18_file_delim File.truncate("tmp/bb", 0) assert_kind_of(BDB::Recno, $bdb = BDB::Recno.open("tmp/aa", nil, "w", "set_array_base" => 0, "set_re_source" => "tmp/bb", "set_re_delim" => "|"), "") $bdb[0] = "abcd" $bdb[1] = "efgh" $bdb[4] = "ijkl" $bdb.close begin lines = File.readlines("tmp/bb").join rescue assert_fail("") end assert_equal("abcd|efgh|||ijkl|", lines, "") end def test_19_file_len File.truncate("tmp/bb", 0) assert_kind_of(BDB::Recno, $bdb = BDB::Recno.open("tmp/aa", nil, "w", "set_array_base" => 0, "set_re_source" => "tmp/bb", "set_re_len" => 6), "") $bdb[0] = "abcd" $bdb[1] = "efg" $bdb[4] = "ij" $bdb.close begin lines = File.readlines("tmp/bb").join rescue assert_fail("") end assert_equal("abcd efg ij ", lines, "") end def test_20_file_pad File.truncate("tmp/bb", 0) assert_kind_of(BDB::Recno, $bdb = BDB::Recno.open("tmp/aa", nil, "w", "set_array_base" => 0, "set_re_source" => "tmp/bb", "set_re_pad" => "+", "set_re_len" => 6), "") $bdb[0] = "abcd" $bdb[1] = "efg" $bdb[4] = "ij" $bdb.close begin lines = File.readlines("tmp/bb").join rescue assert_fail("") end assert_equal("abcd++efg+++++++++++++++ij++++", lines, "") end def test_21_memory begin File.truncate("tmp/bb", 0) rescue f = File.open("tmp/bb", "w") ensure f.close if f end assert_kind_of(BDB::Recno, $bdb = BDB::Recno.open(nil, nil, "w", "set_array_base" => 0, "set_re_source" => "tmp/bb"), "") $bdb[0] = "abcd" $bdb[1] = "efgh" $bdb[4] = "ijkl" $bdb.close begin lines = File.readlines("tmp/bb").join rescue assert_fail("") end assert_equal("abcd\nefgh\n\n\nijkl\n", lines, "") end def test_22_memory_delim File.truncate("tmp/bb", 0) assert_kind_of(BDB::Recno, $bdb = BDB::Recno.open(nil, nil, "w", "set_array_base" => 0, "set_re_source" => "tmp/bb", "set_re_delim" => "|"), "") $bdb[0] = "abcd" $bdb[1] = "efgh" $bdb[4] = "ijkl" $bdb.close begin lines = File.readlines("tmp/bb").join rescue assert_fail("") end assert_equal("abcd|efgh|||ijkl|", lines, "") end def test_23_memory_len File.truncate("tmp/bb", 0) assert_kind_of(BDB::Recno, $bdb = BDB::Recno.open(nil, nil, "w", "set_array_base" => 0, "set_re_source" => "tmp/bb", "set_re_len" => 6), "") $bdb[0] = "abcd" $bdb[1] = "efg" $bdb[4] = "ij" $bdb.close begin lines = File.readlines("tmp/bb").join rescue assert_fail("") end assert_equal("abcd efg ij ", lines, "") end def test_24_memory_pad File.truncate("tmp/bb", 0) assert_kind_of(BDB::Recno, $bdb = BDB::Recno.open(nil, nil, "w", "set_array_base" => 0, "set_re_source" => "tmp/bb", "set_re_pad" => "+", "set_re_len" => 6), "") $bdb[0] = "abcd" $bdb[1] = "efg" $bdb[4] = "ij" $bdb.close begin lines = File.readlines("tmp/bb").join rescue assert_fail("") end assert_equal("abcd++efg+++++++++++++++ij++++", lines, "") end end if defined?(RUNIT) RUNIT::CUI::TestRunner.run(TestRecno.suite) end ruby-bdb-0.6.6/tests/recnum.rb000066400000000000000000000302601154714021300162100ustar00rootroot00000000000000#!/usr/bin/ruby $LOAD_PATH.unshift(*%w{../src src tests}) require 'bdb' require 'runit_' def clean Dir.foreach('tmp') do |x| if FileTest.file?("tmp/#{x}") File.unlink("tmp/#{x}") end end end def reinject(i) (1 .. i).each do |i| $array.push i.to_s $bdb.push i end end $bdb, $env = nil, nil clean print "\nVERSION of BDB is #{BDB::VERSION}\n" Inh = defined?(RUNIT) ? RUNIT : Test::Unit class TestRecnum < Inh::TestCase def test_00_error assert_raises(BDB::Fatal, "invalid name") do BDB::Recnum.open("tmp/aa", nil, "env" => 1) end assert_raises(BDB::Fatal, "invalid name") do BDB::Recnum.open("tmp/aa", nil, "env" => 1) end end def test_01_init assert_kind_of(BDB::Recnum, $bdb = BDB::Recnum.new("tmp/aa", nil, "w"), "") $array = [] end def test_02_get_set reinject(99) $bdb.each_index do |i| assert_equal($bdb[i], $array[i], "") end -1.downto(-99) do |i| assert_equal($bdb[i], $array[i], "") end 200.times do i = rand($array.size) assert_equal($bdb[i], $array[i], "") end end def test_03_subseq assert_equal($bdb[-1], $array[-1], "") assert_equal($bdb[2 .. 7], $array[2 .. 7], "") $bdb[2 .. 7] = "a", "b" $array[2 .. 7] = "a", "b" assert_equal($bdb.size, $array.size, "") assert_equal($bdb.to_a, $array, "") $bdb[3 .. 6] = "a", "b", "c", "d", "e", "g", "h", "i" $array[3 .. 6] = "a", "b", "c", "d", "e", "g", "h", "i" assert_equal($bdb.size, $array.size, "") assert_equal($bdb.to_a, $array, "") end def test_04_op assert_equal($bdb + ["3", "4"], $array + ["3", "4"], "") assert_equal(["3", "4"] + $bdb, ["3", "4"] + $array, "") assert_equal($bdb - ["3", "4"], $array - ["3", "4"], "") assert_equal(["3", "4"] - $bdb, ["3", "4"] - $array, "") assert_equal($bdb * 2, $array * 2, "") assert_equal($bdb * ":", $array * ":", "") assert_equal($bdb * "", $array * "", "") assert_equal($bdb.size, $array.size, "") end def test_05_at assert_equal($bdb.to_a, $array, "") assert_equal($bdb.at(0), $array.at(0), "") assert_equal($bdb.at(10), $array.at(10), "") assert_equal($bdb.at(99), $array.at(99), "") assert_equal($bdb.at(205), $array.at(205), "") assert_equal($bdb.at(-1), $array.at(-1), "") assert_equal($bdb.at(-100), $array.at(-100), "") assert_equal($bdb.at(205), $array.at(205), "") end def test_06_slice assert_equal($bdb.to_a, $array, "") 100.times do i = rand($bdb.size) assert_equal($bdb.slice(i), $array.slice(i), "") end 100.times do i = rand($bdb.size) assert_equal($bdb.slice(-i), $array.slice(-i), "") end 100.times do i = rand($bdb.size) j = rand($bdb.size) assert_equal($bdb.slice(i, j), $array.slice(i, j), "") end 100.times do i = rand($bdb.size) j = rand($bdb.size) assert_equal($bdb.slice(-i, j), $array.slice(-i, j), "") end 100.times do i = rand($bdb.size) j = rand($bdb.size) assert_equal($bdb.slice(i .. j), $array.slice(i .. j), "") end 100.times do i = rand($bdb.size) j = rand($bdb.size) assert_equal($bdb.slice(-i, j), $array.slice(-i, j), "") end end def test_06_slice_bang assert_equal($bdb.to_a, $array, "") 10.times do |iter| i = rand($bdb.size) assert_equal($bdb.slice!(i), $array.slice!(i), "<#{iter} slice!(#{i})>") assert_equal($bdb.size, $array.size, "") reinject(20) if $bdb.size < 20 end 10.times do |iter| i = rand($bdb.size) assert_equal($bdb.slice!(-i), $array.slice!(-i), "") assert_equal($bdb.size, $array.size, "") reinject(20) if $bdb.size < 20 end 10.times do |iter| i = rand($bdb.size) j = rand($bdb.size) assert_equal($bdb.slice!(i, j), $array.slice!(i, j), "") assert_equal($bdb.size, $array.size, "") reinject(20) if $bdb.size < 20 end 10.times do |iter| i = rand($bdb.size) j = i + rand($bdb.size - i) assert_equal($bdb.slice!(-i, j), $array.slice!(-i, j), "") assert_equal($bdb.size, $array.size, "") reinject(20) if $bdb.size < 20 end reinject(20) another = 0 10.times do |iter| i = rand($bdb.size) j = i + rand($bdb.size - i) if ! $array.slice(i .. j) assert_error(RangeError, '', "") { $bdb.slice!(i .. j) } another += 1 redo if another < 10 another = 0 next end assert_equal($bdb.slice!(i .. j), $array.slice!(i .. j), "") assert_equal($bdb.size, $array.size, "") another = 0 reinject(20) if $bdb.size < 20 end another = 0 10.times do |iter| i = rand($bdb.size) j = 1 + rand($bdb.size - i) if ! $array.slice(-i .. -j) assert_raises(RangeError, "") { $bdb.slice!(-i .. -j) } another += 1 redo if another < 10 another = 0 next end assert_equal($bdb.slice!(-i .. -j), $array.slice!(-i .. -j), "") assert_equal($bdb.size, $array.size, "") another = 0 reinject(20) if $bdb.size < 20 end reinject(40) if $bdb.size < 40 assert_equal($bdb.size, $array.size, "") assert_equal($bdb.to_a, $array, "") end def test_07_reverse assert_equal($bdb.reverse, $array.reverse, "") $array.reverse! ; $bdb.reverse! assert_equal($bdb.to_a, $array, "") assert_equal($bdb.size, $array.size, "") end def test_08_index 100.times do i = rand($bdb.size) assert_equal($bdb.index(i), $array.index(i), "") assert_equal($bdb.index(-i), $array.index(-i), "") end 100.times do i = rand($bdb.size) assert_equal($bdb.rindex(i), $array.rindex(i), "") assert_equal($bdb.rindex(-i), $array.rindex(-i), "") end 100.times do aa = [] rand(12).times do aa.push rand($bdb.size) end assert_equal($array.indices(*aa), $bdb.indices(*aa), "") end 100.times do aa = [] rand(12).times do aa.push(-1 * rand($bdb.size)) end assert_equal($array.indices(*aa), $bdb.indices(*aa), "") end end def test_09_delete assert_equal($bdb.to_a, $array, "") 100.times do i = rand($bdb.size) assert_equal($bdb.delete(i), $array.delete(i), "") reinject(20) if $bdb.size < 20 end assert_equal($bdb.to_a, $array, "") 100.times do i = rand($bdb.size) assert_equal($bdb.delete_at(i), $array.delete_at(i), "") reinject(20) if $bdb.size < 20 end assert_equal($bdb.to_a, $array, "") reinject(60) if $bdb.size < 60 assert_equal($bdb.delete_if { false }, $bdb, "") assert_equal($bdb.to_a, $array, "") assert_equal($bdb.delete_if { true }, $bdb, "") assert_equal($bdb.size, 0, "") $bdb.push(*$array) assert_equal($bdb.to_a, $array, "") 100.times do i = rand($bdb.size) assert_equal($bdb.delete_if {|i| i.to_i > 32}, $bdb, "") $array.delete_if {|i| i.to_i > 32} assert_equal($bdb.to_a, $array, "") reinject(60) if $bdb.size < 60 end reinject(99) if $bdb.size < 99 end def test_10_reject assert_equal($bdb.to_a, $array, "") assert_equal(nil, $bdb.reject! { false }, "") end def test_11_clear $bdb.clear ; $array.clear assert_equal($array.size, $bdb.size, "") assert_equal($array, $bdb.to_a, "") end def test_12_fill $bdb.fill "32", 0, 99; $array.fill "32", 0, 99 assert_equal($array.size, $bdb.size, "") assert_equal($array, $bdb.to_a, "") $bdb.fill "42"; $array.fill "42" assert_equal($array.size, $bdb.size, "") assert_equal($array, $bdb.to_a, "") 10.times do |iter| k = rand($bdb.size).to_s i = rand($bdb.size) assert_equal($bdb.fill(k, i).to_a, $array.fill(k, i), "<#{iter} fill(#{i})>") assert_equal($bdb.size, $array.size, "") reinject(20) if $bdb.size < 20 end 10.times do |iter| k = rand($bdb.size).to_s i = rand($bdb.size) assert_equal($bdb.fill(k, -i).to_a, $array.fill(k, -i), "") assert_equal($bdb.size, $array.size, "") reinject(20) if $bdb.size < 20 end 10.times do |iter| k = rand($bdb.size).to_s i = rand($bdb.size) j = rand($bdb.size) assert_equal($bdb.fill(k, i, j).to_a, $array.fill(k, i, j), "") assert_equal($bdb.size, $array.size, "") reinject(20) if $bdb.size < 20 end 10.times do |iter| k = rand($bdb.size).to_s i = rand($bdb.size) j = i + rand($bdb.size - i) assert_equal($bdb.fill(k, -i, j).to_a, $array.fill(k, -i, j), "") assert_equal($bdb.size, $array.size, "") reinject(20) if $bdb.size < 20 end reinject(20) another = 0 10.times do |iter| k = rand($bdb.size).to_s i = rand($bdb.size) j = i + rand($bdb.size - i) if ! $array.slice(i .. j) assert_raises(RangeError, "") { $bdb.fill(k, i .. j) } another += 1 redo if another < 10 another = 0 next end assert_equal($bdb.fill(k, i .. j).to_a, $array.fill(k, i .. j), "") assert_equal($bdb.size, $array.size, "") another = 0 reinject(20) if $bdb.size < 20 end another = 0 10.times do |iter| k = rand($bdb.size).to_s i = rand($bdb.size) j = 1 + rand($bdb.size - i) if ! $array.slice(-i .. -j) assert_raises(RangeError, "") { $bdb.fill(k, -i .. -j) } another += 1 redo if another < 10 another = 0 next end assert_equal($bdb.fill(k, -i .. -j).to_a, $array.fill(k, -i .. -j), "") assert_equal($bdb.size, $array.size, "") another = 0 reinject(20) if $bdb.size < 20 end reinject(60) if $bdb.size < 60 assert_equal($bdb.size, $array.size, "") assert_equal($bdb.to_a, $array, "") end def test_13_include $bdb.clear; $array.clear; reinject(99) assert_equal($bdb.size, $array.size, "") assert_equal($bdb.to_a, $array, "") 100.times do k = rand($bdb.size + 20).to_s assert_equal($array.include?(k), $bdb.include?(k), "") end end def test_14_replace $array.replace(('a' .. 'zz').to_a) $bdb.replace(('a' .. 'zz').to_a) assert_equal($bdb.size, $array.size, "") assert_equal($bdb.to_a, $array, "") end def test_15_reopen $bdb.close assert_kind_of(BDB::Recnum, $bdb = BDB::Recnum.new("tmp/aa", nil, "a"), "") assert_equal($bdb.size, $array.size, "") assert_equal($bdb.to_a, $array, "") $bdb.close assert_kind_of(BDB::Recnum, $bdb = BDB::Unknown.new("tmp/aa", nil, "r+"), "") assert_equal($bdb.size, $array.size, "") assert_equal($bdb.to_a, $array, "") end end if defined?(RUNIT) RUNIT::CUI::TestRunner.run(TestRecnum.suite) end ruby-bdb-0.6.6/tests/runit_.rb000066400000000000000000000012621154714021300162170ustar00rootroot00000000000000begin require 'test/unit' rescue LoadError require 'runit/testcase' require 'runit/cui/testrunner' module RUNIT module Assert def assert_raises(error, message = nil) begin yield rescue error assert(true, message) rescue assert_fail("must fail with #{error} : #{string}") else assert_fail("*must* fail : #{string}") end end end end end if RUBY_VERSION >= "1.8" class Array alias indices values_at end class Hash alias indexes values_at end module BDB class Common alias indexes values_at end class Recnum alias indices values_at end end end ruby-bdb-0.6.6/util/000077500000000000000000000000001154714021300142045ustar00rootroot00000000000000ruby-bdb-0.6.6/util/mars16.rb000066400000000000000000000000541154714021300156410ustar00rootroot00000000000000require 'mkmf' create_makefile('marshal16') ruby-bdb-0.6.6/util/marshal16.c000066400000000000000000000531601154714021300161530ustar00rootroot00000000000000/********************************************************************** marshal.c - $Author: nobu $ $Date: 2002/12/12 07:35:27 $ created at: Thu Apr 27 16:30:01 JST 1995 Copyright (C) 1993-2000 Yukihiro Matsumoto **********************************************************************/ /* marshal.c from 1.6.8 adapted for 1.8.0 */ #include "ruby.h" #include "rubyio.h" #include "st.h" #if !defined(atof) && !defined(HAVE_STDLIB_H) double strtod(); #endif #define BITSPERSHORT (2*CHAR_BIT) #define SHORTMASK ((1<fp) putc(c, arg->fp); else rb_str_cat(arg->str, &c, 1); } static void w_bytes(s, n, arg) char *s; int n; struct dump_arg *arg; { w_long(n, arg); if (arg->fp) { fwrite(s, 1, n, arg->fp); } else { rb_str_cat(arg->str, s, n); } } static void w_short(x, arg) int x; struct dump_arg *arg; { w_byte((x >> 0) & 0xff, arg); w_byte((x >> 8) & 0xff, arg); } static void w_long(x, arg) long x; struct dump_arg *arg; { char buf[sizeof(long)+1]; int i, len = 0; #if SIZEOF_LONG > 4 if (!(RSHIFT(x, 31) == 0 || RSHIFT(x, 31) == -1)) { /* big long does not fit in 4 bytes */ rb_raise(rb_eTypeError, "long too big to dump"); } #endif if (x == 0) { w_byte(0, arg); return; } if (0 < x && x < 123) { w_byte(x + 5, arg); return; } if (-124 < x && x < 0) { w_byte((x - 5)&0xff, arg); return; } for (i=1;isymbol, id, &num)) { w_byte(TYPE_SYMLINK, arg); w_long(num, arg); } else { w_byte(TYPE_SYMBOL, arg); w_bytes(sym, strlen(sym), arg); st_add_direct(arg->symbol, id, arg->symbol->num_entries); } } static void w_unique(s, arg) char *s; struct dump_arg *arg; { if (s[0] == '#') { rb_raise(rb_eArgError, "can't dump anonymous class %s", s); } w_symbol(rb_intern(s), arg); } static void w_object _((VALUE,struct dump_arg*,int)); static int hash_each(key, value, arg) VALUE key, value; struct dump_call_arg *arg; { w_object(key, arg->arg, arg->limit); w_object(value, arg->arg, arg->limit); return ST_CONTINUE; } static int obj_each(id, value, arg) ID id; VALUE value; struct dump_call_arg *arg; { w_symbol(id, arg->arg); w_object(value, arg->arg, arg->limit); return ST_CONTINUE; } static void w_uclass(obj, klass, arg) VALUE obj, klass; struct dump_arg *arg; { if (rb_obj_class(obj) != klass) { w_byte(TYPE_UCLASS, arg); w_unique(rb_class2name(CLASS_OF(obj)), arg); } } static void w_ivar(tbl, arg) st_table *tbl; struct dump_call_arg *arg; { if (tbl) { w_long(tbl->num_entries, arg->arg); st_foreach(tbl, obj_each, arg); } else { w_long(0, arg->arg); } } static void w_object(obj, arg, limit) VALUE obj; struct dump_arg *arg; int limit; { struct dump_call_arg c_arg; st_table *ivtbl = 0; if (limit == 0) { rb_raise(rb_eArgError, "exceed depth limit"); } if (obj == Qnil) { w_byte(TYPE_NIL, arg); } else if (obj == Qtrue) { w_byte(TYPE_TRUE, arg); } else if (obj == Qfalse) { w_byte(TYPE_FALSE, arg); } else if (FIXNUM_P(obj)) { #if SIZEOF_LONG <= 4 w_byte(TYPE_FIXNUM, arg); w_long(FIX2INT(obj), arg); #else if (RSHIFT((long)obj, 31) == 0 || RSHIFT((long)obj, 31) == -1) { w_byte(TYPE_FIXNUM, arg); w_long(FIX2LONG(obj), arg); } else { w_object(rb_int2big(FIX2LONG(obj)), arg, limit); return; } #endif } else if (SYMBOL_P(obj)) { w_symbol(SYM2ID(obj), arg); return; } else { long num; limit--; c_arg.limit = limit; c_arg.arg = arg; if (st_lookup(arg->data, obj, &num)) { w_byte(TYPE_LINK, arg); w_long(num, arg); return; } if (OBJ_TAINTED(obj)) arg->taint = Qtrue; st_add_direct(arg->data, obj, arg->data->num_entries); if (rb_respond_to(obj, s_dump)) { VALUE v; w_byte(TYPE_USERDEF, arg); w_unique(rb_class2name(CLASS_OF(obj)), arg); v = rb_funcall(obj, s_dump, 1, INT2NUM(limit)); if (TYPE(v) != T_STRING) { rb_raise(rb_eTypeError, "_dump() must return String"); } w_bytes(RSTRING(v)->ptr, RSTRING(v)->len, arg); return; } if (ivtbl = rb_generic_ivar_table(obj)) { w_byte(TYPE_IVAR, arg); } switch (BUILTIN_TYPE(obj)) { case T_CLASS: if (FL_TEST(obj, FL_SINGLETON)) { rb_raise(rb_eTypeError, "singleton class can't be dumped"); } w_byte(TYPE_CLASS, arg); { VALUE path = rb_class_path(obj); if (RSTRING(path)->ptr[0] == '#') { rb_raise(rb_eArgError, "can't dump anonymous class %s", RSTRING(path)->ptr); } w_bytes(RSTRING(path)->ptr, RSTRING(path)->len, arg); } break; case T_MODULE: w_byte(TYPE_MODULE, arg); { VALUE path = rb_class_path(obj); if (RSTRING(path)->ptr[0] == '#') { rb_raise(rb_eArgError, "can't dump anonymous module %s", RSTRING(path)->ptr); } w_bytes(RSTRING(path)->ptr, RSTRING(path)->len, arg); } break; case T_FLOAT: w_byte(TYPE_FLOAT, arg); w_float(RFLOAT(obj)->value, arg); break; case T_BIGNUM: w_byte(TYPE_BIGNUM, arg); { char sign = RBIGNUM(obj)->sign?'+':'-'; long len = RBIGNUM(obj)->len; BDIGIT *d = RBIGNUM(obj)->digits; w_byte(sign, arg); w_long(SHORTLEN(len), arg); /* w_short? */ while (len--) { #if SIZEOF_BDIGITS > SIZEOF_SHORT BDIGIT num = *d; int i; for (i=0; iptr, RSTRING(obj)->len, arg); break; case T_REGEXP: w_uclass(obj, rb_cRegexp, arg); w_byte(TYPE_REGEXP, arg); w_bytes(RREGEXP(obj)->str, RREGEXP(obj)->len, arg); w_byte(rb_reg_options(obj), arg); break; case T_ARRAY: w_uclass(obj, rb_cArray, arg); w_byte(TYPE_ARRAY, arg); { long len = RARRAY(obj)->len; VALUE *ptr = RARRAY(obj)->ptr; w_long(len, arg); while (len--) { w_object(*ptr, arg, limit); ptr++; } } break; case T_HASH: w_uclass(obj, rb_cHash, arg); if (!NIL_P(RHASH(obj)->ifnone)) { w_byte(TYPE_HASH_DEF, arg); } else { w_byte(TYPE_HASH, arg); } w_long(RHASH(obj)->tbl->num_entries, arg); st_foreach(RHASH(obj)->tbl, hash_each, &c_arg); if (!NIL_P(RHASH(obj)->ifnone)) { w_object(RHASH(obj)->ifnone, arg, limit); } break; case T_STRUCT: w_byte(TYPE_STRUCT, arg); { long len = RSTRUCT(obj)->len; VALUE c, mem; long i; c = CLASS_OF(obj); w_unique(rb_class2name(c), arg); w_long(len, arg); if (FL_TEST(c, FL_SINGLETON)) c = RCLASS(c)->super; mem = rb_ivar_get(c, rb_intern("__member__")); if (mem == Qnil) { rb_raise(rb_eTypeError, "uninitialized struct"); } for (i=0; iptr[i]), arg); w_object(RSTRUCT(obj)->ptr[i], arg, limit); } } break; case T_OBJECT: w_byte(TYPE_OBJECT, arg); { VALUE klass = CLASS_OF(obj); char *path; while (FL_TEST(klass, FL_SINGLETON) || BUILTIN_TYPE(klass) == T_ICLASS) { if (RCLASS(klass)->m_tbl->num_entries > 0 || RCLASS(klass)->iv_tbl->num_entries > 1) { rb_raise(rb_eTypeError, "singleton can't be dumped"); } klass = RCLASS(klass)->super; } path = rb_class2name(klass); w_unique(path, arg); w_ivar(ROBJECT(obj)->iv_tbl, &c_arg); } break; default: rb_raise(rb_eTypeError, "can't dump %s", rb_class2name(CLASS_OF(obj))); break; } } if (ivtbl) { w_ivar(ivtbl, &c_arg); } } static VALUE dump(arg) struct dump_call_arg *arg; { w_object(arg->obj, arg->arg, arg->limit); return 0; } static VALUE dump_ensure(arg) struct dump_arg *arg; { st_free_table(arg->symbol); st_free_table(arg->data); if (!arg->fp && arg->taint) { OBJ_TAINT(arg->str); } return 0; } static VALUE marshal_dump(argc, argv) int argc; VALUE* argv; { VALUE obj, port, a1, a2; int limit = -1; struct dump_arg arg; struct dump_call_arg c_arg; port = 0; rb_scan_args(argc, argv, "12", &obj, &a1, &a2); if (argc == 3) { if (!NIL_P(a2)) limit = NUM2INT(a2); port = a1; } else if (argc == 2) { if (FIXNUM_P(a1)) limit = FIX2INT(a1); else port = a1; } if (port) { if (rb_obj_is_kind_of(port, rb_cIO)) { OpenFile *fptr; rb_io_binmode(port); GetOpenFile(port, fptr); rb_io_check_writable(fptr); arg.fp = (fptr->f2) ? fptr->f2 : fptr->f; } else { rb_raise(rb_eTypeError, "instance of IO needed"); } } else { arg.fp = 0; port = rb_str_new(0, 0); arg.str = port; } arg.symbol = st_init_numtable(); arg.data = st_init_numtable(); arg.taint = Qfalse; c_arg.obj = obj; c_arg.arg = &arg; c_arg.limit = limit; w_byte(MARSHAL_MAJOR, &arg); w_byte(MARSHAL_MINOR, &arg); rb_ensure(dump, (VALUE)&c_arg, dump_ensure, (VALUE)&arg); return port; } struct load_arg { FILE *fp; char *ptr, *end; st_table *symbol; VALUE data; VALUE proc; int taint; }; static VALUE r_object _((struct load_arg *arg)); static int r_byte(arg) struct load_arg *arg; { int c; if (arg->fp) { c = rb_getc(arg->fp); if (c == EOF) rb_eof_error(); } else if (arg->ptr < arg->end) { c = *(unsigned char*)arg->ptr++; } else { rb_raise(rb_eArgError, "marshal data too short"); } return c; } static unsigned short r_short(arg) struct load_arg *arg; { unsigned short x; x = r_byte(arg); x |= r_byte(arg)<<8; return x; } static void long_toobig(size) int size; { rb_raise(rb_eTypeError, "long too big for this architecture (size %d, given %d)", sizeof(long), size); } #undef SIGN_EXTEND_CHAR #if __STDC__ # define SIGN_EXTEND_CHAR(c) ((signed char)(c)) #else /* not __STDC__ */ /* As in Harbison and Steele. */ # define SIGN_EXTEND_CHAR(c) ((((unsigned char)(c)) ^ 128) - 128) #endif static long r_long(arg) struct load_arg *arg; { register long x; int c = SIGN_EXTEND_CHAR(r_byte(arg)); long i; if (c == 0) return 0; if (c > 0) { if (4 < c && c < 128) { return c - 5; } if (c > sizeof(long)) long_toobig(c); x = 0; for (i=0;i sizeof(long)) long_toobig(c); x = -1; for (i=0;ifp) { len = fread(s, 1, len, arg->fp); } else { if (arg->ptr + len > arg->end) { len = arg->end - arg->ptr; } memcpy(s, arg->ptr, len); arg->ptr += len; } s[len] = '\0'; } static ID r_symlink(arg) struct load_arg *arg; { ID id; long num = r_long(arg); if (st_lookup(arg->symbol, num, &id)) { return id; } rb_raise(rb_eTypeError, "bad symbol"); } static ID r_symreal(arg) struct load_arg *arg; { char *buf; ID id; r_bytes(buf, arg); id = rb_intern(buf); st_insert(arg->symbol, arg->symbol->num_entries, id); return id; } static ID r_symbol(arg) struct load_arg *arg; { if (r_byte(arg) == TYPE_SYMLINK) { return r_symlink(arg); } return r_symreal(arg); } static char* r_unique(arg) struct load_arg *arg; { return rb_id2name(r_symbol(arg)); } static VALUE r_string(arg) struct load_arg *arg; { char *buf; long len; r_bytes2(buf, len, arg); return rb_str_new(buf, len); } static VALUE r_regist(v, arg) VALUE v; struct load_arg *arg; { rb_hash_aset(arg->data, INT2FIX(RHASH(arg->data)->tbl->num_entries), v); if (arg->taint) OBJ_TAINT(v); return v; } static void r_ivar(obj, arg) VALUE obj; struct load_arg *arg; { long len; len = r_long(arg); if (len > 0) { while (len--) { ID id = r_symbol(arg); VALUE val = r_object(arg); rb_ivar_set(obj, id, val); } } } static VALUE r_object(arg) struct load_arg *arg; { VALUE v = Qnil; int type = r_byte(arg); long id; switch (type) { case TYPE_LINK: id = r_long(arg); v = rb_hash_aref(arg->data, INT2FIX(id)); if (NIL_P(v)) { rb_raise(rb_eArgError, "dump format error (unlinked)"); } return v; case TYPE_IVAR: v = r_object(arg); r_ivar(v, arg); return v; case TYPE_UCLASS: { VALUE c = rb_path2class(r_unique(arg)); if (FL_TEST(c, FL_SINGLETON)) { rb_raise(rb_eTypeError, "singleton can't be loaded"); } v = r_object(arg); if (rb_special_const_p(v) || TYPE(v) == T_OBJECT || TYPE(v) == T_CLASS) { format_error: rb_raise(rb_eArgError, "dump format error (user class)"); } if (TYPE(v) == T_MODULE || !RTEST(rb_funcall(c, '<', 1, RBASIC(v)->klass))) { VALUE tmp = rb_obj_alloc(c); if (TYPE(v) != TYPE(tmp)) goto format_error; } RBASIC(v)->klass = c; return v; } case TYPE_NIL: v = Qnil; break; case TYPE_TRUE: v = Qtrue; break; case TYPE_FALSE: v = Qfalse; break; case TYPE_FIXNUM: { long i = r_long(arg); v = INT2FIX(i); } break; case TYPE_FLOAT: { char *buf; double d, t = 0.0; r_bytes(buf, arg); if (strcmp(buf, "nan") == 0) { d = t / t; } else if (strcmp(buf, "inf") == 0) { d = 1.0 / t; } else if (strcmp(buf, "-inf") == 0) { d = -1.0 / t; } else { /* xxx: should not use system's strtod(3) */ d = strtod(buf, 0); } v = rb_float_new(d); r_regist(v, arg); } break; case TYPE_BIGNUM: { long len; BDIGIT *digits; NEWOBJ(big, struct RBignum); OBJSETUP(big, rb_cBignum, T_BIGNUM); big->sign = (r_byte(arg) == '+'); len = r_long(arg); #if SIZEOF_BDIGITS == SIZEOF_SHORT big->len = len; #else big->len = (len + 1) * 2 / sizeof(BDIGIT); #endif big->digits = digits = ALLOC_N(BDIGIT, big->len); while (len > 0) { #if SIZEOF_BDIGITS > SIZEOF_SHORT BDIGIT num = 0; int shift = 0; int i; for (i=0; iifnone = r_object(arg); } } break; case TYPE_STRUCT: { VALUE klass, mem, values; volatile long i; /* gcc 2.7.2.3 -O2 bug?? */ long len; ID slot; klass = rb_path2class(r_unique(arg)); mem = rb_ivar_get(klass, rb_intern("__member__")); if (mem == Qnil) { rb_raise(rb_eTypeError, "uninitialized struct"); } len = r_long(arg); values = rb_ary_new2(len); for (i=0; iptr[i] != ID2SYM(slot)) { rb_raise(rb_eTypeError, "struct %s not compatible (:%s for :%s)", rb_class2name(klass), rb_id2name(slot), rb_id2name(SYM2ID(RARRAY(mem)->ptr[i]))); } rb_struct_aset(v, INT2FIX(i), r_object(arg)); } } break; case TYPE_USERDEF: { VALUE klass; klass = rb_path2class(r_unique(arg)); if (!rb_respond_to(klass, s_load)) { rb_raise(rb_eTypeError, "class %s needs to have method `_load'", rb_class2name(klass)); } v = rb_funcall(klass, s_load, 1, r_string(arg)); r_regist(v, arg); } break; case TYPE_OBJECT: { VALUE klass; klass = rb_path2class(r_unique(arg)); if (TYPE(klass) != T_CLASS) { rb_raise(rb_eArgError, "dump format error"); } v = rb_obj_alloc(klass); if (TYPE(v) != T_OBJECT) { rb_raise(rb_eArgError, "dump format error"); } r_regist(v, arg); r_ivar(v, arg); } break; case TYPE_MODULE_OLD: { char *buf; r_bytes(buf, arg); v = r_regist(rb_path2class(buf), arg); } break; case TYPE_CLASS: { char *buf; r_bytes(buf, arg); v = rb_path2class(buf); if (TYPE(v) != T_CLASS) { rb_raise(rb_eTypeError, "%s is not a class", buf); } r_regist(v, arg); } break; case TYPE_MODULE: { char *buf; r_bytes(buf, arg); v = rb_path2class(buf); if (TYPE(v) != T_MODULE) { rb_raise(rb_eTypeError, "%s is not a module", buf); } r_regist(v, arg); } break; case TYPE_SYMBOL: v = ID2SYM(r_symreal(arg)); break; case TYPE_SYMLINK: return ID2SYM(r_symlink(arg)); default: rb_raise(rb_eArgError, "dump format error(0x%x)", type); break; } if (arg->proc) { rb_funcall(arg->proc, rb_intern("call"), 1, v); } return v; } static VALUE load(arg) struct load_arg *arg; { return r_object(arg); } static VALUE load_ensure(arg) struct load_arg *arg; { st_free_table(arg->symbol); return 0; } static VALUE marshal_load(argc, argv) int argc; VALUE *argv; { VALUE port, proc; int major, minor; VALUE v; OpenFile *fptr; struct load_arg arg; volatile VALUE hash; /* protect from GC */ rb_scan_args(argc, argv, "11", &port, &proc); if (rb_obj_is_kind_of(port, rb_cIO)) { rb_io_binmode(port); GetOpenFile(port, fptr); rb_io_check_readable(fptr); arg.fp = fptr->f; arg.taint = Qtrue; } else if (rb_respond_to(port, rb_intern("to_str"))) { long int len; arg.fp = 0; arg.ptr = rb_str2cstr(port, &len); arg.end = arg.ptr + len; arg.taint = OBJ_TAINTED(port); } else { rb_raise(rb_eTypeError, "instance of IO needed"); } major = r_byte(&arg); minor = r_byte(&arg); if (major != MARSHAL_MAJOR || minor > MARSHAL_MINOR) { rb_raise(rb_eTypeError, "incompatible marshal file format (can't be read)\n\ \tformat version %d.%d required; %d.%d given", MARSHAL_MAJOR, MARSHAL_MINOR, major, minor); } if (RTEST(ruby_verbose) && minor != MARSHAL_MINOR) { rb_warn("incompatible marshal file format (can be read)\n\ \tformat version %d.%d required; %d.%d given", MARSHAL_MAJOR, MARSHAL_MINOR, major, minor); } arg.symbol = st_init_numtable(); arg.data = hash = rb_hash_new(); if (NIL_P(proc)) arg.proc = 0; else arg.proc = proc; v = rb_ensure(load, (VALUE)&arg, load_ensure, (VALUE)&arg); return v; } void Init_marshal16() { VALUE rb_mMarshal = rb_define_module("Marshal"); s_dump = rb_intern("_dump"); s_load = rb_intern("_load"); rb_define_module_function(rb_mMarshal, "dump16", marshal_dump, -1); rb_define_module_function(rb_mMarshal, "load16", marshal_load, -1); rb_define_module_function(rb_mMarshal, "restore16", marshal_load, -1); }