1 /* 2 bdb2d is BerkeleyDB for D language 3 It is part of unDE project (http://unde.su) 4 5 Copyright (C) 2009-2014 Nikolay (unDEFER) Krivchenkov <undefer@gmail.com> 6 7 This program is free software: you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation, either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 module berkeleydb.db; 22 23 import berkeleydb.c; 24 import berkeleydb.dbenv; 25 import berkeleydb.dbexception; 26 import berkeleydb.dbtxn; 27 import berkeleydb.dbt; 28 import berkeleydb.dbc; 29 import berkeleydb.dbmpoolfile; 30 31 import std.stdint; 32 import std.stdio; 33 import std.string; 34 import std.array; 35 import std.format; 36 import std.conv; 37 38 alias DB_COMPACT DbCompact; 39 alias DB_KEY_RANGE DbKeyRange; 40 alias DB_CACHE_PRIORITY DbCachePriority; 41 42 class Db 43 { 44 private: 45 DB *db = null; 46 DbEnv dbenv = null; 47 int opened = 0; 48 static Db[DB *] db_map; 49 50 static Db from_DB(const DB *_db) 51 { 52 return db_map[_db]; 53 } 54 55 package: 56 @property DB *_DB() {return db;} 57 @property DbEnv _dbenv() {return dbenv;} 58 @property int _opened() {return opened;} 59 60 public: 61 DbEnv get_env() 62 { 63 return dbenv; 64 } 65 66 this(DbEnv dbenv, uint32_t flags = 0) 67 { 68 auto ret = db_create(&db, dbenv?dbenv._DB_ENV:null, flags); 69 DbRetCodeToException(ret, dbenv); 70 db_map[db] = this; 71 this.dbenv = dbenv; 72 assert(ret == 0); 73 } 74 75 ~this() 76 { 77 if (opened >= 0) close(); 78 db_map.remove(db); 79 } 80 81 static ~this() 82 { 83 db_map = null; 84 } 85 86 void open(DbTxn txnid, string file, 87 string database, DBTYPE type, uint32_t flags, int mode) 88 { 89 if (opened > 0) { 90 throw new DbWrongUsingException("Opening opened Db"); 91 } 92 if (opened < 0) { 93 throw new DbWrongUsingException("Opening closed Db"); 94 } 95 auto ret = db.open(db, txnid?txnid._DB_TXN:null, file.toStringz(), database.toStringz(), 96 type, flags, mode); 97 DbRetCodeToException(ret, dbenv); 98 assert(ret == 0); 99 opened++; 100 } 101 102 void close(uint32_t flags = 0) 103 { 104 if (opened < 0) { 105 throw new DbWrongUsingException("Closing closed Db"); 106 } 107 auto ret = db.close(db, flags); 108 opened = -1; 109 DbRetCodeToException(ret, dbenv); 110 assert(ret == 0); 111 } 112 113 void remove(string file, string database, uint32_t flags = 0) 114 { 115 if (opened > 0) { 116 throw new DbWrongUsingException("Removing opened Db"); 117 } 118 if (opened < 0) { 119 throw new DbWrongUsingException("Operation on closed Db"); 120 } 121 auto ret = db.remove(db, file.toStringz(), database.toStringz(), flags); 122 opened = -1; 123 DbRetCodeToException(ret, dbenv); 124 assert(ret == 0); 125 } 126 127 void rename(string file, string database, string newname, uint32_t flags = 0) 128 { 129 if (opened > 0) { 130 throw new DbWrongUsingException("Renaming opened Db"); 131 } 132 if (opened < 0) { 133 throw new DbWrongUsingException("Operation on closed Db"); 134 } 135 auto ret = db.rename(db, file.toStringz(), database.toStringz(), newname.toStringz(), flags); 136 opened = -1; 137 DbRetCodeToException(ret, dbenv); 138 assert(ret == 0); 139 } 140 141 void verify(string file, string database, File outfile, uint32_t flags = 0) 142 { 143 if (opened > 0) { 144 throw new DbWrongUsingException("Verifying opened Db"); 145 } 146 if (opened < 0) { 147 throw new DbWrongUsingException("Operation on closed Db"); 148 } 149 auto ret = db.verify(db, file.toStringz(), database.toStringz(), outfile.getFP(), flags); 150 opened = -1; 151 DbRetCodeToException(ret, dbenv); 152 assert(ret == 0); 153 } 154 155 private 156 { 157 int function(Db secondary, ref const (Dbt) key, 158 ref const (Dbt) data, out Dbt result) associate_callback_refer; 159 160 extern (C) static int associate_callback(DB *_secondary, 161 const (DBT) *_key, const (DBT) *_data, DBT *_result) 162 { 163 Db secondary = from_DB(_secondary); 164 const (Dbt) *key = cast(const (Dbt) *) _key; 165 const (Dbt) *data = cast(const (Dbt) *) _data; 166 Dbt *result = cast(Dbt *) _result; 167 return secondary.associate_callback_refer(secondary, *key, *data, *result); 168 } 169 } 170 171 void associate(DbTxn txnid, Db secondary, 172 int function(Db secondary, 173 ref const (Dbt) key, ref const (Dbt) data, out Dbt result) callback, 174 uint32_t flags = 0) 175 { 176 if (opened < 0) { 177 throw new DbWrongUsingException("Operation on closed Db"); 178 } 179 secondary.associate_callback_refer = callback; 180 auto ret = db.associate(db, txnid?txnid._DB_TXN:null, secondary._DB, 181 callback?&associate_callback:null, flags); 182 DbRetCodeToException(ret, dbenv); 183 assert(ret == 0); 184 } 185 186 private 187 { 188 int function (Db secondary, 189 ref const (Dbt) key, out Dbt data, ref const (Dbt) foreignkey, 190 out int changed) associate_foreign_callback_refer; 191 192 extern (C) static int associate_foreign_callback(DB *_secondary, 193 const (DBT) *_key, DBT *_data, const (DBT) *_foreignkey, int *changed) 194 { 195 Db secondary = from_DB(_secondary); 196 const (Dbt) *key = cast(const (Dbt) *) _key; 197 Dbt *data = cast(Dbt *) _data; 198 const (Dbt) *foreignkey = cast(const (Dbt) *) _foreignkey; 199 return secondary.associate_foreign_callback_refer(secondary, *key, *data, *foreignkey, *changed); 200 } 201 } 202 203 void associate_foreign(Db secondary, int function(Db secondary, 204 ref const (Dbt) key, out Dbt data, ref const (Dbt) foreignkey, out int changed) callback, 205 uint32_t flags = 0) 206 { 207 if (opened < 0) { 208 throw new DbWrongUsingException("Operation on closed Db"); 209 } 210 secondary.associate_foreign_callback_refer = callback; 211 auto ret = db.associate_foreign(db, secondary._DB, 212 callback?&associate_foreign_callback:null, flags); 213 DbRetCodeToException(ret, dbenv); 214 assert(ret == 0); 215 } 216 217 void compact(DbTxn txnid, 218 Dbt *start, Dbt *stop, DbCompact *c_data, uint32_t flags, Dbt *end) 219 { 220 if (opened < 0) { 221 throw new DbWrongUsingException("Operation on closed Db"); 222 } 223 auto ret = db.compact(db, txnid?txnid._DB_TXN:null, &start.dbt, &stop.dbt, 224 c_data, flags, &end.dbt); 225 DbRetCodeToException(ret, dbenv); 226 assert(ret == 0); 227 } 228 229 int del(DbTxn txnid, Dbt *key, uint32_t flags = 0) 230 { 231 if (opened < 0) { 232 throw new DbWrongUsingException("Operation on closed Db"); 233 } 234 auto ret = db.del(db, txnid?txnid._DB_TXN:null, &key.dbt, flags); 235 return DbRetCodeToException!"Db.del"(ret, dbenv); 236 } 237 238 int get(DbTxn txnid, Dbt *key, Dbt *data, uint32_t flags = 0) 239 { 240 if (opened < 0) { 241 throw new DbWrongUsingException("Operation on closed Db"); 242 } 243 auto ret = db.get(db, txnid?txnid._DB_TXN:null, &key.dbt, &data.dbt, flags); 244 DbRetCodeToException!"Db.get"(ret, dbenv, data); 245 return DbRetCodeToException!"Db.get"(ret, dbenv); 246 } 247 248 int pget(DbTxn txnid, Dbt *key, Dbt *pkey, Dbt *data, uint32_t flags = 0) 249 { 250 if (opened < 0) { 251 throw new DbWrongUsingException("Operation on closed Db"); 252 } 253 auto ret = db.pget(db, txnid?txnid._DB_TXN:null, &key.dbt, &pkey.dbt, &data.dbt, flags); 254 DbRetCodeToException!"Db.get"(ret, dbenv, data); 255 return DbRetCodeToException!"Db.get"(ret, dbenv); 256 } 257 258 int put(DbTxn txnid, Dbt *key, Dbt *data, uint32_t flags = 0) 259 { 260 if (opened < 0) { 261 throw new DbWrongUsingException("Operation on closed Db"); 262 } 263 auto ret = db.put(db, txnid?txnid._DB_TXN:null, &key.dbt, &data.dbt, flags); 264 return DbRetCodeToException!"Db.put"(ret, dbenv); 265 } 266 267 void err(T...)(int error, string fmt, T args) 268 { 269 if (opened < 0) { 270 throw new DbWrongUsingException("Operation on closed Db"); 271 } 272 auto app = appender!string(); 273 formattedWrite(app, fmt, args); 274 db.err(db, error, "%s".toStringz(), app.data.toStringz()); 275 } 276 277 void errx(T...)(string fmt, T args) 278 { 279 if (opened < 0) { 280 throw new DbWrongUsingException("Operation on closed Db"); 281 } 282 auto app = appender!string(); 283 formattedWrite(app, fmt, args); 284 db.errx(db, "%s".toStringz(), app.data.toStringz()); 285 } 286 287 int exists(DbTxn txnid, Dbt *key, uint32_t flags = 0) 288 { 289 if (opened < 0) { 290 throw new DbWrongUsingException("Operation on closed Db"); 291 } 292 auto ret = db.exists(db, txnid?txnid._DB_TXN:null, &key.dbt, flags); 293 return DbRetCodeToException!"exists"(ret, dbenv); 294 } 295 296 int fd() 297 { 298 if (opened < 0) { 299 throw new DbWrongUsingException("Operation on closed Db"); 300 } 301 int res; 302 auto ret = db.fd(db, &res); 303 DbRetCodeToException(ret, dbenv); 304 assert(ret == 0); 305 return res; 306 } 307 308 int get_byteswapped() 309 { 310 if (opened <= 0) { 311 throw new DbWrongUsingException("Operation on closed or not opened Db"); 312 } 313 int res; 314 auto ret = db.fd(db, &res); 315 DbRetCodeToException(ret, dbenv); 316 assert(ret == 0); 317 return res; 318 } 319 320 void get_dbname(ref string filename, ref string dbname) 321 { 322 if (opened < 0) { 323 throw new DbWrongUsingException("Operation on closed Db"); 324 } 325 const (char) *_filename; 326 const (char) *_dbname; 327 auto ret = db.get_dbname(db, &_filename, &_dbname); 328 DbRetCodeToException(ret, dbenv); 329 assert(ret == 0); 330 filename = to!string(_filename); 331 dbname = to!string(_dbname); 332 } 333 334 int get_multiple() 335 { 336 if (opened <= 0) { 337 throw new DbWrongUsingException("Operation on closed or not opened Db"); 338 } 339 return db.get_multiple(db); 340 } 341 342 uint32_t get_open_flags() 343 { 344 if (opened <= 0) { 345 throw new DbWrongUsingException("Operation on closed or not opened Db"); 346 } 347 uint32_t res; 348 auto ret = db.get_open_flags(db, &res); 349 DbRetCodeToException(ret, dbenv); 350 assert(ret == 0); 351 return res; 352 } 353 354 DBTYPE get_type() 355 { 356 if (opened <= 0) { 357 throw new DbWrongUsingException("Operation on closed or not opened Db"); 358 } 359 DBTYPE res; 360 auto ret = db.get_type(db, &res); 361 DbRetCodeToException(ret, dbenv); 362 assert(ret == 0); 363 return res; 364 } 365 366 Dbc join(Dbc[] curslist, uint32_t flags = 0) 367 { 368 if (opened < 0) { 369 throw new DbWrongUsingException("Operation on closed Db"); 370 } 371 372 // convert Dbc[] to null-terminated array of DBC* 373 DBC*[] _curslist = new DBC*[curslist.length + 1]; 374 foreach(int i, Dbc c; curslist[]) 375 _curslist[i] = c._DBC; 376 377 DBC *res; 378 auto ret = db.join(db, _curslist.ptr, &res, flags); 379 DbRetCodeToException(ret, dbenv); 380 assert(ret == 0); 381 return new Dbc(res, true, dbenv); 382 } 383 384 DbKeyRange key_range(DbTxn txnid, Dbt *key, uint32_t flags = 0) 385 { 386 if (opened < 0) { 387 throw new DbWrongUsingException("Operation on closed Db"); 388 } 389 DbKeyRange res; 390 auto ret = db.key_range(db, txnid?txnid._DB_TXN:null, &key.dbt, &res, flags); 391 DbRetCodeToException(ret, dbenv); 392 assert(ret == 0); 393 return res; 394 } 395 396 void set_priority(DbCachePriority priority) 397 { 398 if (opened < 0) { 399 throw new DbWrongUsingException("Operation on closed Db"); 400 } 401 auto ret = db.set_priority(db, priority); 402 DbRetCodeToException(ret, dbenv); 403 assert(ret == 0); 404 } 405 406 DbCachePriority get_priority() 407 { 408 if (opened < 0) { 409 throw new DbWrongUsingException("Operation on closed Db"); 410 } 411 DbCachePriority res; 412 auto ret = db.get_priority(db, &res); 413 DbRetCodeToException(ret, dbenv); 414 assert(ret == 0); 415 return res; 416 } 417 418 void stat(DbTxn txnid, void *sp, uint32_t flags = 0) 419 { 420 if (opened <= 0) { 421 throw new DbWrongUsingException("Operation on closed or not opened Db"); 422 } 423 auto ret = db.stat(db, txnid?txnid._DB_TXN:null, sp, flags); 424 DbRetCodeToException(ret, dbenv); 425 assert(ret == 0); 426 } 427 428 void stat_print(uint32_t flags = 0) 429 { 430 if (opened <= 0) { 431 throw new DbWrongUsingException("Operation on closed or not opened Db"); 432 } 433 auto ret = db.stat_print(db, flags); 434 DbRetCodeToException(ret, dbenv); 435 assert(ret == 0); 436 } 437 438 void sync(uint32_t flags = 0) 439 { 440 if (opened < 0) { 441 throw new DbWrongUsingException("Operation on closed Db"); 442 } 443 auto ret = db.sync(db, flags); 444 DbRetCodeToException(ret, dbenv); 445 assert(ret == 0); 446 } 447 448 uint32_t truncate(DbTxn txnid, uint32_t flags = 0) 449 { 450 if (opened < 0) { 451 throw new DbWrongUsingException("Operation on closed Db"); 452 } 453 uint32_t count; 454 auto ret = db.truncate(db, txnid?txnid._DB_TXN:null, &count, flags); 455 DbRetCodeToException(ret, dbenv); 456 assert(ret == 0); 457 return count; 458 } 459 460 void upgrade(string file, uint32_t flags = 0) 461 { 462 if (opened < 0) { 463 throw new DbWrongUsingException("Operation on closed Db"); 464 } 465 auto ret = db.upgrade(db, file.toStringz(), flags); 466 DbRetCodeToException(ret, dbenv); 467 assert(ret == 0); 468 } 469 470 Dbc cursor(DbTxn txnid, uint32_t flags = 0) 471 { 472 if (opened < 0) { 473 throw new DbWrongUsingException("Operation on closed Db"); 474 } 475 476 DBC *res; 477 auto ret = db.cursor(db, txnid?txnid._DB_TXN:null, &res, flags); 478 DbRetCodeToException(ret, dbenv); 479 assert(ret == 0); 480 return new Dbc(res, false, dbenv); 481 } 482 483 /* Database Configuration */ 484 485 private 486 { 487 uint32_t function (Db db, Dbt *key) db_partition_callback_refer; 488 489 extern (C) static uint32_t db_partition_callback(DB *_db, DBT *_key) 490 { 491 Db db = from_DB(_db); 492 Dbt *key = cast(Dbt *) _key; 493 return db.db_partition_callback_refer(db, key); 494 } 495 } 496 497 void set_partition(uint32_t parts, Dbt[] keys, 498 uint32_t function (Db db, Dbt *key) db_partition_fcn) 499 { 500 if (opened < 0) { 501 throw new DbWrongUsingException("Configuration on closed Db"); 502 } 503 if ( (parts-1) != keys.length ) 504 { 505 throw new DbWrongUsingException("Length of keys must be one less than parts"); 506 } 507 db_partition_callback_refer = db_partition_fcn; 508 auto ret = db.set_partition(db, parts, cast(DBT*)keys.ptr, 509 db_partition_fcn?&db_partition_callback:null); 510 DbRetCodeToException(ret, dbenv); 511 assert(ret == 0); 512 } 513 514 /*FIXME: What we must return when callback reference is null??? O_o*/ 515 void get_partition_callback(ref uint32_t parts, 516 ref uint32_t function (Db dbp, Dbt *key) callback_fcn) 517 { 518 if (opened < 0) { 519 throw new DbWrongUsingException("Get configuration on closed Db"); 520 } 521 522 callback_fcn = db_partition_callback_refer; 523 524 extern (C) uint32_t function(DB *_db, DBT *_key) n; 525 auto ret = db.get_partition_callback(db, &parts, &n); 526 DbRetCodeToException(ret, dbenv); 527 assert(ret == 0); 528 } 529 530 void get_partition_keys(ref uint32_t parts, ref Dbt[] keys) 531 { 532 if (opened < 0) { 533 throw new DbWrongUsingException("Get configuration on closed Db"); 534 } 535 536 DBT *_keys; 537 auto ret = db.get_partition_keys(db, &parts, &_keys); 538 DbRetCodeToException(ret, dbenv); 539 assert(ret == 0); 540 541 /*"parts-1" - is not error, it is really length of keys array according 542 BerkeleyDb documentation */ 543 keys = (cast(Dbt*)_keys)[0..parts-1]; 544 } 545 546 Dbt[] get_partition_keys() 547 { 548 if (opened < 0) { 549 throw new DbWrongUsingException("Get configuration on closed Db"); 550 } 551 552 uint32_t parts; 553 DBT *_keys; 554 auto ret = db.get_partition_keys(db, &parts, &_keys); 555 DbRetCodeToException(ret, dbenv); 556 assert(ret == 0); 557 558 /*"parts-1" - is not error, it is really length of keys array according 559 BerkeleyDb documentation */ 560 return (cast(Dbt*)_keys)[0..parts-1]; 561 } 562 563 extern (C) void set_alloc(void *function(size_t) app_malloc, 564 void *function(void *, size_t) app_realloc, 565 void function(void *) app_free) 566 { 567 if (opened < 0) { 568 throw new DbWrongUsingException("Configuration on closed DbEnv"); 569 } 570 if (opened > 0) { 571 throw new DbWrongUsingException("Configuration of opened DbEnv"); 572 } 573 auto ret = db.set_alloc(db, app_malloc, app_realloc, app_free); 574 DbRetCodeToException(ret, dbenv); 575 assert(ret == 0); 576 } 577 578 void set_cachesize(uint32_t gbytes, uint32_t bytes, int ncache) 579 { 580 if (opened < 0) { 581 throw new DbWrongUsingException("Configuration on closed Db"); 582 } 583 if (opened > 0) { 584 throw new DbWrongUsingException("Configuration of opened Db"); 585 } 586 587 auto ret = db.set_cachesize(db, gbytes, bytes, ncache); 588 DbRetCodeToException(ret, dbenv); 589 assert(ret == 0); 590 } 591 592 void set_cachesize(uint64_t bytes, int ncache) 593 { 594 uint32_t _gbytes = cast(uint32_t) bytes/(1024*1024*1024); 595 uint32_t _bytes = bytes%(1024*1024*1024); 596 set_cachesize(_gbytes, _bytes, ncache); 597 } 598 599 void get_cachesize(ref uint32_t gbytes, ref uint32_t bytes, ref int ncache) 600 { 601 if (opened < 0) { 602 throw new DbWrongUsingException("Get configuration on closed Db"); 603 } 604 auto ret = db.get_cachesize(db, &gbytes, &bytes, &ncache); 605 DbRetCodeToException(ret, dbenv); 606 assert(ret == 0); 607 } 608 609 void get_cachesize(ref uint64_t bytes, ref int ncache) 610 { 611 uint32_t _gbytes; 612 uint32_t _bytes; 613 get_cachesize(_gbytes, _bytes, ncache); 614 bytes = (1024UL*1024*1024)*_gbytes + _bytes; 615 } 616 617 uint64_t get_cachesize(ref int ncache) 618 { 619 uint64_t bytes; 620 get_cachesize(bytes, ncache); 621 return bytes; 622 } 623 624 void set_create_dir(string dir) 625 { 626 if (opened < 0) { 627 throw new DbWrongUsingException("Configuration on closed Db"); 628 } 629 if (opened > 0) { 630 throw new DbWrongUsingException("Configuration of opened Db"); 631 } 632 633 auto ret = db.set_create_dir(db, dir.toStringz()); 634 DbRetCodeToException(ret, dbenv); 635 assert(ret == 0); 636 } 637 638 string get_create_dir() 639 { 640 if (opened < 0) { 641 throw new DbWrongUsingException("Get configuration on closed Db"); 642 } 643 const (char) *res; 644 auto ret = db.get_create_dir(db, &res); 645 DbRetCodeToException(ret, dbenv); 646 assert(ret == 0); 647 return to!string(res); 648 } 649 650 private 651 { 652 version(VERSION_6) 653 { 654 int function(Db db, 655 const (Dbt) *dbt1, const (Dbt) *dbt2, size_t *locp) dup_compare_callback_refer; 656 657 extern (C) static int dup_compare_callback(DB *_db, 658 const (DBT) *_dbt1, const (DBT) *_dbt2, size_t *locp) 659 { 660 Db db = from_DB(_db); 661 const (Dbt) *dbt1 = cast(const (Dbt) *) _dbt1; 662 const (Dbt) *dbt2 = cast(const (Dbt) *) _dbt2; 663 return db.dup_compare_callback_refer(db, dbt1, dbt2, locp); 664 } 665 666 alias int function(Db db, const (Dbt) *dbt1, const (Dbt) *dbt2, size_t *locp) dup_compare_fcn_t; 667 } 668 else 669 { 670 int function(Db db, 671 const (Dbt) *dbt1, const (Dbt) *dbt2) dup_compare_callback_refer; 672 673 extern (C) static int dup_compare_callback(DB *_db, 674 const (DBT) *_dbt1, const (DBT) *_dbt2) 675 { 676 Db db = from_DB(_db); 677 const (Dbt) *dbt1 = cast(const (Dbt) *) _dbt1; 678 const (Dbt) *dbt2 = cast(const (Dbt) *) _dbt2; 679 return db.dup_compare_callback_refer(db, dbt1, dbt2); 680 } 681 alias int function(Db db, const (Dbt) *dbt1, const (Dbt) *dbt2) dup_compare_fcn_t; 682 } 683 } 684 685 void set_dup_compare(dup_compare_fcn_t dup_compare_fcn) 686 { 687 if (opened < 0) { 688 throw new DbWrongUsingException("Configuration on closed Db"); 689 } 690 if (opened > 0) { 691 throw new DbWrongUsingException("Configuration of opened Db"); 692 } 693 dup_compare_callback_refer = dup_compare_fcn; 694 auto ret = db.set_dup_compare(db, 695 dup_compare_fcn?&dup_compare_callback:null); 696 DbRetCodeToException(ret, dbenv); 697 assert(ret == 0); 698 } 699 700 void set_encrypt(string passwd, uint32_t flags = 0) 701 { 702 if (opened < 0) { 703 throw new DbWrongUsingException("Configuration on closed Db"); 704 } 705 if (opened > 0) { 706 throw new DbWrongUsingException("Configuration of opened Db"); 707 } 708 auto ret = db.set_encrypt(db, passwd.toStringz(), flags); 709 DbRetCodeToException(ret, dbenv); 710 assert(ret == 0); 711 } 712 713 uint32_t get_encrypt_flags() 714 { 715 if (opened < 0) { 716 throw new DbWrongUsingException("Get configuration on closed Db"); 717 } 718 uint32_t res; 719 auto ret = db.get_encrypt_flags(db, &res); 720 DbRetCodeToException(ret, dbenv); 721 assert(ret == 0); 722 return res; 723 } 724 725 private File _errfile; 726 727 void set_errfile(File errfile) 728 { 729 if (opened < 0) { 730 throw new DbWrongUsingException("Configuration on closed Db"); 731 } 732 if (dbenv) dbenv.set_errfile(errfile); 733 else 734 { 735 _errfile = errfile; 736 db.set_errfile(db, errfile.getFP()); 737 } 738 } 739 740 File get_errfile() 741 { 742 if (opened < 0) { 743 throw new DbWrongUsingException("Get configuration on closed Db"); 744 } 745 if (dbenv) return dbenv.get_errfile(); 746 else return _errfile; 747 } 748 749 void set_errpfx(string errpfx) 750 { 751 if (opened < 0) { 752 throw new DbWrongUsingException("Configuration on closed Db"); 753 } 754 db.set_errpfx(db, errpfx.toStringz()); 755 } 756 757 string get_errpfx() 758 { 759 if (opened < 0) { 760 throw new DbWrongUsingException("Get configuration on closed Db"); 761 } 762 const (char) *res; 763 db.get_errpfx(db, &res); 764 return to!string(res); 765 } 766 767 private 768 { 769 void function(Db db, int opcode, int percent) db_feedback_callback_refer; 770 771 extern (C) static void db_feedback_callback(DB *dbp, int opcode, int percent) 772 { 773 Db db = from_DB(dbp); 774 return db.db_feedback_callback_refer(db, opcode, percent); 775 } 776 } 777 778 void set_feedback(void function(Db db, int opcode, int percent) db_feedback_fcn) 779 { 780 if (opened < 0) { 781 throw new DbWrongUsingException("Configuration on closed Db"); 782 } 783 db_feedback_callback_refer = db_feedback_fcn; 784 auto ret = db.set_feedback(db, db_feedback_fcn?&db_feedback_callback:null); 785 DbRetCodeToException(ret, dbenv); 786 assert(ret == 0); 787 } 788 789 void set_flags(uint32_t flags = 0) 790 { 791 if (opened < 0) { 792 throw new DbWrongUsingException("Configuration on closed Db"); 793 } 794 if (opened > 0) { 795 throw new DbWrongUsingException("Configuration of opened Db"); 796 } 797 auto ret = db.set_flags(db, flags); 798 DbRetCodeToException(ret, dbenv); 799 assert(ret == 0); 800 } 801 802 uint32_t get_flags() 803 { 804 if (opened < 0) { 805 throw new DbWrongUsingException("Get configuration on closed Db"); 806 } 807 uint32_t res; 808 auto ret = db.get_flags(db, &res); 809 DbRetCodeToException(ret, dbenv); 810 assert(ret == 0); 811 return res; 812 } 813 814 void set_lk_exclusive(int nowait_onoff) 815 { 816 if (opened < 0) { 817 throw new DbWrongUsingException("Operation on closed Db"); 818 } 819 if (opened > 0) { 820 throw new DbWrongUsingException("Configuration of opened Db"); 821 } 822 auto ret = db.set_lk_exclusive(db, nowait_onoff); 823 DbRetCodeToException(ret, dbenv); 824 assert(ret == 0); 825 } 826 827 void get_lk_exclusive(ref int onoff, ref int nowait) 828 { 829 if (opened < 0) { 830 throw new DbWrongUsingException("Get configuration on closed Db"); 831 } 832 auto ret = db.get_lk_exclusive(db, &onoff, &nowait); 833 DbRetCodeToException(ret, dbenv); 834 assert(ret == 0); 835 } 836 837 void set_lorder(int lorder) 838 { 839 if (opened < 0) { 840 throw new DbWrongUsingException("Configuration on closed Db"); 841 } 842 if (opened > 0) { 843 throw new DbWrongUsingException("Configuration of opened Db"); 844 } 845 auto ret = db.set_lorder(db, lorder); 846 DbRetCodeToException(ret, dbenv); 847 assert(ret == 0); 848 } 849 850 int get_lorder() 851 { 852 if (opened < 0) { 853 throw new DbWrongUsingException("Get configuration on closed Db"); 854 } 855 int res; 856 auto ret = db.get_lorder(db, &res); 857 DbRetCodeToException(ret, dbenv); 858 assert(ret == 0); 859 return res; 860 } 861 862 void set_msgcall(void function(const DbEnv dbenv, string msg) db_msgcall_fcn) 863 { 864 if (opened < 0) { 865 throw new DbWrongUsingException("Configuration on closed DbEnv"); 866 } 867 if (dbenv) dbenv.set_msgcall(db_msgcall_fcn); 868 else assert(0, "Use extern(C) version of set_msgcall()"); 869 } 870 871 extern (C) void set_msgcall(void function(const (DB_ENV) *dbenv, const (char) *msg) db_msgcall_fcn) 872 { 873 if (opened < 0) { 874 throw new DbWrongUsingException("Configuration on closed DbEnv"); 875 } 876 db.set_msgcall(db, db_msgcall_fcn); 877 } 878 879 private File _msgfile; 880 881 void set_msgfile(File msgfile) 882 { 883 if (opened < 0) { 884 throw new DbWrongUsingException("Configuration on closed Db"); 885 } 886 if (dbenv) dbenv.set_msgfile(msgfile); 887 else 888 { 889 _msgfile = msgfile; 890 db.set_msgfile(db, msgfile.getFP()); 891 } 892 } 893 894 File get_msgfile() 895 { 896 if (opened < 0) { 897 throw new DbWrongUsingException("Get configuration on closed Db"); 898 } 899 if (dbenv) return dbenv.get_msgfile(); 900 return _msgfile; 901 } 902 903 void set_pagesize(uint32_t pagesize) 904 { 905 if (opened < 0) { 906 throw new DbWrongUsingException("Operation on closed Db"); 907 } 908 if (opened > 0) { 909 throw new DbWrongUsingException("Configuration of opened Db"); 910 } 911 auto ret = db.set_pagesize(db, pagesize); 912 DbRetCodeToException(ret, dbenv); 913 assert(ret == 0); 914 } 915 916 uint32_t get_pagesize() 917 { 918 if (opened <= 0) { 919 throw new DbWrongUsingException("Get configuration on closed or not opened Db"); 920 } 921 uint32_t res; 922 auto ret = db.get_pagesize(db, &res); 923 DbRetCodeToException(ret, dbenv); 924 assert(ret == 0); 925 return res; 926 } 927 928 void set_partition_dirs(string[] dirs) 929 { 930 if (opened < 0) { 931 throw new DbWrongUsingException("Operation on closed Db"); 932 } 933 if (opened > 0) { 934 throw new DbWrongUsingException("Configuration of opened Db"); 935 } 936 937 const (char) *[]_dirs = new const (char) *[dirs.length+1]; 938 foreach(int i, string dir; dirs) 939 _dirs[i] = dirs[i].toStringz(); 940 941 auto ret = db.set_partition_dirs(db, _dirs.ptr); 942 DbRetCodeToException(ret, dbenv); 943 assert(ret == 0); 944 } 945 946 string[] get_partition_dirs() 947 { 948 if (opened < 0) { 949 throw new DbWrongUsingException("Get configuration on closed Db"); 950 } 951 const (char) **_res; 952 auto ret = db.get_partition_dirs(db, &_res); 953 DbRetCodeToException(ret, dbenv); 954 assert(ret == 0); 955 956 string[] res = []; 957 for (const (char) **_r = _res; *_r; _r++) 958 res ~= to!string(*_r); 959 960 return res; 961 } 962 963 /* Btree/Recno Configuration */ 964 965 private 966 { 967 int function(Db db, Dbt *data, db_recno_t recno) db_append_recno_callback_refer; 968 969 extern (C) static int db_append_recno_callback(DB *_db, DBT *_data, db_recno_t recno) 970 { 971 Db db = from_DB(_db); 972 Dbt *data = cast(Dbt *) _data; 973 return db.db_append_recno_callback_refer(db, data, recno); 974 } 975 } 976 977 void set_append_recno(int function(Db db, Dbt *data, db_recno_t recno) db_append_recno_fcn) 978 { 979 if (opened < 0) { 980 throw new DbWrongUsingException("Operation on closed Db"); 981 } 982 if (opened > 0) { 983 throw new DbWrongUsingException("Configuration of opened Db"); 984 } 985 db_append_recno_callback_refer = db_append_recno_fcn; 986 auto ret = db.set_append_recno(db, db_append_recno_fcn?&db_append_recno_callback:null); 987 DbRetCodeToException(ret, dbenv); 988 assert(ret == 0); 989 } 990 991 private 992 { 993 version(VERSION_6) 994 { 995 int function(Db db, const (Dbt) *dbt1, const (Dbt) *dbt2, size_t *locp) bt_compare_callback_refer; 996 997 extern (C) static int bt_compare_callback(DB *_db, const (DBT) *_dbt1, const (DBT) *_dbt2, size_t *locp) 998 { 999 Db db = from_DB(_db); 1000 const (Dbt) *dbt1 = cast(const (Dbt) *) _dbt1; 1001 const (Dbt) *dbt2 = cast(const (Dbt) *) _dbt2; 1002 return db.bt_compare_callback_refer(db, dbt1, dbt2, locp); 1003 } 1004 alias int function(Db db, const (Dbt) *dbt1, const (Dbt) *dbt2, size_t *locp) bt_compare_fcn_t; 1005 } 1006 else 1007 { 1008 int function(Db db, const (Dbt) *dbt1, const (Dbt) *dbt2) bt_compare_callback_refer; 1009 1010 extern (C) static int bt_compare_callback(DB *_db, const (DBT) *_dbt1, const (DBT) *_dbt2) 1011 { 1012 Db db = from_DB(_db); 1013 const (Dbt) *dbt1 = cast(const (Dbt) *) _dbt1; 1014 const (Dbt) *dbt2 = cast(const (Dbt) *) _dbt2; 1015 return db.bt_compare_callback_refer(db, dbt1, dbt2); 1016 } 1017 alias int function(Db db, const (Dbt) *dbt1, const (Dbt) *dbt2) bt_compare_fcn_t; 1018 } 1019 } 1020 1021 void set_bt_compare(bt_compare_fcn_t bt_compare_fcn) 1022 { 1023 if (opened < 0) { 1024 throw new DbWrongUsingException("Operation on closed Db"); 1025 } 1026 if (opened > 0) { 1027 throw new DbWrongUsingException("Configuration of opened Db"); 1028 } 1029 bt_compare_callback_refer = bt_compare_fcn; 1030 auto ret = db.set_bt_compare(db, bt_compare_fcn?&bt_compare_callback:null); 1031 DbRetCodeToException(ret, dbenv); 1032 assert(ret == 0); 1033 } 1034 1035 private 1036 { 1037 int function(Db db, const (Dbt) *prevKey, 1038 const (Dbt) *prevData, const (Dbt) *key, const (Dbt) *data, 1039 Dbt *dest) bt_compress_callback_refer; 1040 1041 extern (C) static int bt_compress_callback(DB *_db, const (DBT) *_prevKey, 1042 const (DBT) *_prevData, const (DBT) *_key, const (DBT) *_data, DBT *_dest) 1043 { 1044 Db db = from_DB(_db); 1045 const (Dbt) *prevKey = cast(const (Dbt) *) _prevKey; 1046 const (Dbt) *prevData = cast(const (Dbt) *) _prevData; 1047 const (Dbt) *key = cast(const (Dbt) *) _key; 1048 const (Dbt) *data = cast(const (Dbt) *) _data; 1049 Dbt *dest = cast(Dbt *) _dest; 1050 return db.bt_compress_callback_refer(db, prevKey, prevData, key, data, dest); 1051 } 1052 1053 int function(Db db, const (Dbt) *prevKey, 1054 const (Dbt) *prevData, Dbt *compressed, Dbt *destKey, 1055 Dbt *destData) bt_decompress_callback_refer; 1056 1057 extern (C) static int bt_decompress_callback(DB *_db, const (DBT) *_prevKey, 1058 const (DBT) *_prevData, DBT *_compressed, DBT *_destKey, 1059 DBT *_destData) 1060 { 1061 Db db = from_DB(_db); 1062 const (Dbt) *prevKey = cast(const (Dbt) *) _prevKey; 1063 const (Dbt) *prevData = cast(const (Dbt) *) _prevData; 1064 Dbt *compressed = cast(Dbt *) _compressed; 1065 Dbt *destKey = cast(Dbt *) _destKey; 1066 Dbt *destData = cast(Dbt *) _destData; 1067 return db.bt_decompress_callback_refer(db, prevKey, prevData, 1068 compressed, destKey, destData); 1069 } 1070 } 1071 1072 void set_bt_compress(int function(Db db, const (Dbt) *prevKey, const (Dbt) *prevData, 1073 const (Dbt) *key, const (Dbt) *data, Dbt *dest) bt_compress_fcn, 1074 int function(Db db, const (Dbt) *prevKey, 1075 const (Dbt) *prevData, Dbt *compressed, Dbt *destKey, 1076 Dbt *destData) bt_decompress_fcn) 1077 { 1078 if (opened < 0) { 1079 throw new DbWrongUsingException("Operation on closed Db"); 1080 } 1081 if (opened > 0) { 1082 throw new DbWrongUsingException("Configuration of opened Db"); 1083 } 1084 bt_compress_callback_refer = bt_compress_fcn; 1085 bt_decompress_callback_refer = bt_decompress_fcn; 1086 auto ret = db.set_bt_compress(db, 1087 bt_compress_fcn?&bt_compress_callback:null, 1088 bt_decompress_fcn?&bt_decompress_callback:null); 1089 DbRetCodeToException(ret, dbenv); 1090 assert(ret == 0); 1091 } 1092 1093 void set_bt_minkey(uint32_t bt_minkey) 1094 { 1095 if (opened < 0) { 1096 throw new DbWrongUsingException("Operation on closed Db"); 1097 } 1098 if (opened > 0) { 1099 throw new DbWrongUsingException("Configuration of opened Db"); 1100 } 1101 auto ret = db.set_bt_minkey(db, bt_minkey); 1102 DbRetCodeToException(ret, dbenv); 1103 assert(ret == 0); 1104 } 1105 1106 uint32_t get_bt_minkey() 1107 { 1108 if (opened < 0) { 1109 throw new DbWrongUsingException("Get configuration on closed Db"); 1110 } 1111 uint32_t res; 1112 auto ret = db.get_bt_minkey(db, &res); 1113 DbRetCodeToException(ret, dbenv); 1114 assert(ret == 0); 1115 return res; 1116 } 1117 1118 private 1119 { 1120 size_t function(Db, const (Dbt) *dbt1, const (Dbt) *dbt2) bt_prefix_callback_refer; 1121 1122 extern (C) static size_t bt_prefix_callback(DB *_db, const (DBT) *_dbt1, const (DBT) *_dbt2) 1123 { 1124 Db db = from_DB(_db); 1125 const (Dbt) *dbt1 = cast(const (Dbt) *) _dbt1; 1126 const (Dbt) *dbt2 = cast(const (Dbt) *) _dbt2; 1127 return db.bt_prefix_callback_refer(db, dbt1, dbt2); 1128 } 1129 } 1130 1131 void set_bt_prefix(size_t function(Db, const (Dbt) *dbt1, const (Dbt) *dbt2) bt_prefix_fcn) 1132 { 1133 if (opened < 0) { 1134 throw new DbWrongUsingException("Operation on closed Db"); 1135 } 1136 if (opened > 0) { 1137 throw new DbWrongUsingException("Configuration of opened Db"); 1138 } 1139 bt_prefix_callback_refer = bt_prefix_fcn; 1140 auto ret = db.set_bt_prefix(db, &bt_prefix_callback); 1141 DbRetCodeToException(ret, dbenv); 1142 assert(ret == 0); 1143 } 1144 1145 void set_re_delim(int re_delim) 1146 { 1147 if (opened < 0) { 1148 throw new DbWrongUsingException("Operation on closed Db"); 1149 } 1150 if (opened > 0) { 1151 throw new DbWrongUsingException("Configuration of opened Db"); 1152 } 1153 auto ret = db.set_re_delim(db, re_delim); 1154 DbRetCodeToException(ret, dbenv); 1155 assert(ret == 0); 1156 } 1157 1158 int get_re_delim() 1159 { 1160 if (opened <= 0) { 1161 throw new DbWrongUsingException("Get configuration on closed or not opened Db"); 1162 } 1163 int res; 1164 auto ret = db.get_re_delim(db, &res); 1165 DbRetCodeToException(ret, dbenv); 1166 assert(ret == 0); 1167 return res; 1168 } 1169 1170 void set_re_len(uint32_t re_len) 1171 { 1172 if (opened < 0) { 1173 throw new DbWrongUsingException("Operation on closed Db"); 1174 } 1175 if (opened > 0) { 1176 throw new DbWrongUsingException("Configuration of opened Db"); 1177 } 1178 auto ret = db.set_re_len(db, re_len); 1179 DbRetCodeToException(ret, dbenv); 1180 assert(ret == 0); 1181 } 1182 1183 uint32_t get_re_len() 1184 { 1185 if (opened <= 0) { 1186 throw new DbWrongUsingException("Get configuration on closed or not opened Db"); 1187 } 1188 uint32_t res; 1189 auto ret = db.get_re_len(db, &res); 1190 DbRetCodeToException(ret, dbenv); 1191 assert(ret == 0); 1192 return res; 1193 } 1194 1195 void set_re_pad(int re_pad) 1196 { 1197 if (opened < 0) { 1198 throw new DbWrongUsingException("Operation on closed Db"); 1199 } 1200 if (opened > 0) { 1201 throw new DbWrongUsingException("Configuration of opened Db"); 1202 } 1203 auto ret = db.set_re_pad(db, re_pad); 1204 DbRetCodeToException(ret, dbenv); 1205 assert(ret == 0); 1206 } 1207 1208 int get_re_pad() 1209 { 1210 if (opened <= 0) { 1211 throw new DbWrongUsingException("Get configuration on closed or not opened Db"); 1212 } 1213 int res; 1214 auto ret = db.get_re_pad(db, &res); 1215 DbRetCodeToException(ret, dbenv); 1216 assert(ret == 0); 1217 return res; 1218 } 1219 1220 void set_re_source(string source) 1221 { 1222 if (opened < 0) { 1223 throw new DbWrongUsingException("Operation on closed Db"); 1224 } 1225 if (opened > 0) { 1226 throw new DbWrongUsingException("Configuration of opened Db"); 1227 } 1228 auto ret = db.set_re_source(db, source.toStringz()); 1229 DbRetCodeToException(ret, dbenv); 1230 assert(ret == 0); 1231 } 1232 1233 string get_re_source() 1234 { 1235 if (opened <= 0) { 1236 throw new DbWrongUsingException("Get configuration on closed or not opened Db"); 1237 } 1238 const (char) *res; 1239 auto ret = db.get_re_source(db, &res); 1240 DbRetCodeToException(ret, dbenv); 1241 assert(ret == 0); 1242 return to!string(res); 1243 } 1244 1245 /* Hash Configuration */ 1246 private 1247 { 1248 version(VERSION_6) 1249 { 1250 int function(Db db, const (Dbt) *dbt1, 1251 const (Dbt) *dbt2, size_t *locp) compare_callback_refer; 1252 1253 extern (C) static int compare_callback(DB *_db, 1254 const (DBT) *_dbt1, const (DBT) *_dbt2, size_t *locp) 1255 { 1256 Db db = from_DB(_db); 1257 const (Dbt) *dbt1 = cast(const (Dbt) *) _dbt1; 1258 const (Dbt) *dbt2 = cast(const (Dbt) *) _dbt2; 1259 return db.compare_callback_refer(db, dbt1, dbt2, locp); 1260 } 1261 1262 alias int function(Db db, const (Dbt) *dbt1, const (Dbt) *dbt2, size_t *locp) compare_fcn_t; 1263 } 1264 else 1265 { 1266 int function(Db db, const (Dbt) *dbt1, 1267 const (Dbt) *dbt2) compare_callback_refer; 1268 1269 extern (C) static int compare_callback(DB *_db, 1270 const (DBT) *_dbt1, const (DBT) *_dbt2) 1271 { 1272 Db db = from_DB(_db); 1273 const (Dbt) *dbt1 = cast(const (Dbt) *) _dbt1; 1274 const (Dbt) *dbt2 = cast(const (Dbt) *) _dbt2; 1275 return db.compare_callback_refer(db, dbt1, dbt2); 1276 } 1277 1278 alias int function(Db db, const (Dbt) *dbt1, const (Dbt) *dbt2) compare_fcn_t; 1279 } 1280 } 1281 1282 void set_h_compare(compare_fcn_t compare_fcn) 1283 { 1284 if (opened < 0) { 1285 throw new DbWrongUsingException("Operation on closed Db"); 1286 } 1287 if (opened > 0) { 1288 throw new DbWrongUsingException("Configuration of opened Db"); 1289 } 1290 compare_callback_refer = compare_fcn; 1291 auto ret = db.set_h_compare(db, compare_fcn?&compare_callback:null); 1292 DbRetCodeToException(ret, dbenv); 1293 assert(ret == 0); 1294 } 1295 1296 void set_h_ffactor(uint32_t h_ffactor) 1297 { 1298 if (opened < 0) { 1299 throw new DbWrongUsingException("Operation on closed Db"); 1300 } 1301 if (opened > 0) { 1302 throw new DbWrongUsingException("Configuration of opened Db"); 1303 } 1304 auto ret = db.set_h_ffactor(db, h_ffactor); 1305 DbRetCodeToException(ret, dbenv); 1306 assert(ret == 0); 1307 } 1308 1309 uint32_t get_h_ffactor() 1310 { 1311 if (opened < 0) { 1312 throw new DbWrongUsingException("Get configuration on closed Db"); 1313 } 1314 uint32_t res; 1315 auto ret = db.get_h_ffactor(db, &res); 1316 DbRetCodeToException(ret, dbenv); 1317 assert(ret == 0); 1318 return res; 1319 } 1320 1321 private 1322 { 1323 uint32_t function(Db dbp, const (ubyte)[] bytes) h_hash_callback_refer; 1324 1325 extern (C) static uint32_t h_hash_callback(DB *_db, const (void) *_bytes, uint32_t length) 1326 { 1327 Db db = from_DB(_db); 1328 const (ubyte)[] bytes = (cast(ubyte*) _bytes)[0..length]; 1329 return db.h_hash_callback_refer(db, bytes); 1330 } 1331 } 1332 1333 void set_h_hash(uint32_t function(Db dbp, const (ubyte)[] bytes) h_hash_fcn) 1334 { 1335 if (opened < 0) { 1336 throw new DbWrongUsingException("Operation on closed Db"); 1337 } 1338 if (opened > 0) { 1339 throw new DbWrongUsingException("Configuration of opened Db"); 1340 } 1341 h_hash_callback_refer = h_hash_fcn; 1342 auto ret = db.set_h_hash(db, &h_hash_callback); 1343 DbRetCodeToException(ret, dbenv); 1344 assert(ret == 0); 1345 } 1346 1347 void set_h_nelem(uint32_t h_nelem) 1348 { 1349 if (opened < 0) { 1350 throw new DbWrongUsingException("Operation on closed Db"); 1351 } 1352 if (opened > 0) { 1353 throw new DbWrongUsingException("Configuration of opened Db"); 1354 } 1355 auto ret = db.set_h_nelem(db, h_nelem); 1356 DbRetCodeToException(ret, dbenv); 1357 assert(ret == 0); 1358 } 1359 1360 uint32_t get_h_nelem(uint32_t *h_nelemp) 1361 { 1362 if (opened < 0) { 1363 throw new DbWrongUsingException("Get configuration on closed Db"); 1364 } 1365 uint32_t res; 1366 auto ret = db.get_h_nelem(db, &res); 1367 DbRetCodeToException(ret, dbenv); 1368 assert(ret == 0); 1369 return res; 1370 } 1371 1372 /* Queue Configuration */ 1373 void set_q_extentsize(uint32_t extentsize) 1374 { 1375 if (opened < 0) { 1376 throw new DbWrongUsingException("Operation on closed Db"); 1377 } 1378 if (opened > 0) { 1379 throw new DbWrongUsingException("Configuration of opened Db"); 1380 } 1381 auto ret = db.set_q_extentsize(db, extentsize); 1382 DbRetCodeToException(ret, dbenv); 1383 assert(ret == 0); 1384 } 1385 1386 uint32_t get_q_extentsize() 1387 { 1388 if (opened <= 0) { 1389 throw new DbWrongUsingException("Get configuration on closed or not opened Db"); 1390 } 1391 uint32_t res; 1392 auto ret = db.get_q_extentsize(db, &res); 1393 DbRetCodeToException(ret, dbenv); 1394 assert(ret == 0); 1395 return res; 1396 } 1397 1398 /* Heap */ 1399 void set_heapsize(uint32_t gbytes, uint32_t bytes, uint32_t flags = 0) 1400 { 1401 if (opened < 0) { 1402 throw new DbWrongUsingException("Operation on closed Db"); 1403 } 1404 if (opened > 0) { 1405 throw new DbWrongUsingException("Configuration of opened Db"); 1406 } 1407 auto ret = db.set_heapsize(db, gbytes, bytes, flags); 1408 DbRetCodeToException(ret, dbenv); 1409 assert(ret == 0); 1410 } 1411 1412 void set_heapsize(uint64_t bytes, uint32_t flags = 0) 1413 { 1414 uint32_t _gbytes = cast(uint32_t) bytes/(1024*1024*1024); 1415 uint32_t _bytes = bytes%(1024*1024*1024); 1416 set_heapsize(_gbytes, _bytes, flags); 1417 } 1418 1419 void get_heapsize(ref uint32_t gbytes, ref uint32_t bytes) 1420 { 1421 if (opened <= 0) { 1422 throw new DbWrongUsingException("Get configuration on closed or not opened Db"); 1423 } 1424 auto ret = db.get_heapsize(db, &gbytes, &bytes); 1425 DbRetCodeToException(ret, dbenv); 1426 assert(ret == 0); 1427 } 1428 1429 uint64_t get_heapsize() 1430 { 1431 uint32_t _gbytes; 1432 uint32_t _bytes; 1433 get_heapsize(_gbytes, _bytes); 1434 return (1024UL*1024*1024)*_gbytes + _bytes; 1435 } 1436 1437 void set_heap_regionsize(uint32_t npages) 1438 { 1439 if (opened < 0) { 1440 throw new DbWrongUsingException("Operation on closed Db"); 1441 } 1442 if (opened > 0) { 1443 throw new DbWrongUsingException("Configuration of opened Db"); 1444 } 1445 auto ret = db.set_heap_regionsize(db, npages); 1446 DbRetCodeToException(ret, dbenv); 1447 assert(ret == 0); 1448 } 1449 1450 uint32_t get_heap_regionsize() 1451 { 1452 if (opened <= 0) { 1453 throw new DbWrongUsingException("Get configuration on closed or not opened Db"); 1454 } 1455 uint32_t res; 1456 auto ret = db.get_heap_regionsize(db, &res); 1457 DbRetCodeToException(ret, dbenv); 1458 assert(ret == 0); 1459 return res; 1460 } 1461 1462 /* Memory Pools and Related Methods */ 1463 DbMpoolfile get_mpf() 1464 { 1465 if (opened < 0) { 1466 throw new DbWrongUsingException("Operation on closed Db"); 1467 } 1468 DB_MPOOLFILE *res = db.get_mpf(db); 1469 return new DbMpoolfile(res, dbenv); 1470 } 1471 1472 /* Transaction Subsystem Configuration */ 1473 int get_transactional() 1474 { 1475 if (opened < 0) { 1476 throw new DbWrongUsingException("Operation on closed Db"); 1477 } 1478 return db.get_transactional(db); 1479 } 1480 1481 /* BLOB Configuration */ 1482 version(VERSION_6) 1483 { 1484 void set_blob_dir(string dir) 1485 { 1486 if (opened < 0) { 1487 throw new DbWrongUsingException("Configuration on closed Db"); 1488 } 1489 if (opened > 0) { 1490 throw new DbWrongUsingException("Configuration of opened Db"); 1491 } 1492 auto ret = db.set_blob_dir(db, dir.toStringz()); 1493 DbRetCodeToException(ret, dbenv); 1494 assert(ret == 0); 1495 } 1496 1497 string get_blob_dir() 1498 { 1499 if (opened < 0) { 1500 throw new DbWrongUsingException("Get configuration on closed Db"); 1501 } 1502 const (char) *res; 1503 auto ret = db.get_blob_dir(db, &res); 1504 DbRetCodeToException(ret, dbenv); 1505 assert(ret == 0); 1506 return to!string(res); 1507 } 1508 1509 void set_blob_threshold(uint32_t bytes, uint32_t flags = 0) 1510 { 1511 if (opened < 0) { 1512 throw new DbWrongUsingException("Configuration on closed Db"); 1513 } 1514 if (opened > 0) { 1515 throw new DbWrongUsingException("Configuration of opened Db"); 1516 } 1517 auto ret = db.set_blob_threshold(db, bytes, flags); 1518 DbRetCodeToException(ret, dbenv); 1519 assert(ret == 0); 1520 } 1521 1522 uint32_t get_blob_threshold() 1523 { 1524 if (opened < 0) { 1525 throw new DbWrongUsingException("Get configuration on closed Db"); 1526 } 1527 uint32_t res; 1528 auto ret = db.get_blob_threshold(db, &res); 1529 DbRetCodeToException(ret, dbenv); 1530 assert(ret == 0); 1531 return res; 1532 } 1533 } 1534 } 1535 1536 void db_copy(DbEnv dbenv, string dbfile, string target, 1537 string password) 1538 { 1539 if (dbenv._opened < 0) { 1540 throw new DbWrongUsingException("Operation on closed DbEnv"); 1541 } 1542 auto ret = berkeleydb.c.db_copy(dbenv?dbenv._DB_ENV:null, dbfile.toStringz(), 1543 target.toStringz(), password.toStringz()); 1544 DbRetCodeToException(ret, dbenv); 1545 assert(ret == 0); 1546 } 1547 1548 unittest 1549 { 1550 auto db = new Db(null, 0); 1551 db.set_partition_dirs(["a", "b", "d"]); 1552 assert(db.get_partition_dirs() == ["a", "b", "d"]); 1553 } 1554 1555 unittest 1556 { 1557 import std.file; 1558 1559 try{ 1560 rmdirRecurse("/tmp/berkeleydb.test"); 1561 } catch (FileException file) 1562 { 1563 } 1564 1565 try{ 1566 mkdir("/tmp/berkeleydb.test"); 1567 } catch (FileException file) 1568 { 1569 } 1570 1571 struct customer { 1572 char[4] cust_id; 1573 char[15] last_name; 1574 char[15] first_name; 1575 } 1576 struct order { 1577 char[4] order_id; 1578 int order_number; 1579 char[4] cust_id; 1580 } 1581 1582 DbEnv dbenv = new DbEnv(0); 1583 1584 uint32_t env_flags = DB_CREATE | /* Create the environment if it does 1585 * not already exist. */ 1586 DB_INIT_TXN | /* Initialize transactions */ 1587 DB_INIT_LOCK | /* Initialize locking. */ 1588 DB_INIT_LOG | /* Initialize logging */ 1589 DB_INIT_MPOOL; /* Initialize the in-memory cache. */ 1590 1591 dbenv.open("/tmp/berkeleydb.test/", env_flags, octal!666); 1592 1593 Db db = new Db(dbenv, 0); 1594 db.open(null, "orders.db", null, DB_BTREE, DB_CREATE, octal!600); 1595 1596 Db sdb = new Db(dbenv, 0); 1597 sdb.set_flags(DB_DUP | DB_DUPSORT); 1598 1599 sdb.open(null, "orders_cust_ids.db", null, DB_BTREE, DB_CREATE, octal!600); 1600 1601 static int getcustid(Db secondary, ref const (Dbt) pkey, ref const (Dbt) pdata, out Dbt skey) 1602 { 1603 /* 1604 * Since the secondary key is a simple structure member of the 1605 * record, we don't have to do anything fancy to return it. If 1606 * we have composite keys that need to be constructed from the 1607 * record, rather than simply pointing into it, then the user's 1608 * function might need to allocate space and copy data. In 1609 * this case, the DB_DBT_APPMALLOC flag should be set in the 1610 * secondary key DBT. 1611 */ 1612 const order *o = pdata.to!(const order *)(); 1613 skey = o.cust_id; 1614 return 0; 1615 } 1616 1617 db.associate(null, sdb, &getcustid, 0); 1618 1619 Db fdb = new Db(dbenv, 0); 1620 fdb.open(null, "customers.db", null, DB_BTREE, DB_CREATE, octal!600); 1621 fdb.associate_foreign(sdb, null, DB_FOREIGN_CASCADE); 1622 1623 string PadString(string str, int len) 1624 { 1625 while (str.length < len) 1626 str ~= '\0'; 1627 return str; 1628 } 1629 1630 Dbt key, data; 1631 customer cust; 1632 cust.cust_id = "0001"; 1633 cust.last_name = PadString("Last", 15); 1634 cust.first_name = PadString("First", 15); 1635 key = cust.cust_id; 1636 data = cust; 1637 int res = fdb.put(null, &key, &data, 0); 1638 assert(res == 0); 1639 1640 cust.cust_id = "0002"; 1641 cust.last_name = PadString("Petrov", 15); 1642 cust.first_name = PadString("Ivan", 15); 1643 res = fdb.put(null, &key, &data, 0); 1644 assert(res == 0); 1645 1646 cust.cust_id = "0003"; 1647 cust.last_name = PadString("Smeyana", 15); 1648 cust.first_name = PadString("Lena", 15); 1649 res = fdb.put(null, &key, &data, 0); 1650 assert(res == 0); 1651 1652 order ord; 1653 ord.order_id = "0001"; 1654 ord.order_number = 1; 1655 ord.cust_id = "0001"; 1656 key = ord.order_id; 1657 data = ord; 1658 res = db.put(null, &key, &data, 0); 1659 assert(res == 0); 1660 1661 ord.order_id = "0002"; 1662 ord.order_number = 2; 1663 ord.cust_id = "0001"; 1664 res = db.put(null, &key, &data, 0); 1665 assert(res == 0); 1666 1667 ord.order_id = "0003"; 1668 ord.order_number = 3; 1669 ord.cust_id = "0002"; 1670 res = db.put(null, &key, &data, 0); 1671 assert(res == 0); 1672 1673 ord.order_id = "0004"; 1674 ord.order_number = 4; 1675 ord.cust_id = "0005"; 1676 int except = 0; 1677 try 1678 { 1679 res = db.put(null, &key, &data, 0); 1680 assert(res == 0); 1681 } 1682 catch (DbException exc) 1683 { 1684 assert(exc.dberrno == DB_FOREIGN_CONFLICT); 1685 except = 1; 1686 } 1687 assert(except == 1); 1688 1689 Dbc cursor = fdb.cursor(null, 0); 1690 res = cursor.get(&key, &data, DB_NEXT); 1691 assert(res == 0); 1692 cust.cust_id = "0001"; 1693 cust.last_name = PadString("Last", 15); 1694 cust.first_name = PadString("First", 15); 1695 char[4] cust_key = key.to!(char[])(); 1696 customer *cust_p = data.to!(customer*)(); 1697 assert(cust_key == cust.cust_id); 1698 assert(*cust_p == cust); 1699 1700 res = cursor.get(&key, &data, DB_NEXT); 1701 assert(res == 0); 1702 cust.cust_id = "0002"; 1703 cust.last_name = PadString("Petrov", 15); 1704 cust.first_name = PadString("Ivan", 15); 1705 cust_key = key.to!(char[])(); 1706 cust_p = data.to!(customer*)(); 1707 assert(cust_key == cust.cust_id); 1708 assert(*cust_p == cust); 1709 1710 res = cursor.get(&key, &data, DB_NEXT); 1711 assert(res == 0); 1712 cust.cust_id = "0003"; 1713 cust.last_name = PadString("Smeyana", 15); 1714 cust.first_name = PadString("Lena", 15); 1715 cust_key = key.to!(char[])(); 1716 cust_p = data.to!(customer*)(); 1717 assert(cust_key == cust.cust_id); 1718 assert(*cust_p == cust); 1719 1720 res = cursor.get(&key, &data, DB_NEXT); 1721 assert(res == DB_NOTFOUND); 1722 1723 cursor.close(); 1724 fdb.close(0); 1725 sdb.close(0); 1726 db.close(0); 1727 1728 dbenv.close(0); 1729 }