github.com/moontrade/mdbx-go@v0.4.0/mdbx.go (about) 1 package mdbx 2 3 /* 4 //#cgo !windows CFLAGS: -O2 -g -DMDBX_BUILD_FLAGS='' -DMDBX_DEBUG=0 -DNDEBUG=1 -DMDBX_FORCE_ASSERTIONS=1 -std=gnu11 -fvisibility=hidden -ffast-math -fPIC -pthread -Wno-error=attributes -W -Wall -Werror -Wextra -Wpedantic -Wno-deprecated-declarations -Wno-format -Wno-implicit-fallthrough -Wno-unused-parameter -Wno-format-extra-args -Wno-missing-field-initializers 5 #cgo !windows CFLAGS: -O2 -g -DMDBX_BUILD_FLAGS='' -DMDBX_DEBUG=0 -DNDEBUG=1 -fPIC -ffast-math -std=gnu11 -fvisibility=hidden -pthread 6 #cgo linux LDFLAGS: -lrt 7 8 #include <stdlib.h> 9 #include <string.h> 10 #include <inttypes.h> 11 #include "mdbx.h" 12 #include "mdbx_utils.h" 13 14 #ifndef likely 15 # if (defined(__GNUC__) || __has_builtin(__builtin_expect)) && !defined(__COVERITY__) 16 # define likely(cond) __builtin_expect(!!(cond), 1) 17 # else 18 # define likely(x) (!!(x)) 19 # endif 20 #endif 21 22 #ifndef unlikely 23 # if (defined(__GNUC__) || __has_builtin(__builtin_expect)) && !defined(__COVERITY__) 24 # define unlikely(cond) __builtin_expect(!!(cond), 0) 25 # else 26 # define unlikely(x) (!!(x)) 27 # endif 28 #endif 29 30 static int cmp_lexical(const MDBX_val *a, const MDBX_val *b) { 31 if (a->iov_len == b->iov_len) 32 return a->iov_len ? memcmp(a->iov_base, b->iov_base, a->iov_len) : 0; 33 34 const int diff_len = (a->iov_len < b->iov_len) ? -1 : 1; 35 const size_t shortest = (a->iov_len < b->iov_len) ? a->iov_len : b->iov_len; 36 int diff_data = shortest ? memcmp(a->iov_base, b->iov_base, shortest) : 0; 37 return likely(diff_data) ? diff_data : diff_len; 38 } 39 40 int mdbx_cmp_u16(const MDBX_val *a, const MDBX_val *b) { 41 if (unlikely(a->iov_len < 2 || b->iov_len < 2)) { 42 return cmp_lexical(a, b); 43 } 44 uint16_t aa = *((uint16_t*)a->iov_base); 45 uint16_t bb = *((uint16_t*)b->iov_base); 46 return bb > aa ? -1 : aa > bb; 47 } 48 49 int mdbx_cmp_u32(const MDBX_val *a, const MDBX_val *b) { 50 if (unlikely(a->iov_len < 4 || b->iov_len < 4)) { 51 return cmp_lexical(a, b); 52 } 53 uint32_t aa = *((uint32_t*)a->iov_base); 54 uint32_t bb = *((uint32_t*)b->iov_base); 55 return bb > aa ? -1 : aa > bb; 56 } 57 58 int mdbx_cmp_u64(const MDBX_val *a, const MDBX_val *b) { 59 if (unlikely(a->iov_len < 8 || b->iov_len < 8)) { 60 return cmp_lexical(a, b); 61 } 62 uint64_t aa = *((uint64_t*)a->iov_base); 63 uint64_t bb = *((uint64_t*)b->iov_base); 64 return bb > aa ? -1 : aa > bb; 65 } 66 67 int mdbx_cmp_u16_prefix_lexical(const MDBX_val *a, const MDBX_val *b) { 68 if (unlikely(a->iov_len < 2 || b->iov_len < 2)) { 69 return cmp_lexical(a, b); 70 } 71 uint16_t aa = *((uint16_t*)a->iov_base); 72 uint16_t bb = *((uint16_t*)a->iov_base); 73 if (aa < bb) { 74 return -1; 75 } 76 if (aa > bb) { 77 return 1; 78 } 79 if (a->iov_len == b->iov_len) 80 return a->iov_len ? memcmp(a->iov_base+2, b->iov_base+2, a->iov_len-2) : 0; 81 82 const int diff_len = (a->iov_len < b->iov_len) ? -1 : 1; 83 const size_t shortest = (a->iov_len < b->iov_len) ? a->iov_len : b->iov_len; 84 int diff_data = shortest ? memcmp(a->iov_base+2, b->iov_base+2, shortest-2) : 0; 85 return likely(diff_data) ? diff_data : diff_len; 86 } 87 88 int mdbx_cmp_u16_prefix_u64(const MDBX_val *a, const MDBX_val *b) { 89 if (unlikely(a->iov_len < 10 || b->iov_len < 10)) { 90 return cmp_lexical(a, b); 91 } 92 uint16_t aa = *((uint16_t*)a->iov_base); 93 uint16_t bb = *((uint16_t*)a->iov_base); 94 if (aa < bb) return -1; 95 if (aa > bb) return 1; 96 uint64_t aa2 = *((uint64_t*)a->iov_base+2); 97 uint64_t bb2 = *((uint64_t*)b->iov_base+2); 98 if (aa2 < bb2) return -1; 99 if (aa2 > bb2) return 1; 100 return 0; 101 } 102 103 int mdbx_cmp_u32_prefix_u64_dup_lexical(const MDBX_val *a, const MDBX_val *b) { 104 if (unlikely(a->iov_len < 12 || b->iov_len < 12)) { 105 return cmp_lexical(a, b); 106 } 107 uint32_t aa = *((uint32_t*)a->iov_base); 108 uint32_t bb = *((uint32_t*)a->iov_base); 109 if (aa < bb) { 110 return -1; 111 } 112 if (aa > bb) { 113 return 1; 114 } 115 if (a->iov_len == b->iov_len) { 116 int result = a->iov_len ? memcmp(a->iov_base+12, b->iov_base+12, a->iov_len-12) : 0; 117 if (result != 0) return result; 118 119 uint64_t aaa = *((uint64_t*)a->iov_base+4); 120 uint64_t bbb = *((uint64_t*)a->iov_base+4); 121 if (aaa < bbb) { 122 return -1; 123 } 124 if (aaa > bbb) { 125 return 1; 126 } 127 return 0; 128 } 129 130 const int diff_len = (a->iov_len < b->iov_len) ? -1 : 1; 131 const size_t shortest = (a->iov_len < b->iov_len) ? a->iov_len : b->iov_len; 132 int diff_data = shortest ? memcmp(a->iov_base+12, b->iov_base+12, shortest-12) : 0; 133 return likely(diff_data) ? diff_data : diff_len; 134 } 135 136 int mdbx_cmp_u64_prefix_u64_dup_lexical(const MDBX_val *a, const MDBX_val *b) { 137 if (unlikely(a->iov_len < 16 || b->iov_len < 16)) { 138 return cmp_lexical(a, b); 139 } 140 uint32_t aa = *((uint32_t*)a->iov_base); 141 uint32_t bb = *((uint32_t*)a->iov_base); 142 if (aa < bb) { 143 return -1; 144 } 145 if (aa > bb) { 146 return 1; 147 } 148 if (a->iov_len == b->iov_len) { 149 int result = a->iov_len ? memcmp(a->iov_base+16, b->iov_base+16, a->iov_len-16) : 0; 150 if (result != 0) return result; 151 152 uint64_t aaa = *((uint64_t*)a->iov_base+8); 153 uint64_t bbb = *((uint64_t*)a->iov_base+8); 154 if (aaa < bbb) { 155 return -1; 156 } 157 if (aaa > bbb) { 158 return 1; 159 } 160 return 0; 161 } 162 163 const int diff_len = (a->iov_len < b->iov_len) ? -1 : 1; 164 const size_t shortest = (a->iov_len < b->iov_len) ? a->iov_len : b->iov_len; 165 int diff_data = shortest ? memcmp(a->iov_base+16, b->iov_base+16, shortest-16) : 0; 166 return likely(diff_data) ? diff_data : diff_len; 167 } 168 169 int mdbx_cmp_u32_prefix_u64_dup_u64(const MDBX_val *a, const MDBX_val *b) { 170 if (unlikely(a->iov_len < 20 || b->iov_len < 20)) { 171 return cmp_lexical(a, b); 172 } 173 uint32_t aa = *((uint32_t*)a->iov_base); 174 uint32_t bb = *((uint32_t*)a->iov_base); 175 if (aa < bb) { 176 return -1; 177 } 178 if (aa > bb) { 179 return 1; 180 } 181 uint64_t av = *((uint64_t*)a->iov_base+12); 182 uint64_t bv = *((uint64_t*)a->iov_base+12); 183 if (av < bv) { 184 return -1; 185 } 186 if (av > bv) { 187 return 1; 188 } 189 av = *((uint64_t*)a->iov_base+4); 190 bv = *((uint64_t*)a->iov_base+4); 191 if (av < bv) { 192 return -1; 193 } 194 if (av > bv) { 195 return 1; 196 } 197 return 0; 198 } 199 200 int mdbx_cmp_u64_prefix_u64_dup_u64(const MDBX_val *a, const MDBX_val *b) { 201 if (unlikely(a->iov_len < 24 || b->iov_len < 24)) { 202 return cmp_lexical(a, b); 203 } 204 uint32_t aa = *((uint32_t*)a->iov_base); 205 uint32_t bb = *((uint32_t*)a->iov_base); 206 if (aa < bb) { 207 return -1; 208 } 209 if (aa > bb) { 210 return 1; 211 } 212 uint64_t av = *((uint64_t*)a->iov_base+16); 213 uint64_t bv = *((uint64_t*)a->iov_base+16); 214 if (av < bv) { 215 return -1; 216 } 217 if (av > bv) { 218 return 1; 219 } 220 av = *((uint64_t*)a->iov_base+8); 221 bv = *((uint64_t*)a->iov_base+8); 222 if (av < bv) { 223 return -1; 224 } 225 if (av > bv) { 226 return 1; 227 } 228 return 0; 229 } 230 231 int mdbx_cmp_u32_prefix_lexical(const MDBX_val *a, const MDBX_val *b) { 232 if (unlikely(a->iov_len < 4 || b->iov_len < 4)) { 233 return cmp_lexical(a, b); 234 } 235 uint32_t aa = *((uint32_t*)a->iov_base); 236 uint32_t bb = *((uint32_t*)a->iov_base); 237 if (aa < bb) { 238 return -1; 239 } 240 if (aa > bb) { 241 return 1; 242 } 243 if (a->iov_len == b->iov_len) 244 return a->iov_len ? memcmp(a->iov_base+4, b->iov_base+4, a->iov_len-4) : 0; 245 246 const int diff_len = (a->iov_len < b->iov_len) ? -1 : 1; 247 const size_t shortest = (a->iov_len < b->iov_len) ? a->iov_len : b->iov_len; 248 int diff_data = shortest ? memcmp(a->iov_base+4, b->iov_base+4, shortest-4) : 0; 249 return likely(diff_data) ? diff_data : diff_len; 250 } 251 252 int mdbx_cmp_u32_prefix_u64(const MDBX_val *a, const MDBX_val *b) { 253 if (unlikely(a->iov_len < 12 || b->iov_len < 12)) { 254 return cmp_lexical(a, b); 255 } 256 uint32_t aa = *((uint32_t*)a->iov_base); 257 uint32_t bb = *((uint32_t*)a->iov_base); 258 if (aa < bb) return -1; 259 if (aa > bb) return 1; 260 uint64_t aa2 = *((uint64_t*)a->iov_base+4); 261 uint64_t bb2 = *((uint64_t*)b->iov_base+4); 262 if (aa2 < bb2) return -1; 263 if (aa2 > bb2) return 1; 264 return 0; 265 } 266 267 int mdbx_cmp_u64_prefix_lexical(const MDBX_val *a, const MDBX_val *b) { 268 if (unlikely(a->iov_len < 8 || b->iov_len < 8)) { 269 return cmp_lexical(a, b); 270 } 271 uint64_t aa = *((uint64_t*)a->iov_base); 272 uint64_t bb = *((uint64_t*)a->iov_base); 273 if (aa < bb) { 274 return -1; 275 } 276 if (aa > bb) { 277 return 1; 278 } 279 if (a->iov_len == b->iov_len) 280 return a->iov_len ? memcmp(a->iov_base+8, b->iov_base+8, a->iov_len-8) : 0; 281 282 const int diff_len = (a->iov_len < b->iov_len) ? -1 : 1; 283 const size_t shortest = (a->iov_len < b->iov_len) ? a->iov_len : b->iov_len; 284 int diff_data = shortest ? memcmp(a->iov_base+8, b->iov_base+8, shortest-8) : 0; 285 return likely(diff_data) ? diff_data : diff_len; 286 } 287 288 int mdbx_cmp_u64_prefix_u64(const MDBX_val *a, const MDBX_val *b) { 289 if (unlikely(a->iov_len < 16 || b->iov_len < 16)) { 290 return cmp_lexical(a, b); 291 } 292 uint64_t aa = *((uint32_t*)a->iov_base); 293 uint64_t bb = *((uint32_t*)a->iov_base); 294 if (aa < bb) return -1; 295 if (aa > bb) return 1; 296 aa = *((uint64_t*)a->iov_base+8); 297 bb = *((uint64_t*)b->iov_base+8); 298 if (aa < bb) return -1; 299 if (aa > bb) return 1; 300 return 0; 301 } 302 303 typedef struct mdbx_strerror_t { 304 size_t result; 305 int32_t code; 306 } mdbx_strerror_t; 307 308 void do_mdbx_strerror(size_t arg0, size_t arg1) { 309 mdbx_strerror_t* args = (mdbx_strerror_t*)(void*)arg0; 310 args->result = (size_t)(void*)mdbx_strerror((int)args->code); 311 } 312 313 typedef struct mdbx_env_set_geometry_t { 314 size_t env; 315 size_t size_lower; 316 size_t size_now; 317 size_t size_upper; 318 size_t growth_step; 319 size_t shrink_threshold; 320 size_t page_size; 321 int32_t result; 322 } mdbx_env_set_geometry_t; 323 324 void do_mdbx_env_set_geometry(size_t arg0, size_t arg1) { 325 mdbx_env_set_geometry_t* args = (mdbx_env_set_geometry_t*)(void*)arg0; 326 args->result = (int32_t)mdbx_env_set_geometry( 327 (MDBX_env*)(void*)args->env, 328 args->size_lower, 329 args->size_now, 330 args->size_upper, 331 args->growth_step, 332 args->shrink_threshold, 333 args->page_size 334 ); 335 } 336 337 typedef struct mdbx_env_info_t { 338 size_t env; 339 size_t txn; 340 size_t info; 341 size_t size; 342 int32_t result; 343 } mdbx_env_info_t; 344 345 void do_mdbx_env_info_ex(size_t arg0, size_t arg1) { 346 mdbx_env_info_t* args = (mdbx_env_info_t*)(void*)arg0; 347 args->result = (int32_t)mdbx_env_info_ex( 348 (MDBX_env*)(void*)args->env, 349 (MDBX_txn*)(void*)args->txn, 350 (MDBX_envinfo*)(void*)args->info, 351 args->size 352 ); 353 } 354 355 typedef struct mdbx_txn_info_t { 356 size_t txn; 357 size_t info; 358 int32_t scan_rlt; 359 int32_t result; 360 } mdbx_txn_info_t; 361 362 void do_mdbx_txn_info(size_t arg0, size_t arg1) { 363 mdbx_txn_info_t* args = (mdbx_txn_info_t*)(void*)arg0; 364 args->result = (int32_t)mdbx_txn_info( 365 (MDBX_txn*)(void*)args->txn, 366 (MDBX_txn_info*)(void*)args->info, 367 args->scan_rlt >= 0 368 ); 369 } 370 371 typedef struct mdbx_txn_flags_t { 372 size_t txn; 373 int32_t flags; 374 } mdbx_txn_flags_t; 375 376 void do_mdbx_txn_flags(size_t arg0, size_t arg1) { 377 mdbx_txn_flags_t* args = (mdbx_txn_flags_t*)(void*)arg0; 378 args->flags = (int32_t)mdbx_txn_flags( 379 (MDBX_txn*)(void*)args->txn 380 ); 381 } 382 383 typedef struct mdbx_txn_id_t { 384 size_t txn; 385 uint64_t id; 386 } mdbx_txn_id_t; 387 388 void do_mdbx_txn_id(size_t arg0, size_t arg1) { 389 mdbx_txn_id_t* args = (mdbx_txn_id_t*)(void*)arg0; 390 args->id = mdbx_txn_id( 391 (MDBX_txn*)(void*)args->txn 392 ); 393 } 394 395 typedef struct mdbx_txn_commit_ex_t { 396 size_t txn; 397 size_t latency; 398 int32_t result; 399 } mdbx_txn_commit_ex_t; 400 401 void do_mdbx_txn_commit_ex(size_t arg0, size_t arg1) { 402 mdbx_txn_commit_ex_t* args = (mdbx_txn_commit_ex_t*)(void*)arg0; 403 args->result = (int32_t)mdbx_txn_commit_ex( 404 (MDBX_txn*)(void*)args->txn, 405 (MDBX_commit_latency*)(void*)args->latency 406 ); 407 } 408 409 typedef struct mdbx_txn_result_t { 410 size_t txn; 411 int32_t result; 412 } mdbx_txn_result_t; 413 414 void do_mdbx_txn_abort(size_t arg0, size_t arg1) { 415 mdbx_txn_result_t* args = (mdbx_txn_result_t*)(void*)arg0; 416 args->result = (int32_t)mdbx_txn_abort( 417 (MDBX_txn*)(void*)args->txn 418 ); 419 } 420 421 void do_mdbx_txn_break(size_t arg0, size_t arg1) { 422 mdbx_txn_result_t* args = (mdbx_txn_result_t*)(void*)arg0; 423 args->result = (int32_t)mdbx_txn_break( 424 (MDBX_txn*)(void*)args->txn 425 ); 426 } 427 428 void do_mdbx_txn_reset(size_t arg0, size_t arg1) { 429 mdbx_txn_result_t* args = (mdbx_txn_result_t*)(void*)arg0; 430 args->result = (int32_t)mdbx_txn_reset( 431 (MDBX_txn*)(void*)args->txn 432 ); 433 } 434 435 void do_mdbx_txn_renew(size_t arg0, size_t arg1) { 436 mdbx_txn_result_t* args = (mdbx_txn_result_t*)(void*)arg0; 437 args->result = (int32_t)mdbx_txn_renew( 438 (MDBX_txn*)(void*)args->txn 439 ); 440 } 441 442 typedef struct mdbx_txn_canary_t { 443 size_t txn; 444 size_t canary; 445 int32_t result; 446 } mdbx_txn_canary_t; 447 448 void do_mdbx_canary_put(size_t arg0, size_t arg1) { 449 mdbx_txn_canary_t* args = (mdbx_txn_canary_t*)(void*)arg0; 450 args->result = (int32_t)mdbx_canary_put( 451 (MDBX_txn*)(void*)args->txn, 452 (MDBX_canary*)(void*)args->canary 453 ); 454 } 455 456 void do_mdbx_canary_get(size_t arg0, size_t arg1) { 457 mdbx_txn_canary_t* args = (mdbx_txn_canary_t*)(void*)arg0; 458 args->result = (int32_t)mdbx_canary_get( 459 (MDBX_txn*)(void*)args->txn, 460 (MDBX_canary*)(void*)args->canary 461 ); 462 } 463 464 typedef struct mdbx_dbi_stat_t { 465 size_t txn; 466 size_t stat; 467 size_t size; 468 uint32_t dbi; 469 int32_t result; 470 } mdbx_dbi_stat_t; 471 472 void do_mdbx_dbi_stat(size_t arg0, size_t arg1) { 473 mdbx_dbi_stat_t* args = (mdbx_dbi_stat_t*)(void*)arg0; 474 args->result = (int32_t)mdbx_dbi_stat( 475 (MDBX_txn*)(void*)args->txn, 476 (MDBX_dbi)args->dbi, 477 (MDBX_stat*)(void*)args->stat, 478 args->size 479 ); 480 } 481 482 typedef struct mdbx_dbi_flags_t { 483 size_t txn; 484 size_t flags; 485 size_t state; 486 uint32_t dbi; 487 int32_t result; 488 } mdbx_dbi_flags_t; 489 490 void do_mdbx_dbi_flags_ex(size_t arg0, size_t arg1) { 491 mdbx_dbi_flags_t* args = (mdbx_dbi_flags_t*)(void*)arg0; 492 args->result = (int32_t)mdbx_dbi_flags_ex( 493 (MDBX_txn*)(void*)args->txn, 494 (MDBX_dbi)args->dbi, 495 (unsigned*)(void*)args->flags, 496 (unsigned*)(void*)args->state 497 ); 498 } 499 500 typedef struct mdbx_drop_t { 501 size_t txn; 502 size_t del; 503 uint32_t dbi; 504 int32_t result; 505 } mdbx_drop_t; 506 507 void do_mdbx_drop(size_t arg0, size_t arg1) { 508 mdbx_drop_t* args = (mdbx_drop_t*)(void*)arg0; 509 args->result = (int32_t)mdbx_drop( 510 (MDBX_txn*)(void*)args->txn, 511 (MDBX_dbi)args->dbi, 512 args->del > 0 513 ); 514 } 515 516 typedef struct mdbx_get_t { 517 size_t txn; 518 size_t key; 519 size_t data; 520 uint32_t dbi; 521 int32_t result; 522 } mdbx_get_t; 523 524 void do_mdbx_get(size_t arg0, size_t arg1) { 525 mdbx_get_t* args = (mdbx_get_t*)(void*)arg0; 526 args->result = (int32_t)mdbx_get( 527 (MDBX_txn*)(void*)args->txn, 528 (MDBX_dbi)args->dbi, 529 (MDBX_val*)(void*)args->key, 530 (MDBX_val*)(void*)args->data 531 ); 532 } 533 534 void do_mdbx_get_equal_or_great(size_t arg0, size_t arg1) { 535 mdbx_get_t* args = (mdbx_get_t*)(void*)arg0; 536 args->result = (int32_t)mdbx_get_equal_or_great( 537 (MDBX_txn*)(void*)args->txn, 538 (MDBX_dbi)args->dbi, 539 (MDBX_val*)(void*)args->key, 540 (MDBX_val*)(void*)args->data 541 ); 542 } 543 544 typedef struct mdbx_get_ex_t { 545 size_t txn; 546 size_t key; 547 size_t data; 548 size_t values_count; 549 uint32_t dbi; 550 int32_t result; 551 } mdbx_get_ex_t; 552 553 void do_mdbx_get_ex(size_t arg0, size_t arg1) { 554 mdbx_get_ex_t* args = (mdbx_get_ex_t*)(void*)arg0; 555 args->result = (int32_t)mdbx_get_ex( 556 (MDBX_txn*)(void*)args->txn, 557 (MDBX_dbi)args->dbi, 558 (MDBX_val*)(void*)args->key, 559 (MDBX_val*)(void*)args->data, 560 (size_t*)(void*)args->values_count 561 ); 562 } 563 564 typedef struct mdbx_put_t { 565 size_t txn; 566 size_t key; 567 size_t data; 568 uint32_t dbi; 569 uint32_t flags; 570 int32_t result; 571 } mdbx_put_t; 572 573 void do_mdbx_put(size_t arg0, size_t arg1) { 574 mdbx_put_t* args = (mdbx_put_t*)(void*)arg0; 575 args->result = (int32_t)mdbx_put( 576 (MDBX_txn*)(void*)args->txn, 577 (MDBX_dbi)args->dbi, 578 (MDBX_val*)(void*)args->key, 579 (MDBX_val*)(void*)args->data, 580 (MDBX_put_flags_t)args->flags 581 ); 582 } 583 584 typedef struct mdbx_replace_t { 585 size_t txn; 586 size_t key; 587 size_t data; 588 size_t old_data; 589 uint32_t dbi; 590 uint32_t flags; 591 int32_t result; 592 } mdbx_replace_t; 593 594 void do_mdbx_replace(size_t arg0, size_t arg1) { 595 mdbx_replace_t* args = (mdbx_replace_t*)(void*)arg0; 596 args->result = (int32_t)mdbx_replace( 597 (MDBX_txn*)(void*)args->txn, 598 (MDBX_dbi)args->dbi, 599 (MDBX_val*)(void*)args->key, 600 (MDBX_val*)(void*)args->data, 601 (MDBX_val*)(void*)args->old_data, 602 (MDBX_put_flags_t)args->flags 603 ); 604 } 605 606 typedef struct mdbx_del_t { 607 size_t txn; 608 size_t key; 609 size_t data; 610 uint32_t dbi; 611 int32_t result; 612 } mdbx_del_t; 613 614 void do_mdbx_del(size_t arg0, size_t arg1) { 615 mdbx_del_t* args = (mdbx_del_t*)(void*)arg0; 616 args->result = (int32_t)mdbx_del( 617 (MDBX_txn*)(void*)args->txn, 618 (MDBX_dbi)args->dbi, 619 (MDBX_val*)(void*)args->key, 620 (MDBX_val*)(void*)args->data 621 ); 622 } 623 624 typedef struct mdbx_txn_begin_t { 625 size_t env; 626 size_t parent; 627 size_t txn; 628 size_t context; 629 uint32_t flags; 630 int32_t result; 631 } mdbx_txn_begin_t; 632 633 void do_mdbx_txn_begin_ex(size_t arg0, size_t arg1) { 634 mdbx_txn_begin_t* args = (mdbx_txn_begin_t*)(void*)arg0; 635 args->result = (int32_t)mdbx_txn_begin_ex( 636 (MDBX_env*)(void*)args->env, 637 //(MDBX_txn*)(void*)args->parent, 638 NULL, 639 (MDBX_txn_flags_t)args->flags, 640 (MDBX_txn**)(void*)args->txn, 641 (void*)args->context 642 ); 643 } 644 645 typedef struct mdbx_cursor_create_t { 646 size_t context; 647 size_t cursor; 648 } mdbx_cursor_create_t; 649 650 void do_mdbx_cursor_create(size_t arg0, size_t arg1) { 651 mdbx_cursor_create_t* args = (mdbx_cursor_create_t*)(void*)arg0; 652 args->cursor = (size_t)mdbx_cursor_create( 653 (void*)args->context 654 ); 655 } 656 657 typedef struct mdbx_cursor_bind_t { 658 size_t txn; 659 size_t cursor; 660 uint32_t dbi; 661 int32_t result; 662 } mdbx_cursor_bind_t; 663 664 void do_mdbx_cursor_bind(size_t arg0, size_t arg1) { 665 mdbx_cursor_bind_t* args = (mdbx_cursor_bind_t*)(void*)arg0; 666 args->result = (int32_t)mdbx_cursor_bind( 667 (MDBX_txn*)(void*)args->txn, 668 (MDBX_cursor*)(void*)args->cursor, 669 (MDBX_dbi)args->dbi 670 ); 671 } 672 673 typedef struct mdbx_cursor_open_t { 674 size_t txn; 675 size_t cursor; 676 uint32_t dbi; 677 int32_t result; 678 } mdbx_cursor_open_t; 679 680 void do_mdbx_cursor_open(size_t arg0, size_t arg1) { 681 mdbx_cursor_open_t* args = (mdbx_cursor_open_t*)(void*)arg0; 682 args->result = (int32_t)mdbx_cursor_open( 683 (MDBX_txn*)(void*)args->txn, 684 (MDBX_dbi)args->dbi, 685 (MDBX_cursor**)(void*)args->cursor 686 ); 687 } 688 689 void do_mdbx_cursor_close(size_t arg0, size_t arg1) { 690 mdbx_cursor_close((MDBX_cursor*)(void*)arg0); 691 } 692 693 typedef struct mdbx_cursor_renew_t { 694 size_t txn; 695 size_t cursor; 696 int32_t result; 697 } mdbx_cursor_renew_t; 698 699 void do_mdbx_cursor_renew(size_t arg0, size_t arg1) { 700 mdbx_cursor_renew_t* args = (mdbx_cursor_renew_t*)(void*)arg0; 701 args->result = (int32_t)mdbx_cursor_renew( 702 (MDBX_txn*)(void*)args->txn, 703 (MDBX_cursor*)(void*)args->cursor 704 ); 705 } 706 707 typedef struct mdbx_cursor_txn_t { 708 size_t cursor; 709 size_t txn; 710 } mdbx_cursor_txn_t; 711 712 void do_mdbx_cursor_txn(size_t arg0, size_t arg1) { 713 mdbx_cursor_txn_t* args = (mdbx_cursor_txn_t*)(void*)arg0; 714 args->txn = (size_t)mdbx_cursor_txn( 715 (MDBX_cursor*)(void*)args->cursor 716 ); 717 } 718 719 typedef struct mdbx_cursor_dbi_t { 720 size_t cursor; 721 uint32_t dbi; 722 } mdbx_cursor_dbi_t; 723 724 void do_mdbx_cursor_dbi(size_t arg0, size_t arg1) { 725 mdbx_cursor_dbi_t* args = (mdbx_cursor_dbi_t*)(void*)arg0; 726 args->dbi = (uint32_t)mdbx_cursor_dbi( 727 (MDBX_cursor*)(void*)args->cursor 728 ); 729 } 730 731 typedef struct mdbx_cursor_copy_t { 732 size_t src; 733 size_t dest; 734 int32_t result; 735 } mdbx_cursor_copy_t; 736 737 void do_mdbx_cursor_copy(size_t arg0, size_t arg1) { 738 mdbx_cursor_copy_t* args = (mdbx_cursor_copy_t*)(void*)arg0; 739 args->result = (int32_t)mdbx_cursor_copy( 740 (MDBX_cursor*)(void*)args->src, 741 (MDBX_cursor*)(void*)args->dest 742 ); 743 } 744 745 typedef struct mdbx_cursor_get_t { 746 size_t cursor; 747 size_t key; 748 size_t data; 749 uint32_t op; 750 int32_t result; 751 } mdbx_cursor_get_t; 752 753 void do_mdbx_cursor_get(size_t arg0, size_t arg1) { 754 mdbx_cursor_get_t* args = (mdbx_cursor_get_t*)(void*)arg0; 755 args->result = (int32_t)mdbx_cursor_get( 756 (MDBX_cursor*)(void*)args->cursor, 757 (MDBX_val*)(void*)args->key, 758 (MDBX_val*)(void*)args->data, 759 (MDBX_cursor_op)args->op 760 ); 761 } 762 763 typedef struct mdbx_cursor_put_t { 764 size_t cursor; 765 size_t key; 766 size_t data; 767 uint32_t flags; 768 int32_t result; 769 } mdbx_cursor_put_t; 770 771 void do_mdbx_cursor_put(size_t arg0, size_t arg1) { 772 mdbx_cursor_put_t* args = (mdbx_cursor_put_t*)(void*)arg0; 773 args->result = (int32_t)mdbx_cursor_put( 774 (MDBX_cursor*)(void*)args->cursor, 775 (MDBX_val*)(void*)args->key, 776 (MDBX_val*)(void*)args->data, 777 (MDBX_put_flags_t)args->flags 778 ); 779 } 780 781 typedef struct mdbx_cursor_del_t { 782 size_t cursor; 783 uint32_t flags; 784 int32_t result; 785 } mdbx_cursor_del_t; 786 787 void do_mdbx_cursor_del(size_t arg0, size_t arg1) { 788 mdbx_cursor_del_t* args = (mdbx_cursor_del_t*)(void*)arg0; 789 args->result = (int32_t)mdbx_cursor_del( 790 (MDBX_cursor*)(void*)args->cursor, 791 (MDBX_put_flags_t)args->flags 792 ); 793 } 794 795 typedef struct mdbx_cursor_count_t { 796 size_t cursor; 797 size_t count; 798 int32_t result; 799 } mdbx_cursor_count_t; 800 801 void do_mdbx_cursor_count(size_t arg0, size_t arg1) { 802 mdbx_cursor_count_t* args = (mdbx_cursor_count_t*)(void*)arg0; 803 args->result = (int32_t)mdbx_cursor_count( 804 (MDBX_cursor*)(void*)args->cursor, 805 (size_t*)(void*)args->count 806 ); 807 } 808 809 typedef struct mdbx_cursor_eof_t { 810 size_t cursor; 811 int32_t result; 812 } mdbx_cursor_eof_t; 813 814 void do_mdbx_cursor_eof(size_t arg0, size_t arg1) { 815 mdbx_cursor_eof_t* args = (mdbx_cursor_eof_t*)(void*)arg0; 816 args->result = (int32_t)mdbx_cursor_eof( 817 (MDBX_cursor*)(void*)args->cursor 818 ); 819 } 820 821 typedef struct mdbx_cursor_on_first_t { 822 size_t cursor; 823 int32_t result; 824 } mdbx_cursor_on_first_t; 825 826 void do_mdbx_cursor_on_first(size_t arg0, size_t arg1) { 827 mdbx_cursor_on_first_t* args = (mdbx_cursor_on_first_t*)(void*)arg0; 828 args->result = (int32_t)mdbx_cursor_on_first( 829 (MDBX_cursor*)(void*)args->cursor 830 ); 831 } 832 833 typedef struct mdbx_cursor_on_last_t { 834 size_t cursor; 835 int32_t result; 836 } mdbx_cursor_on_last_t; 837 838 void do_mdbx_cursor_on_last(size_t arg0, size_t arg1) { 839 mdbx_cursor_on_last_t* args = (mdbx_cursor_on_last_t*)(void*)arg0; 840 args->result = (int32_t)mdbx_cursor_on_last( 841 (MDBX_cursor*)(void*)args->cursor 842 ); 843 } 844 845 typedef struct mdbx_estimate_distance_t { 846 size_t first; 847 size_t last; 848 int64_t distance_items; 849 int32_t result; 850 } mdbx_estimate_distance_t; 851 852 void do_mdbx_estimate_distance(size_t arg0, size_t arg1) { 853 mdbx_estimate_distance_t* args = (mdbx_estimate_distance_t*)(void*)arg0; 854 args->result = (int32_t)mdbx_estimate_distance( 855 (MDBX_cursor*)(void*)args->first, 856 (MDBX_cursor*)(void*)args->last, 857 (ptrdiff_t*)(void*)args->distance_items 858 ); 859 } 860 861 //typedef struct mdbx_estimate_move_t { 862 // size_t txn; 863 // size_t last; 864 // int64_t distance_items; 865 // int32_t result; 866 //} mdbx_estimate_move_t; 867 868 */ 869 import "C" 870 import ( 871 "github.com/moontrade/mdbx-go/internal/capture" 872 "github.com/moontrade/mdbx-go/internal/unsafecgo" 873 "os" 874 "reflect" 875 "sync" 876 "syscall" 877 "time" 878 "unsafe" 879 ) 880 881 const ( 882 MaxDBI = uint32(C.MDBX_MAX_DBI) 883 MaxDataSize = uint32(C.MDBX_MAXDATASIZE) 884 MinPageSize = int(C.MDBX_MIN_PAGESIZE) 885 MaxPageSize = int(C.MDBX_MAX_PAGESIZE) 886 ) 887 888 func init() { 889 sz0 := unsafe.Sizeof(C.MDBX_envinfo{}) 890 sz1 := unsafe.Sizeof(EnvInfo{}) 891 if sz0 != sz1 { 892 panic("sizeof(C.MDBX_envinfo) != sizeof(EnvInfo{})") 893 } 894 } 895 896 type Cmp C.MDBX_cmp_func 897 898 var ( 899 CmpU16 = (*Cmp)(C.mdbx_cmp_u16) 900 CmpU32 = (*Cmp)(C.mdbx_cmp_u32) 901 CmpU64 = (*Cmp)(C.mdbx_cmp_u64) 902 CmpU16PrefixLexical = (*Cmp)(C.mdbx_cmp_u16_prefix_lexical) 903 CmpU16PrefixU64 = (*Cmp)(C.mdbx_cmp_u16_prefix_u64) 904 CmpU32PrefixLexical = (*Cmp)(C.mdbx_cmp_u32_prefix_lexical) 905 CmpU32PrefixU64 = (*Cmp)(C.mdbx_cmp_u32_prefix_u64) 906 CmpU64PrefixLexical = (*Cmp)(C.mdbx_cmp_u64_prefix_lexical) 907 CmpU64PrefixU64 = (*Cmp)(C.mdbx_cmp_u64_prefix_u64) 908 CmpU32PrefixU64DupLexical = (*Cmp)(C.mdbx_cmp_u32_prefix_u64_dup_lexical) 909 CmpU32PrefixU64DupU64 = (*Cmp)(C.mdbx_cmp_u32_prefix_u64_dup_u64) 910 CmpU64PrefixU64DupLexical = (*Cmp)(C.mdbx_cmp_u64_prefix_u64_dup_lexical) 911 CmpU64PrefixU64DupU64 = (*Cmp)(C.mdbx_cmp_u64_prefix_u64_dup_u64) 912 ) 913 914 // Chk invokes the embedded mdbx_chk utility 915 // usage: mdbx_chk [-V] [-v] [-q] [-c] [-0|1|2] [-w] [-d] [-i] [-s subdb] dbpath 916 // 917 // -V print version and exit 918 // -v more verbose, could be used multiple times 919 // -q be quiet 920 // -c force cooperative mode (don't try exclusive) 921 // -w write-mode checking 922 // -d disable page-by-page traversal of B-tree 923 // -i ignore wrong order errors (for custom comparators case) 924 // -s subdb process a specific subdatabase only 925 // -0|1|2 force using specific meta-page 0, or 2 for checking 926 // -t turn to a specified meta-page on successful check 927 // -T turn to a specified meta-page EVEN ON UNSUCCESSFUL CHECK! 928 func Chk(args ...string) (result int32, output []byte, err error) { 929 argv := make([]*C.char, len(args)+1) 930 argv[0] = C.CString("mdbx_chk") 931 for i, arg := range args { 932 argv[i+1] = C.CString(arg) 933 } 934 defer func() { 935 for _, arg := range argv { 936 C.free(unsafe.Pointer(arg)) 937 } 938 }() 939 940 // ch := make(chan string) 941 // go func() { 942 // defer close(ch) 943 // err = capture.CaptureWithCGoChan(ch, func() { 944 // result = int32(C.mdbx_chk((C.int)(len(argv)), (**C.char)(unsafe.Pointer(&argv[0])))) 945 // }) 946 // }() 947 // 948 // var lines []string 949 //LOOP: 950 // for { 951 // select { 952 // case line, ok := <-ch: 953 // if !ok { 954 // break LOOP 955 // } 956 // //fmt.Fprintf(out, "%s\n", line) 957 // lines = append(lines, line) 958 // } 959 // } 960 // for _, line := range lines { 961 // println(line) 962 // } 963 964 output, err = capture.CaptureWithCGo(func() { 965 result = int32(C.mdbx_chk((C.int)(len(argv)), (**C.char)(unsafe.Pointer(&argv[0])))) 966 }) 967 return 968 } 969 970 // ChkMain invokes the embedded mdbx_chk utility and exits the program. 971 // usage: mdbx_chk [-V] [-v] [-q] [-c] [-0|1|2] [-w] [-d] [-i] [-s subdb] dbpath 972 // 973 // -V print version and exit 974 // -v more verbose, could be used multiple times 975 // -q be quiet 976 // -c force cooperative mode (don't try exclusive) 977 // -w write-mode checking 978 // -d disable page-by-page traversal of B-tree 979 // -i ignore wrong order errors (for custom comparators case) 980 // -s subdb process a specific subdatabase only 981 // -0|1|2 force using specific meta-page 0, or 2 for checking 982 // -t turn to a specified meta-page on successful check 983 // -T turn to a specified meta-page EVEN ON UNSUCCESSFUL CHECK! 984 func ChkMain(args ...string) { 985 argv := make([]*C.char, len(args)+1) 986 argv[0] = C.CString("mdbx_chk") 987 for i, arg := range args { 988 argv[i+1] = C.CString(arg) 989 } 990 defer func() { 991 for _, arg := range argv { 992 C.free(unsafe.Pointer(arg)) 993 } 994 }() 995 996 os.Exit(int(C.mdbx_chk((C.int)(len(argv)), (**C.char)(unsafe.Pointer(&argv[0]))))) 997 } 998 999 // Stat invokes the embedded mdbx_stat utility. 1000 // usage: mdbx_stat [-V] [-q] [-e] [-f[f[f]]] [-r[r]] [-a|-s name] dbpath 1001 // 1002 // -V print version and exit 1003 // -q be quiet 1004 // -p show statistics of page operations for current session 1005 // -e show whole DB info 1006 // -f show GC info 1007 // -r show readers 1008 // -a print stat of main DB and all subDBs 1009 // -s name print stat of only the specified named subDB 1010 // by default print stat of only the main DB 1011 func Stat(args ...string) (result int32, output []byte, err error) { 1012 argv := make([]*C.char, len(args)+1) 1013 argv[0] = C.CString("mdbx_stat") 1014 for i, arg := range args { 1015 argv[i+1] = C.CString(arg) 1016 } 1017 defer func() { 1018 for _, arg := range argv { 1019 C.free(unsafe.Pointer(arg)) 1020 } 1021 }() 1022 output, err = capture.CaptureWithCGo(func() { 1023 result = int32(C.mdbx_stat((C.int)(len(argv)), (**C.char)(unsafe.Pointer(&argv[0])))) 1024 }) 1025 return 1026 } 1027 1028 // StatMain invokes the embedded mdbx_stat utility and exits the program. 1029 // usage: mdbx_stat [-V] [-q] [-e] [-f[f[f]]] [-r[r]] [-a|-s name] dbpath 1030 // 1031 // -V print version and exit 1032 // -q be quiet 1033 // -p show statistics of page operations for current session 1034 // -e show whole DB info 1035 // -f show GC info 1036 // -r show readers 1037 // -a print stat of main DB and all subDBs 1038 // -s name print stat of only the specified named subDB 1039 // by default print stat of only the main DB 1040 func StatMain(args ...string) { 1041 argv := make([]*C.char, len(args)+1) 1042 argv[0] = C.CString("mdbx_chk") 1043 for i, arg := range args { 1044 argv[i+1] = C.CString(arg) 1045 } 1046 defer func() { 1047 for _, arg := range argv { 1048 C.free(unsafe.Pointer(arg)) 1049 } 1050 }() 1051 1052 os.Exit(int(C.mdbx_stat((C.int)(len(argv)), (**C.char)(unsafe.Pointer(&argv[0]))))) 1053 } 1054 1055 type LogLevel int32 1056 1057 const ( 1058 // LogFatal Critical conditions, i.e. assertion failures 1059 LogFatal = LogLevel(C.MDBX_LOG_FATAL) 1060 1061 // LogError Enables logging for error conditions and \ref MDBX_LOG_FATAL 1062 LogError = LogLevel(C.MDBX_LOG_ERROR) 1063 1064 // LogWarn Enables logging for warning conditions and \ref MDBX_LOG_ERROR ... 1065 // \ref MDBX_LOG_FATAL 1066 LogWarn = LogLevel(C.MDBX_LOG_WARN) 1067 1068 // LogNotice Enables logging for normal but significant condition and 1069 // \ref MDBX_LOG_WARN ... \ref MDBX_LOG_FATAL 1070 LogNotice = LogLevel(C.MDBX_LOG_NOTICE) 1071 1072 // LogVerbose Enables logging for verbose informational and \ref MDBX_LOG_NOTICE ... 1073 // \ref MDBX_LOG_FATAL 1074 LogVerbose = LogLevel(C.MDBX_LOG_VERBOSE) 1075 1076 // LogDebug Enables logging for debug-level messages and \ref MDBX_LOG_VERBOSE ... 1077 // \ref MDBX_LOG_FATAL 1078 LogDebug = LogLevel(C.MDBX_LOG_DEBUG) 1079 1080 // LogTrace Enables logging for trace debug-level messages and \ref MDBX_LOG_DEBUG ... 1081 // \ref MDBX_LOG_FATAL 1082 LogTrace = LogLevel(C.MDBX_LOG_TRACE) 1083 1084 // LogExtra Enables extra debug-level messages (dump pgno lists) and all other log-messages 1085 LogExtra = LogLevel(C.MDBX_LOG_EXTRA) 1086 LogMax = LogLevel(7) 1087 1088 // LogDontChange for \ref mdbx_setup_debug() only: Don't change current settings 1089 LogDontChange = LogLevel(C.MDBX_LOG_DONTCHANGE) 1090 ) 1091 1092 type Error int32 1093 1094 func (e Error) Error() string { 1095 args := struct { 1096 result uintptr 1097 code int32 1098 }{ 1099 code: int32(e), 1100 } 1101 ptr := uintptr(unsafe.Pointer(&args)) 1102 unsafecgo.NonBlocking((*byte)(C.do_mdbx_strerror), ptr, 0) 1103 str := C.GoString((*C.char)(unsafe.Pointer(args.result))) 1104 return str 1105 } 1106 1107 const ( 1108 ErrSuccess = Error(C.MDBX_SUCCESS) 1109 ErrResultFalse = ErrSuccess 1110 1111 // ErrResultTrue Successful result with special meaning or a flag 1112 ErrResultTrue = Error(C.MDBX_RESULT_TRUE) 1113 1114 // ErrKeyExist key/data pair already exist 1115 ErrKeyExist = Error(C.MDBX_KEYEXIST) 1116 1117 // ErrFirstLMDBErrCode The first LMDB-compatible defined error code 1118 ErrFirstLMDBErrCode = ErrKeyExist 1119 1120 // ErrNotFound key/data pair not found (EOF) 1121 ErrNotFound = Error(C.MDBX_NOTFOUND) 1122 1123 // ErrPageNotFound Requested page not found -this usually indicates corruption 1124 ErrPageNotFound = Error(C.MDBX_PAGE_NOTFOUND) 1125 1126 // ErrCorrupted Database is corrupted (page was wrong type and so on) 1127 ErrCorrupted = Error(C.MDBX_CORRUPTED) 1128 1129 // ErrPanic Environment had fatal error, i.e. update of meta page failed and so on. 1130 ErrPanic = Error(C.MDBX_PANIC) 1131 1132 // ErrVersionMismatch DB file version mismatch with libmdbx 1133 ErrVersionMismatch = Error(C.MDBX_VERSION_MISMATCH) 1134 1135 // ErrInvalid File is not a valid MDBX file 1136 ErrInvalid = Error(C.MDBX_INVALID) 1137 1138 // ErrMapFull Environment mapsize reached 1139 ErrMapFull = Error(C.MDBX_MAP_FULL) 1140 1141 // ErrDBSFull Environment maxdbs reached 1142 ErrDBSFull = Error(C.MDBX_DBS_FULL) 1143 1144 // ErrReadersFull Environment maxreaders reached 1145 ErrReadersFull = Error(C.MDBX_READERS_FULL) 1146 1147 // ErrTXNFull Transaction has too many dirty pages, i.e transaction too big 1148 ErrTXNFull = Error(C.MDBX_TXN_FULL) 1149 1150 // ErrCursorFull Cursor stack too deep -this usually indicates corruption, i.e branchC.pages loop 1151 ErrCursorFull = Error(C.MDBX_CURSOR_FULL) 1152 1153 // ErrPageFull Page has not enough space -internal error 1154 ErrPageFull = Error(C.MDBX_PAGE_FULL) 1155 1156 // ErrUnableExtendMapSize Database engine was unable to extend mapping, e.g. since address space 1157 // is unavailable or busy. This can mean: 1158 // - Database size extended by other process beyond to environment mapsize 1159 // and engine was unable to extend mapping while starting read 1160 // transaction. Environment should be reopened to continue. 1161 // - Engine was unable to extend mapping during write transaction 1162 // or explicit call of \ref mdbx_env_set_geometry(). 1163 ErrUnableExtendMapSize = Error(C.MDBX_UNABLE_EXTEND_MAPSIZE) 1164 1165 // ErrIncompatible Environment or database is not compatible with the requested operation 1166 // or the specified flags. This can mean: 1167 // - The operation expects an \ref MDBX_DUPSORT / \ref MDBX_DUPFIXED 1168 // database. 1169 // - Opening a named DB when the unnamed DB has \ref MDBX_DUPSORT / 1170 // \ref MDBX_INTEGERKEY. 1171 // - Accessing a data record as a database, or vice versa. 1172 // - The database was dropped and recreated with different flags. 1173 ErrIncompatible = Error(C.MDBX_INCOMPATIBLE) 1174 1175 // ErrBadRSlot Invalid reuse of reader locktable slot 1176 // e.g. readC.transaction already run for current thread 1177 ErrBadRSlot = Error(C.MDBX_BAD_RSLOT) 1178 1179 // ErrBadTXN Transaction is not valid for requested operation, 1180 // e.g. had errored and be must aborted, has a child, or is invalid 1181 ErrBadTXN = Error(C.MDBX_BAD_TXN) 1182 1183 // ErrBadValSize Invalid size or alignment of key or data for target database, 1184 // either invalid subDB name 1185 ErrBadValSize = Error(C.MDBX_BAD_VALSIZE) 1186 1187 // ErrBadDBI The specified DBIC.handle is invalid 1188 // or changed by another thread/transaction. 1189 ErrBadDBI = Error(C.MDBX_BAD_DBI) 1190 1191 // ErrProblem Unexpected internal error, transaction should be aborted 1192 ErrProblem = Error(C.MDBX_PROBLEM) 1193 1194 // ErrLastLMDBErrCode The last LMDBC.compatible defined error code 1195 ErrLastLMDBErrCode = ErrProblem 1196 1197 // ErrBusy Another write transaction is running or environment is already used while 1198 // opening with \ref MDBX_EXCLUSIVE flag 1199 ErrBusy = Error(C.MDBX_BUSY) 1200 ErrFirstAddedErrCode = ErrBusy // The first of MDBXC.added error codes 1201 ErrEMultiVal = Error(C.MDBX_EMULTIVAL) // The specified key has more than one associated value 1202 1203 // ErrEBadSign Bad signature of a runtime object(s), this can mean: 1204 // - memory corruption or doubleC.free; 1205 // - ABI version mismatch (rare case); 1206 ErrEBadSign = Error(C.MDBX_EBADSIGN) 1207 1208 // ErrWannaRecovery Database should be recovered, but this could NOT be done for now 1209 // since it opened in readC.only mode. 1210 ErrWannaRecovery = Error(C.MDBX_WANNA_RECOVERY) 1211 1212 // ErrEKeyMismatch The given key value is mismatched to the current cursor position 1213 ErrEKeyMismatch = Error(C.MDBX_EKEYMISMATCH) 1214 1215 // ErrTooLarge Database is too large for current system, 1216 // e.g. could NOT be mapped into RAM. 1217 ErrTooLarge = Error(C.MDBX_TOO_LARGE) 1218 1219 // ErrThreadMismatch A thread has attempted to use a not owned object, 1220 // e.g. a transaction that started by another thread. 1221 ErrThreadMismatch = Error(C.MDBX_THREAD_MISMATCH) 1222 1223 // ErrTXNOverlapping Overlapping read and write transactions for the current thread 1224 ErrTXNOverlapping = Error(C.MDBX_TXN_OVERLAPPING) 1225 1226 ErrLastAddedErrcode = ErrTXNOverlapping 1227 1228 ErrENODAT = Error(C.MDBX_ENODATA) 1229 ErrEINVAL = Error(C.MDBX_EINVAL) 1230 ErrEACCESS = Error(C.MDBX_EACCESS) 1231 ErrENOMEM = Error(C.MDBX_ENOMEM) 1232 ErrEROFS = Error(C.MDBX_EROFS) 1233 ErrENOSYS = Error(C.MDBX_ENOSYS) 1234 ErrEIO = Error(C.MDBX_EIO) 1235 ErrEPERM = Error(C.MDBX_EPERM) 1236 ErrEINTR = Error(C.MDBX_EINTR) 1237 ErrENOENT = Error(C.MDBX_ENOFILE) 1238 ErrENOTBLK = Error(C.MDBX_EREMOTE) 1239 ) 1240 1241 type EnvFlags uint32 1242 1243 const ( 1244 EnvEnvDefaults EnvFlags = 0 1245 1246 // EnvNoSubDir No environment directory. 1247 // 1248 // By default, MDBX creates its environment in a directory whose pathname is 1249 // given in path, and creates its data and lock files under that directory. 1250 // With this option, path is used as-is for the database rootDB data file. 1251 // The database lock file is the path with "-lck" appended. 1252 // 1253 // - with `MDBX_NOSUBDIR` = in a filesystem we have the pair of MDBX-files 1254 // which names derived from given pathname by appending predefined suffixes. 1255 // 1256 // - without `MDBX_NOSUBDIR` = in a filesystem we have the MDBX-directory with 1257 // given pathname, within that a pair of MDBX-files with predefined names. 1258 // 1259 // This flag affects only at new environment creating by \ref mdbx_env_open(), 1260 // otherwise at opening an existing environment libmdbx will choice this 1261 // automatically. 1262 EnvNoSubDir = EnvFlags(C.MDBX_NOSUBDIR) 1263 1264 // EnvReadOnly Read only mode. 1265 // 1266 // Open the environment in read-only mode. No write operations will be 1267 // allowed. MDBX will still modify the lock file - except on read-only 1268 // filesystems, where MDBX does not use locks. 1269 // 1270 // - with `MDBX_RDONLY` = open environment in read-only mode. 1271 // MDBX supports pure read-only mode (i.e. without opening LCK-file) only 1272 // when environment directory and/or both files are not writable (and the 1273 // LCK-file may be missing). In such case allowing file(s) to be placed 1274 // on a network read-only share. 1275 // 1276 // - without `MDBX_RDONLY` = open environment in read-write mode. 1277 // 1278 // This flag affects only at environment opening but can't be changed after. 1279 EnvReadOnly = EnvFlags(C.MDBX_RDONLY) 1280 1281 // EnvExclusive Open environment in exclusive/monopolistic mode. 1282 // 1283 // `MDBX_EXCLUSIVE` flag can be used as a replacement for `MDB_NOLOCK`, 1284 // which don't supported by MDBX. 1285 // In this way, you can get the minimal overhead, but with the correct 1286 // multi-process and multi-thread locking. 1287 // 1288 // - with `MDBX_EXCLUSIVE` = open environment in exclusive/monopolistic mode 1289 // or return \ref MDBX_BUSY if environment already used by other process. 1290 // The rootDB feature of the exclusive mode is the ability to open the 1291 // environment placed on a network share. 1292 // 1293 // - without `MDBX_EXCLUSIVE` = open environment in cooperative mode, 1294 // i.e. for multi-process access/interaction/cooperation. 1295 // The rootDB requirements of the cooperative mode are: 1296 // 1297 // 1. data files MUST be placed in the LOCAL file system, 1298 // but NOT on a network share. 1299 // 2. environment MUST be opened only by LOCAL processes, 1300 // but NOT over a network. 1301 // 3. OS kernel (i.e. file system and memory mapping implementation) and 1302 // all processes that open the given environment MUST be running 1303 // in the physically single RAM with cache-coherency. The only 1304 // exception for cache-consistency requirement is Linux on MIPS 1305 // architecture, but this case has not been tested for a long time). 1306 // 1307 // This flag affects only at environment opening but can't be changed after. 1308 EnvExclusive = EnvFlags(C.MDBX_EXCLUSIVE) 1309 1310 // EnvAccede Using database/environment which already opened by another process(es). 1311 // 1312 // The `MDBX_ACCEDE` flag is useful to avoid \ref MDBX_INCOMPATIBLE error 1313 // while opening the database/environment which is already used by another 1314 // process(es) with unknown mode/flags. In such cases, if there is a 1315 // difference in the specified flags (\ref MDBX_NOMETASYNC, 1316 // \ref MDBX_SAFE_NOSYNC, \ref MDBX_UTTERLY_NOSYNC, \ref MDBX_LIFORECLAIM, 1317 // \ref MDBX_COALESCE and \ref MDBX_NORDAHEAD), instead of returning an error, 1318 // the database will be opened in a compatibility with the already used mode. 1319 // 1320 // `MDBX_ACCEDE` has no effect if the current process is the only one either 1321 // opening the DB in read-only mode or other process(es) uses the DB in 1322 // read-only mode. 1323 EnvAccede = EnvFlags(C.MDBX_ACCEDE) 1324 1325 // EnvWriteMap Map data into memory with write permission. 1326 // 1327 // Use a writeable memory map unless \ref MDBX_RDONLY is set. This uses fewer 1328 // mallocs and requires much less work for tracking database pages, but 1329 // loses protection from application bugs like wild pointer writes and other 1330 // bad updates into the database. This may be slightly faster for DBs that 1331 // fit entirely in RAM, but is slower for DBs larger than RAM. Also adds the 1332 // possibility for stray application writes thru pointers to silently 1333 // corrupt the database. 1334 // 1335 // - with `MDBX_WRITEMAP` = all data will be mapped into memory in the 1336 // read-write mode. This offers a significant performance benefit, since the 1337 // data will be modified directly in mapped memory and then flushed to disk 1338 // by single system call, without any memory management nor copying. 1339 // 1340 // - without `MDBX_WRITEMAP` = data will be mapped into memory in the 1341 // read-only mode. This requires stocking all modified database pages in 1342 // memory and then writing them to disk through file operations. 1343 // 1344 // \warning On the other hand, `MDBX_WRITEMAP` adds the possibility for stray 1345 // application writes thru pointers to silently corrupt the database. 1346 // 1347 // \note The `MDBX_WRITEMAP` mode is incompatible with nested transactions, 1348 // since this is unreasonable. I.e. nested transactions requires mallocation 1349 // of database pages and more work for tracking ones, which neuters a 1350 // performance boost caused by the `MDBX_WRITEMAP` mode. 1351 // 1352 // This flag affects only at environment opening but can't be changed after. 1353 EnvWriteMap = EnvFlags(C.MDBX_WRITEMAP) 1354 1355 // EnvNoTLS Tie reader locktable slots to read-only transactions 1356 // instead of to threads. 1357 // 1358 // Don't use Thread-Local Storage, instead tie reader locktable slots to 1359 // \ref MDBX_txn objects instead of to threads. So, \ref mdbx_txn_reset() 1360 // keeps the slot reserved for the \ref MDBX_txn object. A thread may use 1361 // parallel read-only transactions. And a read-only transaction may span 1362 // threads if you synchronizes its use. 1363 // 1364 // Applications that multiplex many user threads over individual OS threads 1365 // need this option. Such an application must also serialize the write 1366 // transactions in an OS thread, since MDBX's write locking is unaware of 1367 // the user threads. 1368 // 1369 // \note Regardless to `MDBX_NOTLS` flag a write transaction entirely should 1370 // always be used in one thread from start to finish. MDBX checks this in a 1371 // reasonable manner and return the \ref MDBX_THREAD_MISMATCH error in rules 1372 // violation. 1373 // 1374 // This flag affects only at environment opening but can't be changed after. 1375 EnvNoTLS = EnvFlags(C.MDBX_NOTLS) 1376 //MDBX_NOTLS = UINT32_C(0x200000) 1377 1378 // EnvNoReadAhead Don't do readahead. 1379 // 1380 // Turn off readahead. Most operating systems perform readahead on read 1381 // requests by default. This option turns it off if the OS supports it. 1382 // Turning it off may help random read performance when the DB is larger 1383 // than RAM and system RAM is full. 1384 // 1385 // By default libmdbx dynamically enables/disables readahead depending on 1386 // the actual database size and currently available memory. On the other 1387 // hand, such automation has some limitation, i.e. could be performed only 1388 // when DB size changing but can't tracks and reacts changing a free RAM 1389 // availability, since it changes independently and asynchronously. 1390 // 1391 // \note The mdbx_is_readahead_reasonable() function allows to quickly find 1392 // out whether to use readahead or not based on the size of the data and the 1393 // amount of available memory. 1394 // 1395 // This flag affects only at environment opening and can't be changed after. 1396 EnvNoReadAhead = EnvFlags(C.MDBX_NORDAHEAD) 1397 1398 // EnvNoMemInit Don't initialize malloc'ed memory before writing to datafile. 1399 // 1400 // Don't initialize malloc'ed memory before writing to unused spaces in the 1401 // data file. By default, memory for pages written to the data file is 1402 // obtained using malloc. While these pages may be reused in subsequent 1403 // transactions, freshly malloc'ed pages will be initialized to zeroes before 1404 // use. This avoids persisting leftover data from other code (that used the 1405 // heap and subsequently freed the memory) into the data file. 1406 // 1407 // Note that many other system libraries may allocate and free memory from 1408 // the heap for arbitrary uses. E.g., stdio may use the heap for file I/O 1409 // buffers. This initialization step has a modest performance cost so some 1410 // applications may want to disable it using this flag. This option can be a 1411 // problem for applications which handle sensitive data like passwords, and 1412 // it makes memory checkers like Valgrind noisy. This flag is not needed 1413 // with \ref MDBX_WRITEMAP, which writes directly to the mmap instead of using 1414 // malloc for pages. The initialization is also skipped if \ref MDBX_RESERVE 1415 // is used; the caller is expected to overwrite all of the memory that was 1416 // reserved in that case. 1417 // 1418 // This flag may be changed at any time using `mdbx_env_set_flags()`. 1419 EnvNoMemInit = EnvFlags(C.MDBX_NOMEMINIT) 1420 1421 // EnvCoalesce Aims to coalesce a Garbage Collection items. 1422 // 1423 // With `MDBX_COALESCE` flag MDBX will aims to coalesce items while recycling 1424 // a Garbage Collection. Technically, when possible short lists of pages 1425 // will be combined into longer ones, but to fit on one database page. As a 1426 // result, there will be fewer items in Garbage Collection and a page lists 1427 // are longer, which slightly increases the likelihood of returning pages to 1428 // Unallocated space and reducing the database file. 1429 // 1430 // This flag may be changed at any time using mdbx_env_set_flags(). 1431 EnvCoalesce = EnvFlags(C.MDBX_COALESCE) 1432 1433 // EnvLIFOReclaim LIFO policy for recycling a Garbage Collection items. 1434 // 1435 // `MDBX_LIFORECLAIM` flag turns on LIFO policy for recycling a Garbage 1436 // Collection items, instead of FIFO by default. On systems with a disk 1437 // write-back cache, this can significantly increase write performance, up 1438 // to several times in a best case scenario. 1439 // 1440 // LIFO recycling policy means that for reuse pages will be taken which became 1441 // unused the lastest (i.e. just now or most recently). Therefore the loop of 1442 // database pages circulation becomes as short as possible. In other words, 1443 // the number of pages, that are overwritten in memory and on disk during a 1444 // series of write transactions, will be as small as possible. Thus creates 1445 // ideal conditions for the efficient operation of the disk write-back cache. 1446 // 1447 // \ref MDBX_LIFORECLAIM is compatible with all no-sync flags, but gives NO 1448 // noticeable impact in combination with \ref MDBX_SAFE_NOSYNC or 1449 // \ref MDBX_UTTERLY_NOSYN-Because MDBX will reused pages only before the 1450 // last "steady" MVCC-snapshot, i.e. the loop length of database pages 1451 // circulation will be mostly defined by frequency of calling 1452 // \ref mdbx_env_sync() rather than LIFO and FIFO difference. 1453 // 1454 // This flag may be changed at any time using mdbx_env_set_flags(). 1455 EnvLIFOReclaim = EnvFlags(C.MDBX_LIFORECLAIM) 1456 1457 // EnvPagPerTurb Debugging option, fill/perturb released pages. 1458 EnvPagePerTurb = EnvFlags(C.MDBX_PAGEPERTURB) 1459 1460 // SYNC MODES 1461 1462 // \defgroup sync_modes SYNC MODES 1463 // 1464 // \attention Using any combination of \ref MDBX_SAFE_NOSYNC, \ref 1465 // MDBX_NOMETASYNC and especially \ref MDBX_UTTERLY_NOSYNC is always a deal to 1466 // reduce durability for gain write performance. You must know exactly what 1467 // you are doing and what risks you are taking! 1468 // 1469 // \note for LMDB users: \ref MDBX_SAFE_NOSYNC is NOT similar to LMDB_NOSYNC, 1470 // but \ref MDBX_UTTERLY_NOSYNC is exactly match LMDB_NOSYN-See details 1471 // below. 1472 // 1473 // THE SCENE: 1474 // - The DAT-file contains several MVCC-snapshots of B-tree at same time, 1475 // each of those B-tree has its own root page. 1476 // - Each of meta pages at the beginning of the DAT file contains a 1477 // pointer to the root page of B-tree which is the result of the particular 1478 // transaction, and a number of this transaction. 1479 // - For data durability, MDBX must first write all MVCC-snapshot data 1480 // pages and ensure that are written to the disk, then update a meta page 1481 // with the new transaction number and a pointer to the corresponding new 1482 // root page, and flush any buffers yet again. 1483 // - Thus during commit a I/O buffers should be flushed to the disk twice; 1484 // i.e. fdatasync(), FlushFileBuffers() or similar syscall should be 1485 // called twice for each commit. This is very expensive for performance, 1486 // but guaranteed durability even on unexpected system failure or power 1487 // outage. Of course, provided that the operating system and the 1488 // underlying hardware (e.g. disk) work correctly. 1489 // 1490 // TRADE-OFF: 1491 // By skipping some stages described above, you can significantly benefit in 1492 // speed, while partially or completely losing in the guarantee of data 1493 // durability and/or consistency in the event of system or power failure. 1494 // Moreover, if for any reason disk write order is not preserved, then at 1495 // moment of a system crash, a meta-page with a pointer to the new B-tree may 1496 // be written to disk, while the itself B-tree not yet. In that case, the 1497 // database will be corrupted! 1498 // 1499 // \see MDBX_SYNC_DURABLE \see MDBX_NOMETASYNC \see MDBX_SAFE_NOSYNC 1500 // \see MDBX_UTTERLY_NOSYNC 1501 // 1502 // @{ 1503 1504 // EnvSyncDurable Default robust and durable sync mode. 1505 // 1506 // Metadata is written and flushed to disk after a data is written and 1507 // flushed, which guarantees the integrity of the database in the event 1508 // of a crash at any time. 1509 // 1510 // \attention Please do not use other modes until you have studied all the 1511 // details and are sure. Otherwise, you may lose your users' data, as happens 1512 // in [Miranda NG](https://www.miranda-ng.org/) messenger. 1513 EnvSyncDurable = EnvFlags(C.MDBX_SYNC_DURABLE) 1514 1515 // EnvNoMetaSync Don't sync the meta-page after commit. 1516 // 1517 // Flush system buffers to disk only once per transaction commit, omit the 1518 // metadata flush. Defer that until the system flushes files to disk, 1519 // or next non-\ref MDBX_RDONLY commit or \ref mdbx_env_sync(). Depending on 1520 // the platform and hardware, with \ref MDBX_NOMETASYNC you may get a doubling 1521 // of write performance. 1522 // 1523 // This trade-off maintains database integrity, but a system crash may 1524 // undo the last committed transaction. I.e. it preserves the ACI 1525 // (atomicity, consistency, isolation) but not D (durability) database 1526 // property. 1527 // 1528 // `MDBX_NOMETASYNC` flag may be changed at any time using 1529 // \ref mdbx_env_set_flags() or by passing to \ref mdbx_txn_begin() for 1530 // particular write transaction. \see sync_modes 1531 EnvNoMetaSync = EnvFlags(C.MDBX_NOMETASYNC) 1532 1533 // EnvSafeNoSync Don't sync anything but keep previous steady commits. 1534 // 1535 // Like \ref MDBX_UTTERLY_NOSYNC the `MDBX_SAFE_NOSYNC` flag disable similarly 1536 // flush system buffers to disk when committing a transaction. But there is a 1537 // huge difference in how are recycled the MVCC snapshots corresponding to 1538 // previous "steady" transactions (see below). 1539 // 1540 // With \ref MDBX_WRITEMAP the `MDBX_SAFE_NOSYNC` instructs MDBX to use 1541 // asynchronous mmap-flushes to disk. Asynchronous mmap-flushes means that 1542 // actually all writes will scheduled and performed by operation system on it 1543 // own manner, i.e. unordered. MDBX itself just notify operating system that 1544 // it would be nice to write data to disk, but no more. 1545 // 1546 // Depending on the platform and hardware, with `MDBX_SAFE_NOSYNC` you may get 1547 // a multiple increase of write performance, even 10 times or more. 1548 // 1549 // In contrast to \ref MDBX_UTTERLY_NOSYNC mode, with `MDBX_SAFE_NOSYNC` flag 1550 // MDBX will keeps untouched pages within B-tree of the last transaction 1551 // "steady" which was synced to disk completely. This has big implications for 1552 // both data durability and (unfortunately) performance: 1553 // - a system crash can't corrupt the database, but you will lose the last 1554 // transactions; because MDBX will rollback to last steady commit since it 1555 // kept explicitly. 1556 // - the last steady transaction makes an effect similar to "long-lived" read 1557 // transaction (see above in the \ref restrictions section) since prevents 1558 // reuse of pages freed by newer write transactions, thus the any data 1559 // changes will be placed in newly allocated pages. 1560 // - to avoid rapid database growth, the system will sync data and issue 1561 // a steady commit-point to resume reuse pages, each time there is 1562 // insufficient space and before increasing the size of the file on disk. 1563 // 1564 // In other words, with `MDBX_SAFE_NOSYNC` flag MDBX insures you from the 1565 // whole database corruption, at the cost increasing database size and/or 1566 // number of disk IOPs. So, `MDBX_SAFE_NOSYNC` flag could be used with 1567 // \ref mdbx_env_sync() as alternatively for batch committing or nested 1568 // transaction (in some cases). As well, auto-sync feature exposed by 1569 // \ref mdbx_env_set_syncbytes() and \ref mdbx_env_set_syncperiod() functions 1570 // could be very useful with `MDBX_SAFE_NOSYNC` flag. 1571 // 1572 // The number and volume of of disk IOPs with MDBX_SAFE_NOSYNC flag will 1573 // exactly the as without any no-sync flags. However, you should expect a 1574 // larger process's [work set](https://bit.ly/2kA2tFX) and significantly worse 1575 // a [locality of reference](https://bit.ly/2mbYq2J), due to the more 1576 // intensive allocation of previously unused pages and increase the size of 1577 // the database. 1578 // 1579 // `MDBX_SAFE_NOSYNC` flag may be changed at any time using 1580 // \ref mdbx_env_set_flags() or by passing to \ref mdbx_txn_begin() for 1581 // particular write transaction. 1582 EnvSafeNoSync = EnvFlags(C.MDBX_SAFE_NOSYNC) 1583 1584 // EnvUtterlyNoSync Don't sync anything and wipe previous steady commits. 1585 // 1586 // Don't flush system buffers to disk when committing a transaction. This 1587 // optimization means a system crash can corrupt the database, if buffers are 1588 // not yet flushed to disk. Depending on the platform and hardware, with 1589 // `MDBX_UTTERLY_NOSYNC` you may get a multiple increase of write performance, 1590 // even 100 times or more. 1591 // 1592 // If the filesystem preserves write order (which is rare and never provided 1593 // unless explicitly noted) and the \ref MDBX_WRITEMAP and \ref 1594 // MDBX_LIFORECLAIM flags are not used, then a system crash can't corrupt the 1595 // database, but you can lose the last transactions, if at least one buffer is 1596 // not yet flushed to disk. The risk is governed by how often the system 1597 // flushes dirty buffers to disk and how often \ref mdbx_env_sync() is called. 1598 // So, transactions exhibit ACI (atomicity, consistency, isolation) properties 1599 // and only lose `D` (durability). I.e. database integrity is maintained, but 1600 // a system crash may undo the final transactions. 1601 // 1602 // Otherwise, if the filesystem not preserves write order (which is 1603 // typically) or \ref MDBX_WRITEMAP or \ref MDBX_LIFORECLAIM flags are used, 1604 // you should expect the corrupted database after a system crash. 1605 // 1606 // So, most important thing about `MDBX_UTTERLY_NOSYNC`: 1607 // - a system crash immediately after commit the write transaction 1608 // high likely lead to database corruption. 1609 // - successful completion of mdbx_env_sync(force = true) after one or 1610 // more committed transactions guarantees consistency and durability. 1611 // - BUT by committing two or more transactions you back database into 1612 // a weak state, in which a system crash may lead to database corruption! 1613 // In case single transaction after mdbx_env_sync, you may lose transaction 1614 // itself, but not a whole database. 1615 // 1616 // Nevertheless, `MDBX_UTTERLY_NOSYNC` provides "weak" durability in case 1617 // of an application crash (but no durability on system failure), and 1618 // therefore may be very useful in scenarios where data durability is 1619 // not required over a system failure (e.g for short-lived data), or if you 1620 // can take such risk. 1621 // 1622 // `MDBX_UTTERLY_NOSYNC` flag may be changed at any time using 1623 // \ref mdbx_env_set_flags(), but don't has effect if passed to 1624 // \ref mdbx_txn_begin() for particular write transaction. \see sync_modes 1625 EnvUtterlyNoSync = EnvFlags(C.MDBX_UTTERLY_NOSYNC) 1626 ) 1627 1628 type TxFlags uint32 1629 1630 const ( 1631 // TxReadWrite Start read-write transaction. 1632 // 1633 // Only one write transaction may be active at a time. Writes are fully 1634 // serialized, which guarantees that writers can never deadlock. 1635 TxReadWrite = TxFlags(C.MDBX_TXN_READWRITE) 1636 1637 // TxReadOnly Start read-only transaction. 1638 // 1639 // There can be multiple read-only transactions simultaneously that do not 1640 // block each other and a write transactions. 1641 TxReadOnly = TxFlags(C.MDBX_TXN_RDONLY) 1642 1643 // TxReadOnlyPrepare Prepare but not start read-only transaction. 1644 // 1645 // Transaction will not be started immediately, but created transaction handle 1646 // will be ready for use with \ref mdbx_txn_renew(). This flag allows to 1647 // preallocate memory and assign a reader slot, thus avoiding these operations 1648 // at the next start of the transaction. 1649 TxReadOnlyPrepare = TxFlags(C.MDBX_TXN_RDONLY_PREPARE) 1650 1651 // TxTry Do not block when starting a write transaction. 1652 TxTry = TxFlags(C.MDBX_TXN_TRY) 1653 1654 // TxNoMetaSync Exactly the same as \ref MDBX_NOMETASYNC, 1655 // but for this transaction only 1656 TxNoMetaSync = TxFlags(C.MDBX_TXN_NOMETASYNC) 1657 1658 // TxNoSync Exactly the same as \ref MDBX_SAFE_NOSYNC, 1659 // but for this transaction only 1660 TxNoSync = TxFlags(C.MDBX_TXN_NOSYNC) 1661 ) 1662 1663 type DBFlags uint32 1664 1665 const ( 1666 DBDefaults = DBFlags(C.MDBX_DB_DEFAULTS) 1667 1668 // DBReverseKey Use reverse string keys 1669 DBReverseKey = DBFlags(C.MDBX_REVERSEKEY) 1670 1671 // DBDupSort Use sorted duplicates, i.e. allow multi-values 1672 DBDupSort = DBFlags(C.MDBX_DUPSORT) 1673 1674 // DBIntegerKey Numeric keys in native byte order either uint32_t or uint64_t. The keys 1675 // must all be of the same size and must be aligned while passing as 1676 // arguments. 1677 DBIntegerKey = DBFlags(C.MDBX_INTEGERKEY) 1678 1679 // DBDupFixed With \ref MDBX_DUPSORT; sorted dup items have fixed size 1680 DBDupFixed = DBFlags(C.MDBX_DUPFIXED) 1681 1682 // DBIntegerGroup With \ref MDBX_DUPSORT and with \ref MDBX_DUPFIXED; dups are fixed size 1683 // \ref MDBX_INTEGERKEY -style integers. The data values must all be of the 1684 // same size and must be aligned while passing as arguments. 1685 DBIntegerGroup = DBFlags(C.MDBX_INTEGERDUP) 1686 1687 // DBReverseDup With \ref MDBX_DUPSORT; use reverse string comparison 1688 DBReverseDup = DBFlags(C.MDBX_REVERSEDUP) 1689 1690 // DBCreate Create DB if not already existing 1691 DBCreate = DBFlags(C.MDBX_CREATE) 1692 1693 // DBAccede Opens an existing sub-database created with unknown flags. 1694 // 1695 // The `MDBX_DB_ACCEDE` flag is intend to open a existing sub-database which 1696 // was created with unknown flags (\ref MDBX_REVERSEKEY, \ref MDBX_DUPSORT, 1697 // \ref MDBX_INTEGERKEY, \ref MDBX_DUPFIXED, \ref MDBX_INTEGERDUP and 1698 // \ref MDBX_REVERSEDUP). 1699 // 1700 // In such cases, instead of returning the \ref MDBX_INCOMPATIBLE error, the 1701 // sub-database will be opened with flags which it was created, and then an 1702 // application could determine the actual flags by \ref mdbx_dbi_flags(). 1703 DBAccede = DBFlags(C.MDBX_DB_ACCEDE) 1704 ) 1705 1706 type PutFlags uint32 1707 1708 const ( 1709 // PutUpsert Upsertion by default (without any other flags) 1710 PutUpsert = PutFlags(C.MDBX_UPSERT) 1711 1712 // PutNoOverwrite For insertion: Don't write if the key already exists. 1713 PutNoOverwrite = PutFlags(C.MDBX_NOOVERWRITE) 1714 1715 // PutNoDupData Has effect only for \ref MDBX_DUPSORT databases. 1716 // For upsertion: don't write if the key-value pair already exist. 1717 // For deletion: remove all values for key. 1718 PutNoDupData = PutFlags(C.MDBX_NODUPDATA) 1719 1720 // PutCurrent For upsertion: overwrite the current key/data pair. 1721 // MDBX allows this flag for \ref mdbx_put() for explicit overwrite/update 1722 // without insertion. 1723 // For deletion: remove only single entry at the current cursor position. 1724 PutCurrent = PutFlags(C.MDBX_CURRENT) 1725 1726 // PutAllDups Has effect only for \ref MDBX_DUPSORT databases. 1727 // For deletion: remove all multi-values (aka duplicates) for given key. 1728 // For upsertion: replace all multi-values for given key with a new one. 1729 PutAllDups = PutFlags(C.MDBX_ALLDUPS) 1730 1731 // PutReserve For upsertion: Just reserve space for data, don't copy it. 1732 // Return a pointer to the reserved space. 1733 PutReserve = PutFlags(C.MDBX_RESERVE) 1734 1735 // PutAppend Data is being appended. 1736 // Don't split full pages, continue on a new instead. 1737 PutAppend = PutFlags(C.MDBX_APPEND) 1738 1739 // PutAppendDup Has effect only for \ref MDBX_DUPSORT databases. 1740 // Duplicate data is being appended. 1741 // Don't split full pages, continue on a new instead. 1742 PutAppendDup = PutFlags(C.MDBX_APPENDDUP) 1743 1744 // PutMultiple Only for \ref MDBX_DUPFIXED. 1745 // Store multiple data items in one call. 1746 PutMultiple = PutFlags(C.MDBX_MULTIPLE) 1747 ) 1748 1749 type CopyFlags uint32 1750 1751 const ( 1752 CopyDefaults = CopyFlags(C.MDBX_CP_DEFAULTS) 1753 1754 // CopyCompact Copy and compact: Omit free space from copy and renumber all 1755 // pages sequentially 1756 CopyCompact = CopyFlags(C.MDBX_CP_COMPACT) 1757 1758 // CopyForceDynamicSize Force to make resizeable copy, i.e. dynamic size instead of fixed 1759 CopyForceDynamicSize = CopyFlags(C.MDBX_CP_FORCE_DYNAMIC_SIZE) 1760 ) 1761 1762 type CursorOp int32 1763 1764 const ( 1765 // CursorFirst Position at first key/data item 1766 CursorFirst = CursorOp(C.MDBX_FIRST) 1767 1768 // CursorFirstDup \ref MDBX_DUPSORT -only: Position at first data item of current key. 1769 CursorFirstDup = CursorOp(C.MDBX_FIRST_DUP) 1770 1771 // CursorGetBoth \ref MDBX_DUPSORT -only: Position at key/data pair. 1772 CursorGetBoth = CursorOp(C.MDBX_GET_BOTH) 1773 1774 // CursorGetBothRange \ref MDBX_DUPSORT -only: Position at given key and at first data greater 1775 // than or equal to specified data. 1776 CursorGetBothRange = CursorOp(C.MDBX_GET_BOTH_RANGE) 1777 1778 // CursorGetCurrent Return key/data at current cursor position 1779 CursorGetCurrent = CursorOp(C.MDBX_GET_CURRENT) 1780 1781 // CursorGetMultiple \ref MDBX_DUPFIXED -only: Return up to a page of duplicate data items 1782 // from current cursor position. Move cursor to prepare 1783 // for \ref MDBX_NEXT_MULTIPLE. 1784 CursorGetMultiple = CursorOp(C.MDBX_GET_MULTIPLE) 1785 1786 // CursorLast Position at last key/data item 1787 CursorLast = CursorOp(C.MDBX_LAST) 1788 1789 // CursorLastDup \ref MDBX_DUPSORT -only: Position at last data item of current key. 1790 CursorLastDup = CursorOp(C.MDBX_LAST_DUP) 1791 1792 // CursorNext Position at next data item 1793 CursorNext = CursorOp(C.MDBX_NEXT) 1794 1795 // CursorNextDup \ref MDBX_DUPSORT -only: Position at next data item of current key. 1796 CursorNextDup = CursorOp(C.MDBX_NEXT_DUP) 1797 1798 // CursorNextMultiple \ref MDBX_DUPFIXED -only: Return up to a page of duplicate data items 1799 // from next cursor position. Move cursor to prepare 1800 // for `MDBX_NEXT_MULTIPLE`. 1801 CursorNextMultiple = CursorOp(C.MDBX_NEXT_MULTIPLE) 1802 1803 // CursorNextNoDup Position at first data item of next key 1804 CursorNextNoDup = CursorOp(C.MDBX_NEXT_NODUP) 1805 1806 // CursorPrev Position at previous data item 1807 CursorPrev = CursorOp(C.MDBX_PREV) 1808 1809 // CursorPrevDup \ref MDBX_DUPSORT -only: Position at previous data item of current key. 1810 CursorPrevDup = CursorOp(C.MDBX_PREV_DUP) 1811 1812 // CursorPrevNoDup Position at last data item of previous key 1813 CursorPrevNoDup = CursorOp(C.MDBX_PREV_NODUP) 1814 1815 // CursorSet Position at specified key 1816 CursorSet = CursorOp(C.MDBX_SET) 1817 1818 // CursorSetKey Position at specified key, return both key and data 1819 CursorSetKey = CursorOp(C.MDBX_SET_KEY) 1820 1821 // CursorSetRange Position at first key greater than or equal to specified key. 1822 CursorSetRange = CursorOp(C.MDBX_SET_RANGE) 1823 1824 // CursorPrevMultiple \ref MDBX_DUPFIXED -only: Position at previous page and return up to 1825 // a page of duplicate data items. 1826 CursorPrevMultiple = CursorOp(C.MDBX_PREV_MULTIPLE) 1827 1828 // CursorSetLowerBound Positions cursor at first key-value pair greater than or equal to 1829 // specified, return both key and data, and the return code depends on whether 1830 // a exact match. 1831 // 1832 // For non DUPSORT-ed collections this work the same to \ref MDBX_SET_RANGE, 1833 // but returns \ref MDBX_SUCCESS if key found exactly or 1834 // \ref MDBX_RESULT_TRUE if greater key was found. 1835 // 1836 // For DUPSORT-ed a data value is taken into account for duplicates, 1837 // i.e. for a pairs/tuples of a key and an each data value of duplicates. 1838 // Returns \ref MDBX_SUCCESS if key-value pair found exactly or 1839 // \ref MDBX_RESULT_TRUE if the next pair was returned./// 1840 CursorSetLowerBound = CursorOp(C.MDBX_SET_LOWERBOUND) 1841 1842 // CursorSetUpperBound Positions cursor at first key-value pair greater than specified, 1843 // return both key and data, and the return code depends on whether a 1844 // upper-bound was found. 1845 // 1846 // For non DUPSORT-ed collections this work the same to \ref MDBX_SET_RANGE, 1847 // but returns \ref MDBX_SUCCESS if the greater key was found or 1848 // \ref MDBX_NOTFOUND otherwise. 1849 // 1850 // For DUPSORT-ed a data value is taken into account for duplicates, 1851 // i.e. for a pairs/tuples of a key and an each data value of duplicates. 1852 // Returns \ref MDBX_SUCCESS if the greater pair was returned or 1853 // \ref MDBX_NOTFOUND otherwise./// 1854 CursorSetUpperBound = CursorOp(C.MDBX_SET_UPPERBOUND) 1855 ) 1856 1857 type Opt int32 1858 1859 const ( 1860 // OptMaxDB \brief Controls the maximum number of named databases for the environment. 1861 // 1862 // \details By default only unnamed key-value database could used and 1863 // appropriate value should set by `MDBX_opt_max_db` to using any more named 1864 // subDB(s). To reduce overhead, use the minimum sufficient value. This option 1865 // may only set after \ref mdbx_env_create() and before \ref mdbx_env_open(). 1866 // 1867 // \see mdbx_env_set_maxdbs() \see mdbx_env_get_maxdbs() 1868 OptMaxDB = Opt(C.MDBX_opt_max_db) 1869 1870 // OptMaxReaders \brief Defines the maximum number of threads/reader slots 1871 // for all processes interacting with the database. 1872 // 1873 // \details This defines the number of slots in the lock table that is used to 1874 // track readers in the the environment. The default is about 100 for 4K 1875 // system page size. Starting a read-only transaction normally ties a lock 1876 // table slot to the current thread until the environment closes or the thread 1877 // exits. If \ref MDBX_NOTLS is in use, \ref mdbx_txn_begin() instead ties the 1878 // slot to the \ref MDBX_txn object until it or the \ref MDBX_env object is 1879 // destroyed. This option may only set after \ref mdbx_env_create() and before 1880 // \ref mdbx_env_open(), and has an effect only when the database is opened by 1881 // the first process interacts with the database. 1882 // 1883 // \see mdbx_env_set_maxreaders() \see mdbx_env_get_maxreaders() 1884 OptMaxReaders = Opt(C.MDBX_opt_max_readers) 1885 1886 // OptSyncBytes \brief Controls interprocess/shared threshold to force flush the data 1887 // buffers to disk, if \ref MDBX_SAFE_NOSYNC is used. 1888 // 1889 // \see mdbx_env_set_syncbytes() \see mdbx_env_get_syncbytes() 1890 OptSyncBytes = Opt(C.MDBX_opt_sync_bytes) 1891 1892 // OptSyncPeriod \brief Controls interprocess/shared relative period since the last 1893 // unsteady commit to force flush the data buffers to disk, 1894 // if \ref MDBX_SAFE_NOSYNC is used. 1895 // \see mdbx_env_set_syncperiod() \see mdbx_env_get_syncperiod() 1896 OptSyncPeriod = Opt(C.MDBX_opt_sync_period) 1897 1898 // OptRpAugmentLimit \brief Controls the in-process limit to grow a list of reclaimed/recycled 1899 // page's numbers for finding a sequence of contiguous pages for large data 1900 // items. 1901 // 1902 // \details A long values requires allocation of contiguous database pages. 1903 // To find such sequences, it may be necessary to accumulate very large lists, 1904 // especially when placing very long values (more than a megabyte) in a large 1905 // databases (several tens of gigabytes), which is much expensive in extreme 1906 // cases. This threshold allows you to avoid such costs by allocating new 1907 // pages at the end of the database (with its possible growth on disk), 1908 // instead of further accumulating/reclaiming Garbage Collection records. 1909 // 1910 // On the other hand, too small threshold will lead to unreasonable database 1911 // growth, or/and to the inability of put long values. 1912 // 1913 // The `MDBX_opt_rp_augment_limit` controls described limit for the current 1914 // process. Default is 262144, it is usually enough for most cases. 1915 OptRpAugmentLimit = Opt(C.MDBX_opt_rp_augment_limit) 1916 1917 // OptLooseLimit \brief Controls the in-process limit to grow a cache of dirty 1918 // pages for reuse in the current transaction. 1919 // 1920 // \details A 'dirty page' refers to a page that has been updated in memory 1921 // only, the changes to a dirty page are not yet stored on disk. 1922 // To reduce overhead, it is reasonable to release not all such pages 1923 // immediately, but to leave some ones in cache for reuse in the current 1924 // transaction. 1925 // 1926 // The `MDBX_opt_loose_limit` allows you to set a limit for such cache inside 1927 // the current process. Should be in the range 0..255, default is 64. 1928 OptLooseLimit = Opt(C.MDBX_opt_loose_limit) 1929 1930 // OptDpReserveLimit \brief Controls the in-process limit of a pre-allocated memory items 1931 // for dirty pages. 1932 // 1933 // \details A 'dirty page' refers to a page that has been updated in memory 1934 // only, the changes to a dirty page are not yet stored on disk. 1935 // Without \ref MDBX_WRITEMAP dirty pages are allocated from memory and 1936 // released when a transaction is committed. To reduce overhead, it is 1937 // reasonable to release not all ones, but to leave some allocations in 1938 // reserve for reuse in the next transaction(s). 1939 // 1940 // The `MDBX_opt_dp_reserve_limit` allows you to set a limit for such reserve 1941 // inside the current process. Default is 1024. 1942 OptDpReserveLimit = Opt(C.MDBX_opt_dp_reserve_limit) 1943 1944 // OptTxnDpLimit \brief Controls the in-process limit of dirty pages 1945 // for a write transaction. 1946 // 1947 // \details A 'dirty page' refers to a page that has been updated in memory 1948 // only, the changes to a dirty page are not yet stored on disk. 1949 // Without \ref MDBX_WRITEMAP dirty pages are allocated from memory and will 1950 // be busy until are written to disk. Therefore for a large transactions is 1951 // reasonable to limit dirty pages collecting above an some threshold but 1952 // spill to disk instead. 1953 // 1954 // The `MDBX_opt_txn_dp_limit` controls described threshold for the current 1955 // process. Default is 65536, it is usually enough for most cases. 1956 OptTxnDpLimit = Opt(C.MDBX_opt_txn_dp_limit) 1957 1958 // OptTxnDpInitial \brief Controls the in-process initial allocation size for dirty pages 1959 // list of a write transaction. Default is 1024. 1960 OptTxnDpInitial = Opt(C.MDBX_opt_txn_dp_initial) 1961 1962 // OptSpillMaxDenomiator \brief Controls the in-process how maximal part of the dirty pages may be 1963 // spilled when necessary. 1964 // 1965 // \details The `MDBX_opt_spill_max_denominator` defines the denominator for 1966 // limiting from the top for part of the current dirty pages may be spilled 1967 // when the free room for a new dirty pages (i.e. distance to the 1968 // `MDBX_opt_txn_dp_limit` threshold) is not enough to perform requested 1969 // operation. 1970 // Exactly `max_pages_to_spill = dirty_pages - dirty_pages / N`, 1971 // where `N` is the value set by `MDBX_opt_spill_max_denominator`. 1972 // 1973 // Should be in the range 0..255, where zero means no limit, i.e. all dirty 1974 // pages could be spilled. Default is 8, i.e. no more than 7/8 of the current 1975 // dirty pages may be spilled when reached the condition described above. 1976 OptSpillMaxDenomiator = Opt(C.MDBX_opt_spill_max_denominator) 1977 1978 // OptSpillMinDenomiator \brief Controls the in-process how minimal part of the dirty pages should 1979 // be spilled when necessary. 1980 // 1981 // \details The `MDBX_opt_spill_min_denominator` defines the denominator for 1982 // limiting from the bottom for part of the current dirty pages should be 1983 // spilled when the free room for a new dirty pages (i.e. distance to the 1984 // `MDBX_opt_txn_dp_limit` threshold) is not enough to perform requested 1985 // operation. 1986 // Exactly `min_pages_to_spill = dirty_pages / N`, 1987 // where `N` is the value set by `MDBX_opt_spill_min_denominator`. 1988 // 1989 // Should be in the range 0..255, where zero means no restriction at the 1990 // bottom. Default is 8, i.e. at least the 1/8 of the current dirty pages 1991 // should be spilled when reached the condition described above. 1992 OptSpillMinDenomiator = Opt(C.MDBX_opt_spill_min_denominator) 1993 1994 // OptSpillParent4ChildDenominator \brief Controls the in-process how much of the parent transaction dirty 1995 // pages will be spilled while start each child transaction. 1996 // 1997 // \details The `MDBX_opt_spill_parent4child_denominator` defines the 1998 // denominator to determine how much of parent transaction dirty pages will be 1999 // spilled explicitly while start each child transaction. 2000 // Exactly `pages_to_spill = dirty_pages / N`, 2001 // where `N` is the value set by `MDBX_opt_spill_parent4child_denominator`. 2002 // 2003 // For a stack of nested transactions each dirty page could be spilled only 2004 // once, and parent's dirty pages couldn't be spilled while child 2005 // transaction(s) are running. Therefore a child transaction could reach 2006 // \ref MDBX_TXN_FULL when parent(s) transaction has spilled too less (and 2007 // child reach the limit of dirty pages), either when parent(s) has spilled 2008 // too more (since child can't spill already spilled pages). So there is no 2009 // universal golden ratio. 2010 // 2011 // Should be in the range 0..255, where zero means no explicit spilling will 2012 // be performed during starting nested transactions. 2013 // Default is 0, i.e. by default no spilling performed during starting nested 2014 // transactions, that correspond historically behaviour. 2015 OptSpillParent4ChildDenominator = Opt(C.MDBX_opt_spill_parent4child_denominator) 2016 2017 // OptMergeThreshold16Dot16Percent \brief Controls the in-process threshold of semi-empty pages merge. 2018 // \warning This is experimental option and subject for change or removal. 2019 // \details This option controls the in-process threshold of minimum page 2020 // fill, as used space of percentage of a page. Neighbour pages emptier than 2021 // this value are candidates for merging. The threshold value is specified 2022 // in 1/65536 of percent, which is equivalent to the 16-dot-16 fixed point 2023 // format. The specified value must be in the range from 12.5% (almost empty) 2024 // to 50% (half empty) which corresponds to the range from 8192 and to 32768 2025 // in units respectively. 2026 OptMergeThreshold16Dot16Percent = Opt(C.MDBX_opt_merge_threshold_16dot16_percent) 2027 ) 2028 2029 type DeleteMode int32 2030 2031 const ( 2032 // DeleteModeJustDelete \brief Just delete the environment's files and directory if any. 2033 // \note On POSIX systems, processes already working with the database will 2034 // continue to work without interference until it close the environment. 2035 // \note On Windows, the behavior of `MDB_ENV_JUST_DELETE` is different 2036 // because the system does not support deleting files that are currently 2037 // memory mapped. 2038 DeleteModeJustDelete = DeleteMode(C.MDBX_ENV_JUST_DELETE) 2039 2040 // DeleteModeEnsureUnused \brief Make sure that the environment is not being used by other 2041 // processes, or return an error otherwise. 2042 DeleteModeEnsureUnused = DeleteMode(C.MDBX_ENV_ENSURE_UNUSED) 2043 2044 // DeleteModeWaitForUnused \brief Wait until other processes closes the environment before deletion. 2045 DeleteModeWaitForUnused = DeleteMode(C.MDBX_ENV_WAIT_FOR_UNUSED) 2046 ) 2047 2048 type DBIState uint32 2049 2050 const ( 2051 DBIStateDirty = DBIState(C.MDBX_DBI_DIRTY) // DB was written in this txn 2052 DBIStateState = DBIState(C.MDBX_DBI_STALE) // Named-DB record is older than txnID 2053 DBIStateFresh = DBIState(C.MDBX_DBI_FRESH) // Named-DB handle opened in this txn 2054 DBIStateCreat = DBIState(C.MDBX_DBI_CREAT) // Named-DB handle created in this txn 2055 ) 2056 2057 // Delete \brief Delete the environment's files in a proper and multiprocess-safe way. 2058 // \ingroup c_extra 2059 // 2060 // \param [in] pathname The pathname for the database or the directory in which 2061 // 2062 // the database files reside. 2063 // 2064 // \param [in] mode Special deletion mode for the environment. This 2065 // 2066 // parameter must be set to one of the values described 2067 // above in the \ref MDBX_env_delete_mode_t section. 2068 // 2069 // \note The \ref MDBX_ENV_JUST_DELETE don't supported on Windows since system 2070 // unable to delete a memory-mapped files. 2071 // 2072 // \returns A non-zero error value on failure and 0 on success, 2073 // 2074 // some possible errors are: 2075 // 2076 // \retval MDBX_RESULT_TRUE No corresponding files or directories were found, 2077 // 2078 // so no deletion was performed. 2079 func Delete(path string, mode DeleteMode) Error { 2080 p := C.CString(path) 2081 defer C.free(unsafe.Pointer(p)) 2082 return Error(C.mdbx_env_delete(p, (C.MDBX_env_delete_mode_t)(mode))) 2083 } 2084 2085 ////////////////////////////////////////////////////////////////////////////////////////// 2086 // Env 2087 ////////////////////////////////////////////////////////////////////////////////////////// 2088 2089 type Env struct { 2090 env *C.MDBX_env 2091 opened int64 2092 info EnvInfo 2093 closed int64 2094 mu sync.Mutex 2095 } 2096 2097 // NewEnv \brief Create an MDBX environment instance. 2098 // \ingroup c_opening 2099 // 2100 // This function allocates memory for a \ref MDBX_env structure. To release 2101 // the allocated memory and discard the handle, call \ref mdbx_env_close(). 2102 // Before the handle may be used, it must be opened using \ref mdbx_env_open(). 2103 // 2104 // Various other options may also need to be set before opening the handle, 2105 // e.g. \ref mdbx_env_set_geometry(), \ref mdbx_env_set_maxreaders(), 2106 // \ref mdbx_env_set_maxdbs(), depending on usage requirements. 2107 // 2108 // \param [out] penv The address where the new handle will be stored. 2109 // 2110 // \returns a non-zero error value on failure and 0 on success. 2111 func NewEnv() (*Env, Error) { 2112 env := &Env{} 2113 err := Error(C.mdbx_env_create((**C.MDBX_env)(unsafe.Pointer(&env.env)))) 2114 if err != ErrSuccess { 2115 return nil, err 2116 } 2117 return env, err 2118 } 2119 2120 // FD returns the open file descriptor (or Windows file handle) for the given 2121 // environment. An error is returned if the environment has not been 2122 // successfully Opened (where C API just retruns an invalid handle). 2123 // 2124 // See mdbx_env_get_fd. 2125 func (env *Env) FD() (uintptr, error) { 2126 // fdInvalid is the value -1 as a uintptr, which is used by MDBX in the 2127 // case that env has not been opened yet. the strange construction is done 2128 // to avoid constant value overflow errors at compile time. 2129 const fdInvalid = ^uintptr(0) 2130 2131 var mf C.mdbx_filehandle_t 2132 err := Error(C.mdbx_env_get_fd(env.env, &mf)) 2133 //err := operrno("mdbx_env_get_fd", ret) 2134 if err != ErrSuccess { 2135 return 0, err 2136 } 2137 fd := uintptr(mf) 2138 2139 if fd == fdInvalid { 2140 return 0, os.ErrClosed 2141 } 2142 return fd, nil 2143 } 2144 2145 // ReaderList dumps the contents of the reader lock table as text. Readers 2146 // start on the second line as space-delimited fields described by the first 2147 // line. 2148 // 2149 // See mdbx_reader_list. 2150 //func (env *Env) ReaderList(fn func(string) error) error { 2151 // ctx, done := newMsgFunc(fn) 2152 // defer done() 2153 // if fn == nil { 2154 // ctx = 0 2155 // } 2156 // 2157 // ret := C.mdbxgo_reader_list(env._env, C.size_t(ctx)) 2158 // if ret >= 0 { 2159 // return nil 2160 // } 2161 // if ret < 0 && ctx != 0 { 2162 // err := ctx.get().err 2163 // if err != nil { 2164 // return err 2165 // } 2166 // } 2167 // return operrno("mdbx_reader_list", ret) 2168 //} 2169 2170 // ReaderCheck clears stale entries from the reader lock table and returns the 2171 // number of entries cleared. 2172 // 2173 // See mdbx_reader_check() 2174 func (env *Env) ReaderCheck() (int, error) { 2175 var dead C.int 2176 err := Error(C.mdbx_reader_check(env.env, &dead)) 2177 if err != ErrSuccess { 2178 return int(dead), err 2179 } 2180 return int(dead), nil 2181 } 2182 2183 // Path returns the path argument passed to Open. Path returns a non-nil error 2184 // if env.Open() was not previously called. 2185 // 2186 // See mdbx_env_get_path. 2187 func (env *Env) Path() (string, error) { 2188 var cpath *C.char 2189 err := Error(C.mdbx_env_get_path(env.env, &cpath)) 2190 if err != ErrSuccess { 2191 return "", err 2192 } 2193 if cpath == nil { 2194 return "", os.ErrNotExist 2195 } 2196 return C.GoString(cpath), nil 2197 } 2198 2199 // MaxKeySize returns the maximum allowed length for a key. 2200 // 2201 // See mdbx_env_get_maxkeysize. 2202 func (env *Env) MaxKeySize() int { 2203 if env == nil { 2204 return int(C.mdbx_env_get_maxkeysize_ex(nil, 0)) 2205 } 2206 return int(C.mdbx_env_get_maxkeysize_ex(env.env, 0)) 2207 } 2208 2209 // Close the environment and release the memory map. 2210 // \ingroup c_opening 2211 // 2212 // Only a single thread may call this function. All transactions, databases, 2213 // and cursors must already be closed before calling this function. Attempts 2214 // to use any such handles after calling this function will cause a `SIGSEGV`. 2215 // The environment handle will be freed and must not be used again after this 2216 // call. 2217 // 2218 // \param [in] env An environment handle returned by 2219 // 2220 // \ref mdbx_env_create(). 2221 // 2222 // \param [in] dont_sync A dont'sync flag, if non-zero the last checkpoint 2223 // 2224 // will be kept "as is" and may be still "weak" in the 2225 // \ref MDBX_SAFE_NOSYNC or \ref MDBX_UTTERLY_NOSYNC 2226 // modes. Such "weak" checkpoint will be ignored on 2227 // opening next time, and transactions since the last 2228 // non-weak checkpoint (meta-page update) will rolledback 2229 // for consistency guarantee. 2230 // 2231 // \returns A non-zero error value on failure and 0 on success, 2232 // 2233 // some possible errors are: 2234 // 2235 // \retval MDBX_BUSY The write transaction is running by other thread, 2236 // 2237 // in such case \ref MDBX_env instance has NOT be destroyed 2238 // not released! 2239 // \note If any OTHER error code was returned then 2240 // given MDBX_env instance has been destroyed and released. 2241 // 2242 // \retval MDBX_EBADSIGN Environment handle already closed or not valid, 2243 // 2244 // i.e. \ref mdbx_env_close() was already called for the 2245 // `env` or was not created by \ref mdbx_env_create(). 2246 // 2247 // \retval MDBX_PANIC If \ref mdbx_env_close_ex() was called in the child 2248 // 2249 // process after `fork()`. In this case \ref MDBX_PANIC 2250 // is expected, i.e. \ref MDBX_env instance was freed in 2251 // proper manner. 2252 // 2253 // \retval MDBX_EIO An error occurred during synchronization. 2254 func (env *Env) Close(dontSync bool) Error { 2255 env.mu.Lock() 2256 defer env.mu.Unlock() 2257 if env.closed > 0 { 2258 return ErrSuccess 2259 } 2260 err := Error(C.mdbx_env_close_ex(env.env, (C.bool)(dontSync))) 2261 if err != ErrSuccess { 2262 return err 2263 } 2264 env.closed = time.Now().UnixNano() 2265 return err 2266 } 2267 2268 // SetFlags Set environment flags. 2269 // \ingroup c_settings 2270 // 2271 // This may be used to set some flags in addition to those from 2272 // mdbx_env_open(), or to unset these flags. 2273 // \see mdbx_env_get_flags() 2274 // 2275 // \note In contrast to LMDB, the MDBX serialize threads via mutex while 2276 // changing the flags. Therefore this function will be blocked while a write 2277 // transaction running by other thread, or \ref MDBX_BUSY will be returned if 2278 // function called within a write transaction. 2279 // 2280 // \param [in] env An environment handle returned 2281 // 2282 // by \ref mdbx_env_create(). 2283 // 2284 // \param [in] flags The \ref env_flags to change, bitwise OR'ed together. 2285 // \param [in] onoff A non-zero value sets the flags, zero clears them. 2286 // 2287 // \returns A non-zero error value on failure and 0 on success, 2288 // 2289 // some possible errors are: 2290 // 2291 // \retval MDBX_EINVAL An invalid parameter was specified. 2292 func (env *Env) SetFlags(flags EnvFlags, onoff bool) Error { 2293 return Error(C.mdbx_env_set_flags(env.env, (C.MDBX_env_flags_t)(flags), (C.bool)(onoff))) 2294 } 2295 2296 // GetFlags Get environment flags. 2297 // \ingroup c_statinfo 2298 // \see mdbx_env_set_flags() 2299 // 2300 // \param [in] env An environment handle returned by \ref mdbx_env_create(). 2301 // \param [out] flags The address of an integer to store the flags. 2302 // 2303 // \returns A non-zero error value on failure and 0 on success, 2304 // 2305 // some possible errors are: 2306 // 2307 // \retval MDBX_EINVAL An invalid parameter was specified. 2308 func (env *Env) GetFlags() (EnvFlags, Error) { 2309 flags := C.unsigned(0) 2310 err := Error(C.mdbx_env_get_flags(env.env, &flags)) 2311 return EnvFlags(flags), err 2312 } 2313 2314 // Copy an MDBX environment to the specified path, with options. 2315 // \ingroup c_extra 2316 // 2317 // This function may be used to make a backup of an existing environment. 2318 // No lockfile is created, since it gets recreated at need. 2319 // \note This call can trigger significant file size growth if run in 2320 // parallel with write transactions, because it employs a read-only 2321 // transaction. See long-lived transactions under \ref restrictions section. 2322 // 2323 // \param [in] env An environment handle returned by mdbx_env_create(). 2324 // 2325 // It must have already been opened successfully. 2326 // 2327 // \param [in] dest The pathname of a file in which the copy will reside. 2328 // 2329 // This file must not be already exist, but parent directory 2330 // must be writable. 2331 // 2332 // \param [in] flags Special options for this operation. This parameter must 2333 // 2334 // be set to 0 or by bitwise OR'ing together one or more 2335 // of the values described here: 2336 // 2337 // - \ref MDBX_CP_COMPACT 2338 // Perform compaction while copying: omit free pages and sequentially 2339 // renumber all pages in output. This option consumes little bit more 2340 // CPU for processing, but may running quickly than the default, on 2341 // account skipping free pages. 2342 // 2343 // - \ref MDBX_CP_FORCE_DYNAMIC_SIZE 2344 // Force to make resizeable copy, i.e. dynamic size instead of fixed. 2345 // 2346 // \returns A non-zero error value on failure and 0 on success. 2347 func (env *Env) Copy(dest string, flags CopyFlags) Error { 2348 if env.env == nil { 2349 return ErrSuccess 2350 } 2351 d := C.CString(dest) 2352 defer C.free(unsafe.Pointer(d)) 2353 return Error(C.mdbx_env_copy(env.env, d, (C.MDBX_copy_flags_t)(flags))) 2354 } 2355 2356 // Open \brief Open an environment instance. 2357 // \ingroup c_opening 2358 // 2359 // Indifferently this function will fails or not, the \ref mdbx_env_close() must 2360 // be called later to discard the \ref MDBX_env handle and release associated 2361 // resources. 2362 // 2363 // \param [in] env An environment handle returned 2364 // 2365 // by \ref mdbx_env_create() 2366 // 2367 // \param [in] pathname The pathname for the database or the directory in which 2368 // 2369 // the database files reside. In the case of directory it 2370 // must already exist and be writable. 2371 // 2372 // \param [in] flags Special options for this environment. This parameter 2373 // 2374 // must be set to 0 or by bitwise OR'ing together one 2375 // or more of the values described above in the 2376 // \ref env_flags and \ref sync_modes sections. 2377 // 2378 // Flags set by mdbx_env_set_flags() are also used: 2379 // 2380 // - \ref MDBX_NOSUBDIR, \ref MDBX_RDONLY, \ref MDBX_EXCLUSIVE, 2381 // \ref MDBX_WRITEMAP, \ref MDBX_NOTLS, \ref MDBX_NORDAHEAD, 2382 // \ref MDBX_NOMEMINIT, \ref MDBX_COALESCE, \ref MDBX_LIFORECLAIM. 2383 // See \ref env_flags section. 2384 // 2385 // - \ref MDBX_NOMETASYNC, \ref MDBX_SAFE_NOSYNC, \ref MDBX_UTTERLY_NOSYNC. 2386 // See \ref sync_modes section. 2387 // 2388 // \note `MDB_NOLOCK` flag don't supported by MDBX, 2389 // 2390 // try use \ref MDBX_EXCLUSIVE as a replacement. 2391 // 2392 // \note MDBX don't allow to mix processes with different \ref MDBX_SAFE_NOSYNC 2393 // 2394 // flags on the same environment. 2395 // In such case \ref MDBX_INCOMPATIBLE will be returned. 2396 // 2397 // If the database is already exist and parameters specified early by 2398 // \ref mdbx_env_set_geometry() are incompatible (i.e. for instance, different 2399 // page size) then \ref mdbx_env_open() will return \ref MDBX_INCOMPATIBLE 2400 // error. 2401 // 2402 // \param [in] mode The UNIX permissions to set on created files. 2403 // 2404 // Zero value means to open existing, but do not create. 2405 // 2406 // \return A non-zero error value on failure and 0 on success, 2407 // 2408 // some possible errors are: 2409 // 2410 // \retval MDBX_VERSION_MISMATCH The version of the MDBX library doesn't match 2411 // 2412 // the version that created the database environment. 2413 // 2414 // \retval MDBX_INVALID The environment file headers are corrupted. 2415 // \retval MDBX_ENOENT The directory specified by the path parameter 2416 // 2417 // doesn't exist. 2418 // 2419 // \retval MDBX_EACCES The user didn't have permission to access 2420 // 2421 // the environment files. 2422 // 2423 // \retval MDBX_EAGAIN The environment was locked by another process. 2424 // \retval MDBX_BUSY The \ref MDBX_EXCLUSIVE flag was specified and the 2425 // 2426 // environment is in use by another process, 2427 // or the current process tries to open environment 2428 // more than once. 2429 // 2430 // \retval MDBX_INCOMPATIBLE Environment is already opened by another process, 2431 // 2432 // but with different set of \ref MDBX_SAFE_NOSYNC, 2433 // \ref MDBX_UTTERLY_NOSYNC flags. 2434 // Or if the database is already exist and parameters 2435 // specified early by \ref mdbx_env_set_geometry() 2436 // are incompatible (i.e. different pagesize, etc). 2437 // 2438 // \retval MDBX_WANNA_RECOVERY The \ref MDBX_RDONLY flag was specified but 2439 // 2440 // read-write access is required to rollback 2441 // inconsistent state after a system crash. 2442 // 2443 // \retval MDBX_TOO_LARGE Database is too large for this process, 2444 // 2445 // i.e. 32-bit process tries to open >4Gb database. 2446 func (env *Env) Open(path string, flags EnvFlags, mode os.FileMode) Error { 2447 if env.opened > 0 { 2448 return ErrSuccess 2449 } 2450 2451 p := C.CString(path) 2452 defer C.free(unsafe.Pointer(p)) 2453 2454 err := Error(C.mdbx_env_open( 2455 (*C.MDBX_env)(unsafe.Pointer(env.env)), 2456 p, 2457 (C.MDBX_env_flags_t)(flags), 2458 (C.mdbx_mode_t)(mode), 2459 )) 2460 if err != ErrSuccess { 2461 return err 2462 } 2463 2464 env.opened = time.Now().UnixNano() 2465 return err 2466 } 2467 2468 type Geometry struct { 2469 env uintptr 2470 SizeLower uintptr 2471 SizeNow uintptr 2472 SizeUpper uintptr 2473 GrowthStep uintptr 2474 ShrinkThreshold uintptr 2475 PageSize uintptr 2476 err Error 2477 } 2478 2479 // SetGeometry Set all size-related parameters of environment, including page size 2480 // and the min/max size of the memory map. \ingroup c_settings 2481 // 2482 // In contrast to LMDB, the MDBX provide automatic size management of an 2483 // database according the given parameters, including shrinking and resizing 2484 // on the fly. From user point of view all of these just working. Nevertheless, 2485 // it is reasonable to know some details in order to make optimal decisions 2486 // when choosing parameters. 2487 // 2488 // Both \ref mdbx_env_info_ex() and legacy \ref mdbx_env_info() are inapplicable 2489 // to read-only opened environment. 2490 // 2491 // Both \ref mdbx_env_info_ex() and legacy \ref mdbx_env_info() could be called 2492 // either before or after \ref mdbx_env_open(), either within the write 2493 // transaction running by current thread or not: 2494 // 2495 // - In case \ref mdbx_env_info_ex() or legacy \ref mdbx_env_info() was called 2496 // BEFORE \ref mdbx_env_open(), i.e. for closed environment, then the 2497 // specified parameters will be used for new database creation, or will be 2498 // applied during opening if database exists and no other process using it. 2499 // 2500 // If the database is already exist, opened with \ref MDBX_EXCLUSIVE or not 2501 // used by any other process, and parameters specified by 2502 // \ref mdbx_env_set_geometry() are incompatible (i.e. for instance, 2503 // different page size) then \ref mdbx_env_open() will return 2504 // \ref MDBX_INCOMPATIBLE error. 2505 // 2506 // In another way, if database will opened read-only or will used by other 2507 // process during calling \ref mdbx_env_open() that specified parameters will 2508 // silently discarded (open the database with \ref MDBX_EXCLUSIVE flag 2509 // to avoid this). 2510 // 2511 // - In case \ref mdbx_env_info_ex() or legacy \ref mdbx_env_info() was called 2512 // after \ref mdbx_env_open() WITHIN the write transaction running by current 2513 // thread, then specified parameters will be applied as a part of write 2514 // transaction, i.e. will not be visible to any others processes until the 2515 // current write transaction has been committed by the current process. 2516 // However, if transaction will be aborted, then the database file will be 2517 // reverted to the previous size not immediately, but when a next transaction 2518 // will be committed or when the database will be opened next time. 2519 // 2520 // - In case \ref mdbx_env_info_ex() or legacy \ref mdbx_env_info() was called 2521 // after \ref mdbx_env_open() but OUTSIDE a write transaction, then MDBX will 2522 // execute internal pseudo-transaction to apply new parameters (but only if 2523 // anything has been changed), and changes be visible to any others processes 2524 // immediately after succesful completion of function. 2525 // 2526 // Essentially a concept of "automatic size management" is simple and useful: 2527 // - There are the lower and upper bound of the database file size; 2528 // - There is the growth step by which the database file will be increased, 2529 // in case of lack of space. 2530 // - There is the threshold for unused space, beyond which the database file 2531 // will be shrunk. 2532 // - The size of the memory map is also the maximum size of the database. 2533 // - MDBX will automatically manage both the size of the database and the size 2534 // of memory map, according to the given parameters. 2535 // 2536 // So, there some considerations about choosing these parameters: 2537 // - The lower bound allows you to prevent database shrinking below some 2538 // rational size to avoid unnecessary resizing costs. 2539 // - The upper bound allows you to prevent database growth above some rational 2540 // size. Besides, the upper bound defines the linear address space 2541 // reservation in each process that opens the database. Therefore changing 2542 // the upper bound is costly and may be required reopening environment in 2543 // case of \ref MDBX_UNABLE_EXTEND_MAPSIZE errors, and so on. Therefore, this 2544 // value should be chosen reasonable as large as possible, to accommodate 2545 // future growth of the database. 2546 // - The growth step must be greater than zero to allow the database to grow, 2547 // but also reasonable not too small, since increasing the size by little 2548 // steps will result a large overhead. 2549 // - The shrink threshold must be greater than zero to allow the database 2550 // to shrink but also reasonable not too small (to avoid extra overhead) and 2551 // not less than growth step to avoid up-and-down flouncing. 2552 // - The current size (i.e. size_now argument) is an auxiliary parameter for 2553 // simulation legacy \ref mdbx_env_set_mapsize() and as workaround Windows 2554 // issues (see below). 2555 // 2556 // Unfortunately, Windows has is a several issues 2557 // with resizing of memory-mapped file: 2558 // - Windows unable shrinking a memory-mapped file (i.e memory-mapped section) 2559 // in any way except unmapping file entirely and then map again. Moreover, 2560 // it is impossible in any way if a memory-mapped file is used more than 2561 // one process. 2562 // - Windows does not provide the usual API to augment a memory-mapped file 2563 // (that is, a memory-mapped partition), but only by using "Native API" 2564 // in an undocumented way. 2565 // 2566 // MDBX bypasses all Windows issues, but at a cost: 2567 // - Ability to resize database on the fly requires an additional lock 2568 // and release `SlimReadWriteLock during` each read-only transaction. 2569 // - During resize all in-process threads should be paused and then resumed. 2570 // - Shrinking of database file is performed only when it used by single 2571 // process, i.e. when a database closes by the last process or opened 2572 // by the first. 2573 // = Therefore, the size_now argument may be useful to set database size 2574 // by the first process which open a database, and thus avoid expensive 2575 // remapping further. 2576 // 2577 // For create a new database with particular parameters, including the page 2578 // size, \ref mdbx_env_set_geometry() should be called after 2579 // \ref mdbx_env_create() and before mdbx_env_open(). Once the database is 2580 // created, the page size cannot be changed. If you do not specify all or some 2581 // of the parameters, the corresponding default values will be used. For 2582 // instance, the default for database size is 10485760 bytes. 2583 // 2584 // If the mapsize is increased by another process, MDBX silently and 2585 // transparently adopt these changes at next transaction start. However, 2586 // \ref mdbx_txn_begin() will return \ref MDBX_UNABLE_EXTEND_MAPSIZE if new 2587 // mapping size could not be applied for current process (for instance if 2588 // address space is busy). Therefore, in the case of 2589 // \ref MDBX_UNABLE_EXTEND_MAPSIZE error you need close and reopen the 2590 // environment to resolve error. 2591 // 2592 // \note Actual values may be different than your have specified because of 2593 // rounding to specified database page size, the system page size and/or the 2594 // size of the system virtual memory management unit. You can get actual values 2595 // by \ref mdbx_env_sync_ex() or see by using the tool `mdbx_chk` with the `-v` 2596 // option. 2597 // 2598 // Legacy \ref mdbx_env_set_mapsize() correspond to calling 2599 // \ref mdbx_env_set_geometry() with the arguments `size_lower`, `size_now`, 2600 // `size_upper` equal to the `size` and `-1` (i.e. default) for all other 2601 // parameters. 2602 // 2603 // \param [in] env An environment handle returned 2604 // 2605 // by \ref mdbx_env_create() 2606 // 2607 // \param [in] size_lower The lower bound of database size in bytes. 2608 // 2609 // Zero value means "minimal acceptable", 2610 // and negative means "keep current or use default". 2611 // 2612 // \param [in] size_now The size in bytes to setup the database size for 2613 // 2614 // now. Zero value means "minimal acceptable", and 2615 // negative means "keep current or use default". So, 2616 // it is recommended always pass -1 in this argument 2617 // except some special cases. 2618 // 2619 // \param [in] size_upper The upper bound of database size in bytes. 2620 // 2621 // Zero value means "minimal acceptable", 2622 // and negative means "keep current or use default". 2623 // It is recommended to avoid change upper bound while 2624 // database is used by other processes or threaded 2625 // (i.e. just pass -1 in this argument except absolutely 2626 // necessary). Otherwise you must be ready for 2627 // \ref MDBX_UNABLE_EXTEND_MAPSIZE error(s), unexpected 2628 // pauses during remapping and/or system errors like 2629 // "address busy", and so on. In other words, there 2630 // is no way to handle a growth of the upper bound 2631 // robustly because there may be a lack of appropriate 2632 // system resources (which are extremely volatile in 2633 // a multi-process multi-threaded environment). 2634 // 2635 // \param [in] growth_step The growth step in bytes, must be greater than 2636 // 2637 // zero to allow the database to grow. Negative value 2638 // means "keep current or use default". 2639 // 2640 // \param [in] shrink_threshold The shrink threshold in bytes, must be greater 2641 // 2642 // than zero to allow the database to shrink and 2643 // greater than growth_step to avoid shrinking 2644 // right after grow. 2645 // Negative value means "keep current 2646 // or use default". Default is 2*growth_step. 2647 // 2648 // \param [in] pagesize The database page size for new database 2649 // 2650 // creation or -1 otherwise. Must be power of 2 2651 // in the range between \ref MDBX_MIN_PAGESIZE and 2652 // \ref MDBX_MAX_PAGESIZE. Zero value means 2653 // "minimal acceptable", and negative means 2654 // "keep current or use default". 2655 // 2656 // \returns A non-zero error value on failure and 0 on success, 2657 // 2658 // some possible errors are: 2659 // 2660 // \retval MDBX_EINVAL An invalid parameter was specified, 2661 // 2662 // or the environment has an active write transaction. 2663 // 2664 // \retval MDBX_EPERM Specific for Windows: Shrinking was disabled before 2665 // 2666 // and now it wanna be enabled, but there are reading 2667 // threads that don't use the additional `SRWL` (that 2668 // is required to avoid Windows issues). 2669 // 2670 // \retval MDBX_EACCESS The environment opened in read-only. 2671 // \retval MDBX_MAP_FULL Specified size smaller than the space already 2672 // 2673 // consumed by the environment. 2674 // 2675 // \retval MDBX_TOO_LARGE Specified size is too large, i.e. too many pages for 2676 // 2677 // given size, or a 32-bit process requests too much 2678 // bytes for the 32-bit address space. 2679 func (env *Env) SetGeometry(args Geometry) Error { 2680 args.env = uintptr(unsafe.Pointer(env.env)) 2681 ptr := uintptr(unsafe.Pointer(&args)) 2682 unsafecgo.NonBlocking((*byte)(C.do_mdbx_env_set_geometry), ptr, 0) 2683 return args.err 2684 } 2685 2686 // GetOption \brief Gets the value of runtime options from an environment. 2687 // \ingroup c_settings 2688 // 2689 // \param [in] env An environment handle returned by \ref mdbx_env_create(). 2690 // \param [in] option The option from \ref MDBX_option_t to get value of it. 2691 // \param [out] pvalue The address where the option's value will be stored. 2692 // 2693 // \see MDBX_option_t 2694 // \see mdbx_env_get_option() 2695 // \returns A non-zero error value on failure and 0 on success. 2696 func (env *Env) GetOption(option Opt) (uint64, Error) { 2697 value := uint64(0) 2698 err := Error(C.mdbx_env_get_option( 2699 (*C.MDBX_env)(unsafe.Pointer(env.env)), 2700 (C.MDBX_option_t)(option), 2701 (*C.uint64_t)(unsafe.Pointer(&value))), 2702 ) 2703 return value, err 2704 } 2705 2706 // SetOption \brief Sets the value of a runtime options for an environment. 2707 // \ingroup c_settings 2708 // 2709 // \param [in] env An environment handle returned by \ref mdbx_env_create(). 2710 // \param [in] option The option from \ref MDBX_option_t to set value of it. 2711 // \param [in] value The value of option to be set. 2712 // 2713 // \see MDBX_option_t 2714 // \see mdbx_env_get_option() 2715 // \returns A non-zero error value on failure and 0 on success. 2716 func (env *Env) SetOption(option Opt, value uint64) Error { 2717 return Error(C.mdbx_env_set_option( 2718 (*C.MDBX_env)(unsafe.Pointer(env.env)), 2719 (C.MDBX_option_t)(option), 2720 C.uint64_t(value)), 2721 ) 2722 } 2723 2724 type EnvInfo struct { 2725 Geo struct { 2726 Lower uint64 // Lower limit for datafile size 2727 Upper uint64 // Upper limit for datafile size 2728 Current uint64 // Current datafile size 2729 Shrink uint64 // Shrink threshold for datafile 2730 Grow uint64 // Growth step for datafile 2731 } 2732 MapSize uint64 // Size of the data memory map 2733 LastPageNumber uint64 // Number of the last used page 2734 RecentTxnID uint64 // ID of the last committed transaction 2735 LatterReaderTxnID uint64 // ID of the last reader transaction 2736 SelfLatterReaderTxnID uint64 // ID of the last reader transaction of caller process 2737 2738 Meta0TxnID, MIMeta0Sign uint64 2739 Meta1TxnID, MIMeta1Sign uint64 2740 Meta2TxnID, MIMeta2Sign uint64 2741 2742 MaxReaders uint32 // Total reader slots in the environment 2743 NumReaders uint32 // Max reader slots used in the environment 2744 DXBPageSize uint32 // Database pagesize 2745 SysPageSize uint32 // System pagesize 2746 2747 // BootID A mostly unique ID that is regenerated on each boot. 2748 // As such it can be used to identify the local machine's current boot. MDBX 2749 // uses such when open the database to determine whether rollback required to 2750 // the last steady sync point or not. I.e. if current bootid is differ from the 2751 // value within a database then the system was rebooted and all changes since 2752 // last steady sync must be reverted for data integrity. Zeros mean that no 2753 // relevant information is available from the system. 2754 BootID struct { 2755 Current, Meta0, Meta1, Meta2 struct{ X, Y uint64 } 2756 } 2757 2758 UnSyncVolume uint64 // Bytes not explicitly synchronized to disk. 2759 AutoSyncThreshold uint64 // Current auto-sync threshold, see \ref mdbx_env_set_syncbytes(). 2760 SinceSyncSeconds16Dot16 uint32 // Time since the last steady sync in 1/65536 of second 2761 AutoSyncPeriodSeconds16Dot16 uint32 // Current auto-sync period in 1/65536 of second, see \ref mdbx_env_set_syncperiod(). 2762 SinceReaderCheckSeconds16Dot16 uint32 // Time since the last readers check in 1/65536 of second, see \ref mdbx_reader_check() 2763 Mode uint32 // Current environment mode. The same as \ref mdbx_env_get_flags() returns. 2764 2765 // Statistics of page operations. 2766 // details Overall statistics of page operations of all (running, completed 2767 // and aborted) transactions in the current multi-process session (since the 2768 // first process opened the database after everyone had previously closed it). 2769 PGOpStat struct { 2770 Newly uint64 // Quantity of a new pages added 2771 Cow uint64 // Quantity of pages copied for update 2772 Clone uint64 // Quantity of parent's dirty pages clones for nested transactions 2773 Split uint64 // Page splits 2774 Merge uint64 // Page merges 2775 Spill uint64 // Quantity of spilled dirty pages 2776 UnSpill uint64 // Quantity of unspilled/reloaded pages 2777 Wops uint64 // Number of explicit write operations (not a pages) to a disk 2778 GCRTimeSeconds16dot16 uint64 // Time spent loading and searching inside GC (aka FreeDB) in 1/65536 of second. 2779 } 2780 } 2781 2782 // Sync Flush the environment data buffers to disk. 2783 // \ingroup c_extra 2784 // 2785 // Unless the environment was opened with no-sync flags (\ref MDBX_NOMETASYNC, 2786 // \ref MDBX_SAFE_NOSYNC and \ref MDBX_UTTERLY_NOSYNC), then 2787 // data is always written an flushed to disk when \ref mdbx_txn_commit() is 2788 // called. Otherwise \ref mdbx_env_sync() may be called to manually write and 2789 // flush unsynced data to disk. 2790 // 2791 // Besides, \ref mdbx_env_sync_ex() with argument `force=false` may be used to 2792 // provide polling mode for lazy/asynchronous sync in conjunction with 2793 // \ref mdbx_env_set_syncbytes() and/or \ref mdbx_env_set_syncperiod(). 2794 // 2795 // \note This call is not valid if the environment was opened with MDBX_RDONLY. 2796 // 2797 // \param [in] env An environment handle returned by \ref mdbx_env_create() 2798 // \param [in] force If non-zero, force a flush. Otherwise, If force is 2799 // 2800 // zero, then will run in polling mode, 2801 // i.e. it will check the thresholds that were 2802 // set \ref mdbx_env_set_syncbytes() 2803 // and/or \ref mdbx_env_set_syncperiod() and perform flush 2804 // if at least one of the thresholds is reached. 2805 // 2806 // \param [in] nonblock Don't wait if write transaction 2807 // 2808 // is running by other thread. 2809 // 2810 // \returns A non-zero error value on failure and \ref MDBX_RESULT_TRUE or 0 on 2811 // 2812 // success. The \ref MDBX_RESULT_TRUE means no data pending for flush 2813 // to disk, and 0 otherwise. Some possible errors are: 2814 // 2815 // \retval MDBX_EACCES the environment is read-only. 2816 // \retval MDBX_BUSY the environment is used by other thread 2817 // 2818 // and `nonblock=true`. 2819 // 2820 // \retval MDBX_EINVAL an invalid parameter was specified. 2821 // \retval MDBX_EIO an error occurred during synchronization. 2822 func (env *Env) Sync(force, nonblock bool) Error { 2823 return Error(C.mdbx_env_sync_ex(env.env, (C.bool)(force), (C.bool)(nonblock))) 2824 } 2825 2826 // CloseDBI Close a database handle. Normally unnecessary. 2827 // \ingroup c_dbi 2828 // 2829 // Closing a database handle is not necessary, but lets \ref mdbx_dbi_open() 2830 // reuse the handle value. Usually it's better to set a bigger 2831 // \ref mdbx_env_set_maxdbs(), unless that value would be large. 2832 // 2833 // \note Use with care. 2834 // This call is synchronized via mutex with \ref mdbx_dbi_close(), but NOT with 2835 // other transactions running by other threads. The "next" version of libmdbx 2836 // (\ref MithrilDB) will solve this issue. 2837 // 2838 // Handles should only be closed if no other threads are going to reference 2839 // the database handle or one of its cursors any further. Do not close a handle 2840 // if an existing transaction has modified its database. Doing so can cause 2841 // misbehavior from database corruption to errors like \ref MDBX_BAD_DBI 2842 // (since the DB name is gone). 2843 // 2844 // \param [in] env An environment handle returned by \ref mdbx_env_create(). 2845 // \param [in] dbi A database handle returned by \ref mdbx_dbi_open(). 2846 // 2847 // \returns A non-zero error value on failure and 0 on success. 2848 func (env *Env) CloseDBI(dbi DBI) Error { 2849 return Error(C.mdbx_dbi_close(env.env, (C.MDBX_dbi)(dbi))) 2850 } 2851 2852 // GetMaxDBS Controls the maximum number of named databases for the environment. 2853 // 2854 // \details By default only unnamed key-value database could used and 2855 // appropriate value should set by `MDBX_opt_max_db` to using any more named 2856 // subDB(s). To reduce overhead, use the minimum sufficient value. This option 2857 // may only set after \ref mdbx_env_create() and before \ref mdbx_env_open(). 2858 // 2859 // \see mdbx_env_set_maxdbs() \see mdbx_env_get_maxdbs() 2860 func (env *Env) GetMaxDBS() (uint64, Error) { 2861 return env.GetOption(OptMaxDB) 2862 } 2863 2864 // SetMaxDBS Controls the maximum number of named databases for the environment. 2865 // 2866 // \details By default only unnamed key-value database could used and 2867 // appropriate value should set by `MDBX_opt_max_db` to using any more named 2868 // subDB(s). To reduce overhead, use the minimum sufficient value. This option 2869 // may only set after \ref mdbx_env_create() and before \ref mdbx_env_open(). 2870 // 2871 // \see mdbx_env_set_maxdbs() \see mdbx_env_get_maxdbs() 2872 func (env *Env) SetMaxDBS(max uint16) Error { 2873 return env.SetOption(OptMaxDB, uint64(max)) 2874 } 2875 2876 // GetMaxReaders Defines the maximum number of threads/reader slots 2877 // for all processes interacting with the database. 2878 // 2879 // \details This defines the number of slots in the lock table that is used to 2880 // track readers in the the environment. The default is about 100 for 4K 2881 // system page size. Starting a read-only transaction normally ties a lock 2882 // table slot to the current thread until the environment closes or the thread 2883 // exits. If \ref MDBX_NOTLS is in use, \ref mdbx_txn_begin() instead ties the 2884 // slot to the \ref MDBX_txn object until it or the \ref MDBX_env object is 2885 // destroyed. This option may only set after \ref mdbx_env_create() and before 2886 // \ref mdbx_env_open(), and has an effect only when the database is opened by 2887 // the first process interacts with the database. 2888 // 2889 // \see mdbx_env_set_maxreaders() \see mdbx_env_get_maxreaders() 2890 func (env *Env) GetMaxReaders() (uint64, Error) { 2891 return env.GetOption(OptMaxReaders) 2892 } 2893 2894 // SetMaxReaders Defines the maximum number of threads/reader slots 2895 // for all processes interacting with the database. 2896 // 2897 // \details This defines the number of slots in the lock table that is used to 2898 // track readers in the the environment. The default is about 100 for 4K 2899 // system page size. Starting a read-only transaction normally ties a lock 2900 // table slot to the current thread until the environment closes or the thread 2901 // exits. If \ref MDBX_NOTLS is in use, \ref mdbx_txn_begin() instead ties the 2902 // slot to the \ref MDBX_txn object until it or the \ref MDBX_env object is 2903 // destroyed. This option may only set after \ref mdbx_env_create() and before 2904 // \ref mdbx_env_open(), and has an effect only when the database is opened by 2905 // the first process interacts with the database. 2906 // 2907 // \see mdbx_env_set_maxreaders() \see mdbx_env_get_maxreaders() 2908 func (env *Env) SetMaxReaders(max uint64) Error { 2909 return env.SetOption(OptMaxReaders, max) 2910 } 2911 2912 // GetSyncBytes Controls interprocess/shared threshold to force flush the data 2913 // buffers to disk, if \ref MDBX_SAFE_NOSYNC is used. 2914 // 2915 // \see mdbx_env_set_syncbytes() \see mdbx_env_get_syncbytes() 2916 func (env *Env) GetSyncBytes() (uint64, Error) { 2917 return env.GetOption(OptSyncBytes) 2918 } 2919 2920 // SetSyncBytes Controls interprocess/shared threshold to force flush the data 2921 // buffers to disk, if \ref MDBX_SAFE_NOSYNC is used. 2922 // 2923 // \see mdbx_env_set_syncbytes() \see mdbx_env_get_syncbytes() 2924 func (env *Env) SetSyncBytes(bytes uint64) Error { 2925 return env.SetOption(OptSyncBytes, bytes) 2926 } 2927 2928 // GetSyncPeriod Controls interprocess/shared relative period since the last 2929 // unsteady commit to force flush the data buffers to disk, 2930 // if \ref MDBX_SAFE_NOSYNC is used. 2931 // \see mdbx_env_set_syncperiod() \see mdbx_env_get_syncperiod() 2932 func (env *Env) GetSyncPeriod() (uint64, Error) { 2933 return env.GetOption(OptSyncPeriod) 2934 } 2935 2936 // SetSyncPeriod Controls interprocess/shared relative period since the last 2937 // unsteady commit to force flush the data buffers to disk, 2938 // if \ref MDBX_SAFE_NOSYNC is used. 2939 // \see mdbx_env_set_syncperiod() \see mdbx_env_get_syncperiod() 2940 func (env *Env) SetSyncPeriod(period uint64) Error { 2941 return env.SetOption(OptSyncPeriod, period) 2942 } 2943 2944 // GetRPAugmentLimit Controls the in-process limit to grow a list of reclaimed/recycled 2945 // page's numbers for finding a sequence of contiguous pages for large data 2946 // items. 2947 // 2948 // \details A long values requires allocation of contiguous database pages. 2949 // To find such sequences, it may be necessary to accumulate very large lists, 2950 // especially when placing very long values (more than a megabyte) in a large 2951 // databases (several tens of gigabytes), which is much expensive in extreme 2952 // cases. This threshold allows you to avoid such costs by allocating new 2953 // pages at the end of the database (with its possible growth on disk), 2954 // instead of further accumulating/reclaiming Garbage Collection records. 2955 // 2956 // On the other hand, too small threshold will lead to unreasonable database 2957 // growth, or/and to the inability of put long values. 2958 // 2959 // The `MDBX_opt_rp_augment_limit` controls described limit for the current 2960 // process. Default is 262144, it is usually enough for most cases. 2961 func (env *Env) GetRPAugmentLimit() (uint64, Error) { 2962 return env.GetOption(OptRpAugmentLimit) 2963 } 2964 2965 // SetRPAugmentLimit Controls the in-process limit to grow a list of reclaimed/recycled 2966 // page's numbers for finding a sequence of contiguous pages for large data 2967 // items. 2968 // 2969 // \details A long values requires allocation of contiguous database pages. 2970 // To find such sequences, it may be necessary to accumulate very large lists, 2971 // especially when placing very long values (more than a megabyte) in a large 2972 // databases (several tens of gigabytes), which is much expensive in extreme 2973 // cases. This threshold allows you to avoid such costs by allocating new 2974 // pages at the end of the database (with its possible growth on disk), 2975 // instead of further accumulating/reclaiming Garbage Collection records. 2976 // 2977 // On the other hand, too small threshold will lead to unreasonable database 2978 // growth, or/and to the inability of put long values. 2979 // 2980 // The `MDBX_opt_rp_augment_limit` controls described limit for the current 2981 // process. Default is 262144, it is usually enough for most cases. 2982 func (env *Env) SetRPAugmentLimit(limit uint64) Error { 2983 return env.SetOption(OptRpAugmentLimit, limit) 2984 } 2985 2986 // GetLooseLimit Controls the in-process limit to grow a cache of dirty 2987 // pages for reuse in the current transaction. 2988 // 2989 // \details A 'dirty page' refers to a page that has been updated in memory 2990 // only, the changes to a dirty page are not yet stored on disk. 2991 // To reduce overhead, it is reasonable to release not all such pages 2992 // immediately, but to leave some ones in cache for reuse in the current 2993 // transaction. 2994 // 2995 // The `MDBX_opt_loose_limit` allows you to set a limit for such cache inside 2996 // the current process. Should be in the range 0..255, default is 64. 2997 func (env *Env) GetLooseLimit() (uint64, Error) { 2998 return env.GetOption(OptLooseLimit) 2999 } 3000 3001 // SetLooseLimit Controls the in-process limit to grow a cache of dirty 3002 // pages for reuse in the current transaction. 3003 // 3004 // \details A 'dirty page' refers to a page that has been updated in memory 3005 // only, the changes to a dirty page are not yet stored on disk. 3006 // To reduce overhead, it is reasonable to release not all such pages 3007 // immediately, but to leave some ones in cache for reuse in the current 3008 // transaction. 3009 // 3010 // The `MDBX_opt_loose_limit` allows you to set a limit for such cache inside 3011 // the current process. Should be in the range 0..255, default is 64. 3012 func (env *Env) SetLooseLimit(limit uint64) Error { 3013 return env.SetOption(OptLooseLimit, limit) 3014 } 3015 3016 // GetDPReserveLimit Controls the in-process limit of a pre-allocated memory items 3017 // for dirty pages. 3018 // 3019 // \details A 'dirty page' refers to a page that has been updated in memory 3020 // only, the changes to a dirty page are not yet stored on disk. 3021 // Without \ref MDBX_WRITEMAP dirty pages are allocated from memory and 3022 // released when a transaction is committed. To reduce overhead, it is 3023 // reasonable to release not all ones, but to leave some allocations in 3024 // reserve for reuse in the next transaction(s). 3025 // 3026 // The `MDBX_opt_dp_reserve_limit` allows you to set a limit for such reserve 3027 // inside the current process. Default is 1024. 3028 func (env *Env) GetDPReserveLimit() (uint64, Error) { 3029 return env.GetOption(OptDpReserveLimit) 3030 } 3031 3032 // SetDPReserveLimit Controls the in-process limit of a pre-allocated memory items 3033 // for dirty pages. 3034 // 3035 // \details A 'dirty page' refers to a page that has been updated in memory 3036 // only, the changes to a dirty page are not yet stored on disk. 3037 // Without \ref MDBX_WRITEMAP dirty pages are allocated from memory and 3038 // released when a transaction is committed. To reduce overhead, it is 3039 // reasonable to release not all ones, but to leave some allocations in 3040 // reserve for reuse in the next transaction(s). 3041 // 3042 // The `MDBX_opt_dp_reserve_limit` allows you to set a limit for such reserve 3043 // inside the current process. Default is 1024. 3044 func (env *Env) SetDPReserveLimit(limit uint64) Error { 3045 return env.SetOption(OptDpReserveLimit, limit) 3046 } 3047 3048 // GetTxDPLimit Controls the in-process limit of dirty pages 3049 // for a write transaction. 3050 // 3051 // \details A 'dirty page' refers to a page that has been updated in memory 3052 // only, the changes to a dirty page are not yet stored on disk. 3053 // Without \ref MDBX_WRITEMAP dirty pages are allocated from memory and will 3054 // be busy until are written to disk. Therefore for a large transactions is 3055 // reasonable to limit dirty pages collecting above an some threshold but 3056 // spill to disk instead. 3057 // 3058 // The `MDBX_opt_txn_dp_limit` controls described threshold for the current 3059 // process. Default is 65536, it is usually enough for most cases. 3060 func (env *Env) GetTxDPLimit() (uint64, Error) { 3061 return env.GetOption(OptTxnDpLimit) 3062 } 3063 3064 // SetTxDPLimit Controls the in-process limit of dirty pages 3065 // for a write transaction. 3066 // 3067 // \details A 'dirty page' refers to a page that has been updated in memory 3068 // only, the changes to a dirty page are not yet stored on disk. 3069 // Without \ref MDBX_WRITEMAP dirty pages are allocated from memory and will 3070 // be busy until are written to disk. Therefore for a large transactions is 3071 // reasonable to limit dirty pages collecting above an some threshold but 3072 // spill to disk instead. 3073 // 3074 // The `MDBX_opt_txn_dp_limit` controls described threshold for the current 3075 // process. Default is 65536, it is usually enough for most cases. 3076 func (env *Env) SetTxDPLimit(limit uint64) Error { 3077 return env.SetOption(OptTxnDpLimit, limit) 3078 } 3079 3080 // GetTxDPInitial Controls the in-process initial allocation size for dirty pages 3081 // list of a write transaction. Default is 1024. 3082 func (env *Env) GetTxDPInitial() (uint64, Error) { 3083 return env.GetOption(OptTxnDpInitial) 3084 } 3085 3086 // SetTxDPInitial Controls the in-process initial allocation size for dirty pages 3087 // list of a write transaction. Default is 1024. 3088 func (env *Env) SetTxDPInitial(initial uint64) Error { 3089 return env.SetOption(OptTxnDpInitial, initial) 3090 } 3091 3092 // GetSpillMinDenominator Controls the in-process how minimal part of the dirty pages should 3093 // be spilled when necessary. 3094 // 3095 // \details The `MDBX_opt_spill_min_denominator` defines the denominator for 3096 // limiting from the bottom for part of the current dirty pages should be 3097 // spilled when the free room for a new dirty pages (i.e. distance to the 3098 // `MDBX_opt_txn_dp_limit` threshold) is not enough to perform requested 3099 // operation. 3100 // Exactly `min_pages_to_spill = dirty_pages / N`, 3101 // where `N` is the value set by `MDBX_opt_spill_min_denominator`. 3102 // 3103 // Should be in the range 0..255, where zero means no restriction at the 3104 // bottom. Default is 8, i.e. at least the 1/8 of the current dirty pages 3105 // should be spilled when reached the condition described above. 3106 func (env *Env) GetSpillMinDenominator() (uint64, Error) { 3107 return env.GetOption(OptSpillMinDenomiator) 3108 } 3109 3110 // SetSpillMinDenominator Controls the in-process how minimal part of the dirty pages should 3111 // be spilled when necessary. 3112 // 3113 // \details The `MDBX_opt_spill_min_denominator` defines the denominator for 3114 // limiting from the bottom for part of the current dirty pages should be 3115 // spilled when the free room for a new dirty pages (i.e. distance to the 3116 // `MDBX_opt_txn_dp_limit` threshold) is not enough to perform requested 3117 // operation. 3118 // Exactly `min_pages_to_spill = dirty_pages / N`, 3119 // where `N` is the value set by `MDBX_opt_spill_min_denominator`. 3120 // 3121 // Should be in the range 0..255, where zero means no restriction at the 3122 // bottom. Default is 8, i.e. at least the 1/8 of the current dirty pages 3123 // should be spilled when reached the condition described above. 3124 func (env *Env) SetSpillMinDenominator(min uint64) Error { 3125 return env.SetOption(OptSpillMinDenomiator, min) 3126 } 3127 3128 // GetSpillMaxDenominator Controls the in-process how maximal part of the dirty pages may be 3129 // spilled when necessary. 3130 // 3131 // \details The `MDBX_opt_spill_max_denominator` defines the denominator for 3132 // limiting from the top for part of the current dirty pages may be spilled 3133 // when the free room for a new dirty pages (i.e. distance to the 3134 // `MDBX_opt_txn_dp_limit` threshold) is not enough to perform requested 3135 // operation. 3136 // Exactly `max_pages_to_spill = dirty_pages - dirty_pages / N`, 3137 // where `N` is the value set by `MDBX_opt_spill_max_denominator`. 3138 // 3139 // Should be in the range 0..255, where zero means no limit, i.e. all dirty 3140 // pages could be spilled. Default is 8, i.e. no more than 7/8 of the current 3141 // dirty pages may be spilled when reached the condition described above. 3142 func (env *Env) GetSpillMaxDenominator() (uint64, Error) { 3143 return env.GetOption(OptSpillMaxDenomiator) 3144 } 3145 3146 // SetSpillMaxDenominator Controls the in-process how maximal part of the dirty pages may be 3147 // spilled when necessary. 3148 // 3149 // \details The `MDBX_opt_spill_max_denominator` defines the denominator for 3150 // limiting from the top for part of the current dirty pages may be spilled 3151 // when the free room for a new dirty pages (i.e. distance to the 3152 // `MDBX_opt_txn_dp_limit` threshold) is not enough to perform requested 3153 // operation. 3154 // Exactly `max_pages_to_spill = dirty_pages - dirty_pages / N`, 3155 // where `N` is the value set by `MDBX_opt_spill_max_denominator`. 3156 // 3157 // Should be in the range 0..255, where zero means no limit, i.e. all dirty 3158 // pages could be spilled. Default is 8, i.e. no more than 7/8 of the current 3159 // dirty pages may be spilled when reached the condition described above. 3160 func (env *Env) SetSpillMaxDenominator(max uint64) Error { 3161 return env.SetOption(OptSpillMaxDenomiator, max) 3162 } 3163 3164 // GetSpillParent4ChildDeominator Controls the in-process how much of the parent transaction dirty 3165 // pages will be spilled while start each child transaction. 3166 // 3167 // \details The `MDBX_opt_spill_parent4child_denominator` defines the 3168 // denominator to determine how much of parent transaction dirty pages will be 3169 // spilled explicitly while start each child transaction. 3170 // Exactly `pages_to_spill = dirty_pages / N`, 3171 // where `N` is the value set by `MDBX_opt_spill_parent4child_denominator`. 3172 // 3173 // For a stack of nested transactions each dirty page could be spilled only 3174 // once, and parent's dirty pages couldn't be spilled while child 3175 // transaction(s) are running. Therefore a child transaction could reach 3176 // \ref MDBX_TXN_FULL when parent(s) transaction has spilled too less (and 3177 // child reach the limit of dirty pages), either when parent(s) has spilled 3178 // too more (since child can't spill already spilled pages). So there is no 3179 // universal golden ratio. 3180 // 3181 // Should be in the range 0..255, where zero means no explicit spilling will 3182 // be performed during starting nested transactions. 3183 // Default is 0, i.e. by default no spilling performed during starting nested 3184 // transactions, that correspond historically behaviour. 3185 func (env *Env) GetSpillParent4ChildDeominator() (uint64, Error) { 3186 return env.GetOption(OptSpillParent4ChildDenominator) 3187 } 3188 3189 // SetSpillParent4ChildDeominator Controls the in-process how much of the parent transaction dirty 3190 // pages will be spilled while start each child transaction. 3191 // 3192 // \details The `MDBX_opt_spill_parent4child_denominator` defines the 3193 // denominator to determine how much of parent transaction dirty pages will be 3194 // spilled explicitly while start each child transaction. 3195 // Exactly `pages_to_spill = dirty_pages / N`, 3196 // where `N` is the value set by `MDBX_opt_spill_parent4child_denominator`. 3197 // 3198 // For a stack of nested transactions each dirty page could be spilled only 3199 // once, and parent's dirty pages couldn't be spilled while child 3200 // transaction(s) are running. Therefore a child transaction could reach 3201 // \ref MDBX_TXN_FULL when parent(s) transaction has spilled too less (and 3202 // child reach the limit of dirty pages), either when parent(s) has spilled 3203 // too more (since child can't spill already spilled pages). So there is no 3204 // universal golden ratio. 3205 // 3206 // Should be in the range 0..255, where zero means no explicit spilling will 3207 // be performed during starting nested transactions. 3208 // Default is 0, i.e. by default no spilling performed during starting nested 3209 // transactions, that correspond historically behaviour. 3210 func (env *Env) SetSpillParent4ChildDeominator(value uint64) Error { 3211 return env.SetOption(OptSpillParent4ChildDenominator, value) 3212 } 3213 3214 // GetMergeThreshold16Dot16Percent Controls the in-process threshold of semi-empty pages merge. 3215 // \warning This is experimental option and subject for change or removal. 3216 // \details This option controls the in-process threshold of minimum page 3217 // fill, as used space of percentage of a page. Neighbour pages emptier than 3218 // this value are candidates for merging. The threshold value is specified 3219 // in 1/65536 of percent, which is equivalent to the 16-dot-16 fixed point 3220 // format. The specified value must be in the range from 12.5% (almost empty) 3221 // to 50% (half empty) which corresponds to the range from 8192 and to 32768 3222 // in units respectively. 3223 func (env *Env) GetMergeThreshold16Dot16Percent() (uint64, Error) { 3224 return env.GetOption(OptMergeThreshold16Dot16Percent) 3225 } 3226 3227 // SetMergeThreshold16Dot16Percent Controls the in-process threshold of semi-empty pages merge. 3228 // \warning This is experimental option and subject for change or removal. 3229 // \details This option controls the in-process threshold of minimum page 3230 // fill, as used space of percentage of a page. Neighbour pages emptier than 3231 // this value are candidates for merging. The threshold value is specified 3232 // in 1/65536 of percent, which is equivalent to the 16-dot-16 fixed point 3233 // format. The specified value must be in the range from 12.5% (almost empty) 3234 // to 50% (half empty) which corresponds to the range from 8192 and to 32768 3235 // in units respectively. 3236 func (env *Env) SetMergeThreshold16Dot16Percent(percent uint64) Error { 3237 return env.SetOption(OptMergeThreshold16Dot16Percent, percent) 3238 } 3239 3240 ////////////////////////////////////////////////////////////////////////////////////////// 3241 // DBI 3242 ////////////////////////////////////////////////////////////////////////////////////////// 3243 3244 type DBI uint32 3245 3246 ////////////////////////////////////////////////////////////////////////////////////////// 3247 // Val 3248 ////////////////////////////////////////////////////////////////////////////////////////// 3249 3250 type Val syscall.Iovec 3251 3252 func (v *Val) String() string { 3253 b := make([]byte, v.Len) 3254 copy(b, *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{ 3255 Data: uintptr(unsafe.Pointer(v.Base)), 3256 Len: int(v.Len), 3257 Cap: int(v.Len), 3258 }))) 3259 return string(b) 3260 } 3261 3262 func (v *Val) UnsafeString() string { 3263 return *(*string)(unsafe.Pointer(&reflect.StringHeader{ 3264 Data: uintptr(unsafe.Pointer(v.Base)), 3265 Len: int(v.Len), 3266 })) 3267 } 3268 3269 func (v *Val) Bytes() []byte { 3270 b := make([]byte, v.Len) 3271 copy(b, *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{ 3272 Data: uintptr(unsafe.Pointer(v.Base)), 3273 Len: int(v.Len), 3274 Cap: int(v.Len), 3275 }))) 3276 return b 3277 } 3278 3279 func (v *Val) UnsafeBytes() []byte { 3280 return *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{ 3281 Data: uintptr(unsafe.Pointer(v.Base)), 3282 Len: int(v.Len), 3283 Cap: int(v.Len), 3284 })) 3285 } 3286 3287 func (v *Val) Copy(dst []byte) []byte { 3288 src := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{ 3289 Data: uintptr(unsafe.Pointer(v.Base)), 3290 Len: int(v.Len), 3291 Cap: int(v.Len), 3292 })) 3293 if cap(dst) >= int(v.Len) { 3294 dst = dst[0:v.Len] 3295 copy(dst, src) 3296 return dst 3297 } 3298 dst = make([]byte, v.Len) 3299 copy(dst, src) 3300 return dst 3301 } 3302 3303 func U8(v *uint8) Val { 3304 return Val{ 3305 Base: v, 3306 Len: 1, 3307 } 3308 } 3309 3310 func I8(v *int8) Val { 3311 return Val{ 3312 Base: (*byte)(unsafe.Pointer(v)), 3313 Len: 1, 3314 } 3315 } 3316 3317 func U16(v *uint16) Val { 3318 return Val{ 3319 Base: (*byte)(unsafe.Pointer(v)), 3320 Len: 2, 3321 } 3322 } 3323 3324 func I16(v *int16) Val { 3325 return Val{ 3326 Base: (*byte)(unsafe.Pointer(v)), 3327 Len: 2, 3328 } 3329 } 3330 3331 func U32(v *uint32) Val { 3332 return Val{ 3333 Base: (*byte)(unsafe.Pointer(v)), 3334 Len: 4, 3335 } 3336 } 3337 3338 func I32(v *int32) Val { 3339 return Val{ 3340 Base: (*byte)(unsafe.Pointer(v)), 3341 Len: 4, 3342 } 3343 } 3344 3345 func F32(v *float32) Val { 3346 return Val{ 3347 Base: (*byte)(unsafe.Pointer(v)), 3348 Len: 4, 3349 } 3350 } 3351 3352 func U64(v *uint64) Val { 3353 return Val{ 3354 Base: (*byte)(unsafe.Pointer(v)), 3355 Len: 8, 3356 } 3357 } 3358 3359 func I64(v *int64) Val { 3360 return Val{ 3361 Base: (*byte)(unsafe.Pointer(v)), 3362 Len: 8, 3363 } 3364 } 3365 3366 func F64(v *float64) Val { 3367 return Val{ 3368 Base: (*byte)(unsafe.Pointer(v)), 3369 Len: 8, 3370 } 3371 } 3372 3373 func Bytes(b *[]byte) Val { 3374 return Val{ 3375 Base: &(*b)[0], 3376 Len: uint64(len(*b)), 3377 } 3378 } 3379 3380 func String(s *string) Val { 3381 h := *(*reflect.StringHeader)(unsafe.Pointer(s)) 3382 return Val{ 3383 Base: (*byte)(unsafe.Pointer(h.Data)), 3384 Len: uint64(h.Len), 3385 } 3386 } 3387 3388 func StringConst(s string) Val { 3389 h := *(*reflect.StringHeader)(unsafe.Pointer(&s)) 3390 return Val{ 3391 Base: (*byte)(unsafe.Pointer(h.Data)), 3392 Len: uint64(h.Len), 3393 } 3394 } 3395 3396 func (v *Val) I8() int8 { 3397 if v.Len < 1 { 3398 return 0 3399 } 3400 return *(*int8)(unsafe.Pointer(v.Base)) 3401 } 3402 3403 func (v *Val) U8() uint8 { 3404 if v.Len < 1 { 3405 return 0 3406 } 3407 return *v.Base 3408 } 3409 3410 func (v *Val) I16() int16 { 3411 if v.Len < 2 { 3412 return 0 3413 } 3414 return *(*int16)(unsafe.Pointer(v.Base)) 3415 } 3416 3417 func (v *Val) U16() uint16 { 3418 if v.Len < 2 { 3419 return 0 3420 } 3421 return *(*uint16)(unsafe.Pointer(v.Base)) 3422 } 3423 3424 func (v *Val) I32() int32 { 3425 if v.Len < 4 { 3426 return 0 3427 } 3428 return *(*int32)(unsafe.Pointer(v.Base)) 3429 } 3430 3431 func (v *Val) U32() uint32 { 3432 if v.Len < 4 { 3433 return 0 3434 } 3435 return *(*uint32)(unsafe.Pointer(v.Base)) 3436 } 3437 3438 func (v *Val) I64() int64 { 3439 if v.Len < 8 { 3440 return 0 3441 } 3442 return *(*int64)(unsafe.Pointer(v.Base)) 3443 } 3444 3445 func (v *Val) U64() uint64 { 3446 if v.Len < 8 { 3447 return 0 3448 } 3449 return *(*uint64)(unsafe.Pointer(v.Base)) 3450 } 3451 3452 func (v *Val) F32() float32 { 3453 if v.Len < 4 { 3454 return 0 3455 } 3456 return *(*float32)(unsafe.Pointer(v.Base)) 3457 } 3458 3459 func (v *Val) F64() float64 { 3460 if v.Len < 8 { 3461 return 0 3462 } 3463 return *(*float64)(unsafe.Pointer(v.Base)) 3464 } 3465 3466 ////////////////////////////////////////////////////////////////////////////////////////// 3467 // Tx 3468 ////////////////////////////////////////////////////////////////////////////////////////// 3469 3470 type Tx struct { 3471 env *Env 3472 txn *C.MDBX_txn 3473 shared bool 3474 reset bool 3475 aborted bool 3476 committed bool 3477 } 3478 3479 func NewTransaction(env *Env) *Tx { 3480 txn := &Tx{} 3481 txn.env = env 3482 txn.shared = true 3483 return txn 3484 } 3485 3486 func (tx *Tx) IsReset() bool { 3487 return tx.reset 3488 } 3489 3490 func (tx *Tx) IsAborted() bool { 3491 return tx.aborted 3492 } 3493 3494 func (tx *Tx) IsCommitted() bool { 3495 return tx.committed 3496 } 3497 3498 func (env *Env) Begin(txn *Tx, flags TxFlags) Error { 3499 txn.env = env 3500 txn.txn = nil 3501 txn.reset = false 3502 txn.aborted = false 3503 txn.committed = false 3504 args := struct { 3505 env uintptr 3506 parent uintptr 3507 txn uintptr 3508 context uintptr 3509 flags TxFlags 3510 result Error 3511 }{ 3512 env: uintptr(unsafe.Pointer(env.env)), 3513 parent: 0, 3514 txn: uintptr(unsafe.Pointer(&txn.txn)), 3515 flags: flags, 3516 } 3517 ptr := uintptr(unsafe.Pointer(&args)) 3518 unsafecgo.NonBlocking((*byte)(C.do_mdbx_txn_begin_ex), ptr, 0) 3519 return args.result 3520 } 3521 3522 // TxInfo Information about the transaction 3523 type TxInfo struct { 3524 // The ID of the transaction. For a READ-ONLY transaction, this corresponds to the snapshot being read. 3525 ID uint64 3526 3527 // For READ-ONLY transaction: the lag from a recent MVCC-snapshot, i.e. the 3528 // number of committed transaction since read transaction started. 3529 // For WRITE transaction (provided if `scan_rlt=true`): the lag of the oldest 3530 // reader from current transaction (i.e. at least 1 if any reader running). 3531 ReaderLag uint64 3532 3533 // Used space by this transaction, i.e. corresponding to the last used database page. 3534 SpaceUsed uint64 3535 3536 // Current size of database file. 3537 SpaceLimitSoft uint64 3538 3539 // Upper bound for size the database file, i.e. the value `size_upper` 3540 // argument of the appropriate call of \ref mdbx_env_set_geometry(). 3541 SpaceLimitHard uint64 3542 3543 // For READ-ONLY transaction: The total size of the database pages that were 3544 // retired by committed write transactions after the reader's MVCC-snapshot, 3545 // i.e. the space which would be freed after the Reader releases the 3546 // MVCC-snapshot for reuse by completion read transaction. 3547 // 3548 // For WRITE transaction: The summarized size of the database pages that were 3549 // retired for now due Copy-On-Write during this transaction. 3550 SpaceRetired uint64 3551 3552 // For READ-ONLY transaction: the space available for writer(s) and that 3553 // must be exhausted for reason to call the Handle-Slow-Readers callback for 3554 // this read transaction. 3555 // 3556 // For WRITE transaction: the space inside transaction 3557 // that left to `MDBX_TXN_FULL` error. 3558 SpaceLeftover uint64 3559 3560 // For READ-ONLY transaction (provided if `scan_rlt=true`): The space that 3561 // actually become available for reuse when only this transaction will be finished. 3562 // 3563 // For WRITE transaction: The summarized size of the dirty database 3564 // pages that generated during this transaction. 3565 SpaceDirty uint64 3566 } 3567 3568 // Info Return information about the MDBX transaction. 3569 // \ingroup c_statinfo 3570 // 3571 // \param [in] txn A transaction handle returned by \ref mdbx_txn_begin() 3572 // \param [out] info The address of an \ref MDBX_txn_info structure 3573 // 3574 // where the information will be copied. 3575 // 3576 // \param [in] scan_rlt The boolean flag controls the scan of the read lock 3577 // 3578 // table to provide complete information. Such scan 3579 // is relatively expensive and you can avoid it 3580 // if corresponding fields are not needed. 3581 // See description of \ref MDBX_txn_info. 3582 // 3583 // \returns A non-zero error value on failure and 0 on success. 3584 func (tx *Tx) Info(info *TxInfo) Error { 3585 args := struct { 3586 txn uintptr 3587 info uintptr 3588 scanRlt int32 3589 result Error 3590 }{ 3591 txn: uintptr(unsafe.Pointer(tx.txn)), 3592 info: uintptr(unsafe.Pointer(info)), 3593 } 3594 ptr := uintptr(unsafe.Pointer(&args)) 3595 unsafecgo.NonBlocking((*byte)(C.do_mdbx_txn_info), ptr, 0) 3596 return args.result 3597 } 3598 3599 // Flags Return the transaction's flags. 3600 // \ingroup c_transactions 3601 // 3602 // This returns the flags associated with this transaction. 3603 // 3604 // \param [in] txn A transaction handle returned by \ref mdbx_txn_begin(). 3605 // 3606 // \returns A transaction flags, valid if input is an valid transaction, 3607 // 3608 // otherwise -1. 3609 func (tx *Tx) Flags() int32 { 3610 args := struct { 3611 txn uintptr 3612 flags int32 3613 }{ 3614 txn: uintptr(unsafe.Pointer(tx.txn)), 3615 } 3616 ptr := uintptr(unsafe.Pointer(&args)) 3617 unsafecgo.NonBlocking((*byte)(C.do_mdbx_txn_flags), ptr, 0) 3618 return args.flags 3619 } 3620 3621 // ID Return the transaction's ID. 3622 // \ingroup c_statinfo 3623 // 3624 // This returns the identifier associated with this transaction. For a 3625 // read-only transaction, this corresponds to the snapshot being read; 3626 // concurrent readers will frequently have the same transaction ID. 3627 // 3628 // \param [in] txn A transaction handle returned by \ref mdbx_txn_begin(). 3629 // 3630 // \returns A transaction ID, valid if input is an active transaction, 3631 // 3632 // otherwise 0. 3633 func (tx *Tx) ID() uint64 { 3634 args := struct { 3635 txn uintptr 3636 id uint64 3637 }{ 3638 txn: uintptr(unsafe.Pointer(tx.txn)), 3639 } 3640 ptr := uintptr(unsafe.Pointer(&args)) 3641 unsafecgo.NonBlocking((*byte)(C.do_mdbx_txn_id), ptr, 0) 3642 return args.id 3643 } 3644 3645 // CommitLatency of commit stages in 1/65536 of seconds units. 3646 // \warning This structure may be changed in future releases. 3647 // \see mdbx_txn_commit_ex() 3648 type CommitLatency struct { 3649 // Duration of preparation (commit child transactions, update sub-databases records and cursors destroying). 3650 Preparation uint32 3651 // Duration of GC/freeDB handling & updation. 3652 GC uint32 3653 // Duration of internal audit if enabled. 3654 Audit uint32 3655 // Duration of writing dirty/modified data pages. 3656 Write uint32 3657 // Duration of syncing written data to the dist/storage. 3658 Sync uint32 3659 // Duration of transaction ending (releasing resources). 3660 Ending uint32 3661 // The total duration of a commit. 3662 Whole uint32 3663 } 3664 3665 // CommitEx commit all the operations of a transaction into the database and 3666 // collect latency information. 3667 // \see mdbx_txn_commit() 3668 // \ingroup c_statinfo 3669 // \warning This function may be changed in future releases. 3670 func (tx *Tx) CommitEx(latency *CommitLatency) Error { 3671 args := struct { 3672 txn uintptr 3673 latency uintptr 3674 result Error 3675 }{ 3676 txn: uintptr(unsafe.Pointer(tx.txn)), 3677 latency: uintptr(unsafe.Pointer(latency)), 3678 } 3679 ptr := uintptr(unsafe.Pointer(&args)) 3680 unsafecgo.NonBlocking((*byte)(C.do_mdbx_txn_commit_ex), ptr, 0) 3681 return args.result 3682 } 3683 3684 // Commit all the operations of a transaction into the database. 3685 // \ingroup c_transactions 3686 // 3687 // If the current thread is not eligible to manage the transaction then 3688 // the \ref MDBX_THREAD_MISMATCH error will returned. Otherwise the transaction 3689 // will be committed and its handle is freed. If the transaction cannot 3690 // be committed, it will be aborted with the corresponding error returned. 3691 // 3692 // Thus, a result other than \ref MDBX_THREAD_MISMATCH means that the 3693 // transaction is terminated: 3694 // - Resources are released; 3695 // - Transaction handle is invalid; 3696 // - Cursor(s) associated with transaction must not be used, except with 3697 // mdbx_cursor_renew() and \ref mdbx_cursor_close(). 3698 // Such cursor(s) must be closed explicitly by \ref mdbx_cursor_close() 3699 // before or after transaction commit, either can be reused with 3700 // \ref mdbx_cursor_renew() until it will be explicitly closed by 3701 // \ref mdbx_cursor_close(). 3702 // 3703 // \param [in] txn A transaction handle returned by \ref mdbx_txn_begin(). 3704 // 3705 // \returns A non-zero error value on failure and 0 on success, 3706 // 3707 // some possible errors are: 3708 // 3709 // \retval MDBX_RESULT_TRUE Transaction was aborted since it should 3710 // 3711 // be aborted due to previous errors. 3712 // 3713 // \retval MDBX_PANIC A fatal error occurred earlier 3714 // 3715 // and the environment must be shut down. 3716 // 3717 // \retval MDBX_BAD_TXN Transaction is already finished or never began. 3718 // \retval MDBX_EBADSIGN Transaction object has invalid signature, 3719 // 3720 // e.g. transaction was already terminated 3721 // or memory was corrupted. 3722 // 3723 // \retval MDBX_THREAD_MISMATCH Given transaction is not owned 3724 // 3725 // by current thread. 3726 // 3727 // \retval MDBX_EINVAL Transaction handle is NULL. 3728 // \retval MDBX_ENOSPC No more disk space. 3729 // \retval MDBX_EIO A system-level I/O error occurred. 3730 // \retval MDBX_ENOMEM Out of memory. 3731 func (tx *Tx) Commit() Error { 3732 tx.committed = true 3733 return tx.CommitEx(nil) 3734 } 3735 3736 // Abort Abandon all the operations of the transaction instead of saving them. 3737 // \ingroup c_transactions 3738 // 3739 // The transaction handle is freed. It and its cursors must not be used again 3740 // after this call, except with \ref mdbx_cursor_renew() and 3741 // \ref mdbx_cursor_close(). 3742 // 3743 // If the current thread is not eligible to manage the transaction then 3744 // the \ref MDBX_THREAD_MISMATCH error will returned. Otherwise the transaction 3745 // will be aborted and its handle is freed. Thus, a result other than 3746 // \ref MDBX_THREAD_MISMATCH means that the transaction is terminated: 3747 // - Resources are released; 3748 // - Transaction handle is invalid; 3749 // - Cursor(s) associated with transaction must not be used, except with 3750 // \ref mdbx_cursor_renew() and \ref mdbx_cursor_close(). 3751 // Such cursor(s) must be closed explicitly by \ref mdbx_cursor_close() 3752 // before or after transaction abort, either can be reused with 3753 // \ref mdbx_cursor_renew() until it will be explicitly closed by 3754 // \ref mdbx_cursor_close(). 3755 // 3756 // \param [in] txn A transaction handle returned by \ref mdbx_txn_begin(). 3757 // 3758 // \returns A non-zero error value on failure and 0 on success, 3759 // 3760 // some possible errors are: 3761 // 3762 // \retval MDBX_PANIC A fatal error occurred earlier and 3763 // 3764 // the environment must be shut down. 3765 // 3766 // \retval MDBX_BAD_TXN Transaction is already finished or never began. 3767 // \retval MDBX_EBADSIGN Transaction object has invalid signature, 3768 // 3769 // e.g. transaction was already terminated 3770 // or memory was corrupted. 3771 // 3772 // \retval MDBX_THREAD_MISMATCH Given transaction is not owned 3773 // 3774 // by current thread. 3775 // 3776 // \retval MDBX_EINVAL Transaction handle is NULL. 3777 func (tx *Tx) Abort() Error { 3778 args := struct { 3779 txn uintptr 3780 result Error 3781 }{ 3782 txn: uintptr(unsafe.Pointer(tx.txn)), 3783 } 3784 tx.aborted = true 3785 ptr := uintptr(unsafe.Pointer(&args)) 3786 unsafecgo.NonBlocking((*byte)(C.do_mdbx_txn_abort), ptr, 0) 3787 return args.result 3788 } 3789 3790 // Break Marks transaction as broken. 3791 // \ingroup c_transactions 3792 // 3793 // Function keeps the transaction handle and corresponding locks, but makes 3794 // impossible to perform any operations within a broken transaction. 3795 // Broken transaction must then be aborted explicitly later. 3796 // 3797 // \param [in] txn A transaction handle returned by \ref mdbx_txn_begin(). 3798 // 3799 // \see mdbx_txn_abort() \see mdbx_txn_reset() \see mdbx_txn_commit() 3800 // \returns A non-zero error value on failure and 0 on success. 3801 func (tx *Tx) Break() Error { 3802 args := struct { 3803 txn uintptr 3804 result Error 3805 }{ 3806 txn: uintptr(unsafe.Pointer(tx.txn)), 3807 } 3808 ptr := uintptr(unsafe.Pointer(&args)) 3809 unsafecgo.NonBlocking((*byte)(C.do_mdbx_txn_break), ptr, 0) 3810 return args.result 3811 } 3812 3813 // Reset a read-only transaction. 3814 // \ingroup c_transactions 3815 // 3816 // Abort the read-only transaction like \ref mdbx_txn_abort(), but keep the 3817 // transaction handle. Therefore \ref mdbx_txn_renew() may reuse the handle. 3818 // This saves allocation overhead if the process will start a new read-only 3819 // transaction soon, and also locking overhead if \ref MDBX_NOTLS is in use. The 3820 // reader table lock is released, but the table slot stays tied to its thread 3821 // or \ref MDBX_txn. Use \ref mdbx_txn_abort() to discard a reset handle, and to 3822 // free its lock table slot if \ref MDBX_NOTLS is in use. 3823 // 3824 // Cursors opened within the transaction must not be used again after this 3825 // call, except with \ref mdbx_cursor_renew() and \ref mdbx_cursor_close(). 3826 // 3827 // Reader locks generally don't interfere with writers, but they keep old 3828 // versions of database pages allocated. Thus they prevent the old pages from 3829 // being reused when writers commit new data, and so under heavy load the 3830 // database size may grow much more rapidly than otherwise. 3831 // 3832 // \param [in] txn A transaction handle returned by \ref mdbx_txn_begin(). 3833 // 3834 // \returns A non-zero error value on failure and 0 on success, 3835 // 3836 // some possible errors are: 3837 // 3838 // \retval MDBX_PANIC A fatal error occurred earlier and 3839 // 3840 // the environment must be shut down. 3841 // 3842 // \retval MDBX_BAD_TXN Transaction is already finished or never began. 3843 // \retval MDBX_EBADSIGN Transaction object has invalid signature, 3844 // 3845 // e.g. transaction was already terminated 3846 // or memory was corrupted. 3847 // 3848 // \retval MDBX_THREAD_MISMATCH Given transaction is not owned 3849 // 3850 // by current thread. 3851 // 3852 // \retval MDBX_EINVAL Transaction handle is NULL. 3853 func (tx *Tx) Reset() Error { 3854 args := struct { 3855 txn uintptr 3856 result Error 3857 }{ 3858 txn: uintptr(unsafe.Pointer(tx.txn)), 3859 } 3860 tx.reset = true 3861 ptr := uintptr(unsafe.Pointer(&args)) 3862 unsafecgo.NonBlocking((*byte)(C.do_mdbx_txn_reset), ptr, 0) 3863 return args.result 3864 } 3865 3866 // Renew a read-only transaction. 3867 // \ingroup c_transactions 3868 // 3869 // This acquires a new reader lock for a transaction handle that had been 3870 // released by \ref mdbx_txn_reset(). It must be called before a reset 3871 // transaction may be used again. 3872 // 3873 // \param [in] txn A transaction handle returned by \ref mdbx_txn_begin(). 3874 // 3875 // \returns A non-zero error value on failure and 0 on success, 3876 // 3877 // some possible errors are: 3878 // 3879 // \retval MDBX_PANIC A fatal error occurred earlier and 3880 // 3881 // the environment must be shut down. 3882 // 3883 // \retval MDBX_BAD_TXN Transaction is already finished or never began. 3884 // \retval MDBX_EBADSIGN Transaction object has invalid signature, 3885 // 3886 // e.g. transaction was already terminated 3887 // or memory was corrupted. 3888 // 3889 // \retval MDBX_THREAD_MISMATCH Given transaction is not owned 3890 // 3891 // by current thread. 3892 // 3893 // \retval MDBX_EINVAL Transaction handle is NULL. 3894 func (tx *Tx) Renew() Error { 3895 args := struct { 3896 txn uintptr 3897 result Error 3898 }{ 3899 txn: uintptr(unsafe.Pointer(tx.txn)), 3900 } 3901 tx.reset = false 3902 ptr := uintptr(unsafe.Pointer(&args)) 3903 unsafecgo.NonBlocking((*byte)(C.do_mdbx_txn_renew), ptr, 0) 3904 return args.result 3905 } 3906 3907 type Canary struct { 3908 X, Y, Z, V uint64 3909 } 3910 3911 // PutCanary Set integers markers (aka "canary") associated with the environment. 3912 // \ingroup c_crud 3913 // \see mdbx_canary_get() 3914 // 3915 // \param [in] txn A transaction handle returned by \ref mdbx_txn_begin() 3916 // \param [in] canary A optional pointer to \ref MDBX_canary structure for `x`, 3917 // 3918 // `y` and `z` values from. 3919 // - If canary is NOT NULL then the `x`, `y` and `z` values will be 3920 // updated from given canary argument, but the 'v' be always set 3921 // to the current transaction number if at least one `x`, `y` or 3922 // `z` values have changed (i.e. if `x`, `y` and `z` have the same 3923 // values as currently present then nothing will be changes or 3924 // updated). 3925 // - if canary is NULL then the `v` value will be explicitly update 3926 // to the current transaction number without changes `x`, `y` nor 3927 // `z`. 3928 // 3929 // \returns A non-zero error value on failure and 0 on success. 3930 func (tx *Tx) PutCanary(canary *Canary) Error { 3931 args := struct { 3932 txn uintptr 3933 canary uintptr 3934 result Error 3935 }{ 3936 txn: uintptr(unsafe.Pointer(tx.txn)), 3937 canary: uintptr(unsafe.Pointer(canary)), 3938 } 3939 ptr := uintptr(unsafe.Pointer(&args)) 3940 unsafecgo.NonBlocking((*byte)(C.do_mdbx_canary_put), ptr, 0) 3941 return args.result 3942 } 3943 3944 // GetCanary Returns fours integers markers (aka "canary") associated with the 3945 // environment. 3946 // \ingroup c_crud 3947 // \see mdbx_canary_set() 3948 // 3949 // \param [in] txn A transaction handle returned by \ref mdbx_txn_begin(). 3950 // \param [in] canary The address of an MDBX_canary structure where the 3951 // 3952 // information will be copied. 3953 // 3954 // \returns A non-zero error value on failure and 0 on success. 3955 func (tx *Tx) GetCanary(canary *Canary) Error { 3956 args := struct { 3957 txn uintptr 3958 canary uintptr 3959 result Error 3960 }{ 3961 txn: uintptr(unsafe.Pointer(tx.txn)), 3962 canary: uintptr(unsafe.Pointer(canary)), 3963 } 3964 ptr := uintptr(unsafe.Pointer(&args)) 3965 unsafecgo.NonBlocking((*byte)(C.do_mdbx_canary_get), ptr, 0) 3966 return args.result 3967 } 3968 3969 // EnvInfo Return information about the MDBX environment. 3970 // \ingroup c_statinfo 3971 // 3972 // At least one of env or txn argument must be non-null. If txn is passed 3973 // non-null then stat will be filled accordingly to the given transaction. 3974 // Otherwise, if txn is null, then stat will be populated by a snapshot from 3975 // the last committed write transaction, and at next time, other information 3976 // can be returned. 3977 // 3978 // Legacy \ref mdbx_env_info() correspond to calling \ref mdbx_env_info_ex() 3979 // with the null `txn` argument. 3980 // 3981 // \param [in] env An environment handle returned by \ref mdbx_env_create() 3982 // \param [in] txn A transaction handle returned by \ref mdbx_txn_begin() 3983 // \param [out] info The address of an \ref MDBX_envinfo structure 3984 // 3985 // where the information will be copied 3986 // 3987 // \param [in] bytes The size of \ref MDBX_envinfo. 3988 // 3989 // \returns A non-zero error value on failure and 0 on success. 3990 func (tx *Tx) EnvInfo(info *EnvInfo) Error { 3991 if info == nil { 3992 return ErrInvalid 3993 } 3994 args := struct { 3995 env uintptr 3996 txn uintptr 3997 info uintptr 3998 size uintptr 3999 result int32 4000 }{ 4001 env: uintptr(unsafe.Pointer(tx.env.env)), 4002 txn: uintptr(unsafe.Pointer(tx.txn)), 4003 info: uintptr(unsafe.Pointer(info)), 4004 size: unsafe.Sizeof(C.MDBX_envinfo{}), 4005 } 4006 ptr := uintptr(unsafe.Pointer(&args)) 4007 unsafecgo.NonBlocking((*byte)(C.do_mdbx_env_info_ex), ptr, 0) 4008 return Error(args.result) 4009 } 4010 4011 // OpenDBI Open or Create a database in the environment. 4012 // \ingroup c_dbi 4013 // 4014 // A database handle denotes the name and parameters of a database, 4015 // independently of whether such a database exists. The database handle may be 4016 // discarded by calling \ref mdbx_dbi_close(). The old database handle is 4017 // returned if the database was already open. The handle may only be closed 4018 // once. 4019 // 4020 // \note A notable difference between MDBX and LMDB is that MDBX make handles 4021 // opened for existing databases immediately available for other transactions, 4022 // regardless this transaction will be aborted or reset. The REASON for this is 4023 // to avoiding the requirement for multiple opening a same handles in 4024 // concurrent read transactions, and tracking of such open but hidden handles 4025 // until the completion of read transactions which opened them. 4026 // 4027 // Nevertheless, the handle for the NEWLY CREATED database will be invisible 4028 // for other transactions until the this write transaction is successfully 4029 // committed. If the write transaction is aborted the handle will be closed 4030 // automatically. After a successful commit the such handle will reside in the 4031 // shared environment, and may be used by other transactions. 4032 // 4033 // In contrast to LMDB, the MDBX allow this function to be called from multiple 4034 // concurrent transactions or threads in the same process. 4035 // 4036 // To use named database (with name != NULL), \ref mdbx_env_set_maxdbs() 4037 // must be called before opening the environment. Table names are 4038 // keys in the internal unnamed database, and may be read but not written. 4039 // 4040 // \param [in] txn transaction handle returned by \ref mdbx_txn_begin(). 4041 // \param [in] name The name of the database to open. If only a single 4042 // 4043 // database is needed in the environment, 4044 // this value may be NULL. 4045 // 4046 // \param [in] flags Special options for this database. This parameter must 4047 // 4048 // be set to 0 or by bitwise OR'ing together one or more 4049 // of the values described here: 4050 // - \ref MDBX_REVERSEKEY 4051 // Keys are strings to be compared in reverse order, from the end 4052 // of the strings to the beginning. By default, Keys are treated as 4053 // strings and compared from beginning to end. 4054 // - \ref MDBX_INTEGERKEY 4055 // Keys are binary integers in native byte order, either uint32_t or 4056 // uint64_t, and will be sorted as such. The keys must all be of the 4057 // same size and must be aligned while passing as arguments. 4058 // - \ref MDBX_DUPSORT 4059 // Duplicate keys may be used in the database. Or, from another point of 4060 // view, keys may have multiple data items, stored in sorted order. By 4061 // default keys must be unique and may have only a single data item. 4062 // - \ref MDBX_DUPFIXED 4063 // This flag may only be used in combination with \ref MDBX_DUPSORT. This 4064 // option tells the library that the data items for this database are 4065 // all the same size, which allows further optimizations in storage and 4066 // retrieval. When all data items are the same size, the 4067 // \ref MDBX_GET_MULTIPLE, \ref MDBX_NEXT_MULTIPLE and 4068 // \ref MDBX_PREV_MULTIPLE cursor operations may be used to retrieve 4069 // multiple items at once. 4070 // - \ref MDBX_INTEGERDUP 4071 // This option specifies that duplicate data items are binary integers, 4072 // similar to \ref MDBX_INTEGERKEY keys. The data values must all be of the 4073 // same size and must be aligned while passing as arguments. 4074 // - \ref MDBX_REVERSEDUP 4075 // This option specifies that duplicate data items should be compared as 4076 // strings in reverse order (the comparison is performed in the direction 4077 // from the last byte to the first). 4078 // - \ref MDBX_CREATE 4079 // Create the named database if it doesn't exist. This option is not 4080 // allowed in a read-only transaction or a read-only environment. 4081 // 4082 // \param [out] dbi Address where the new \ref MDBX_dbi handle 4083 // 4084 // will be stored. 4085 // 4086 // For \ref mdbx_dbi_open_ex() additional arguments allow you to set custom 4087 // comparison functions for keys and values (for multimaps). 4088 // \see avoid_custom_comparators 4089 // 4090 // \returns A non-zero error value on failure and 0 on success, 4091 // 4092 // some possible errors are: 4093 // 4094 // \retval MDBX_NOTFOUND The specified database doesn't exist in the 4095 // 4096 // environment and \ref MDBX_CREATE was not specified. 4097 // 4098 // \retval MDBX_DBS_FULL Too many databases have been opened. 4099 // 4100 // \see mdbx_env_set_maxdbs() 4101 // 4102 // \retval MDBX_INCOMPATIBLE Database is incompatible with given flags, 4103 // 4104 // i.e. the passed flags is different with which the 4105 // database was created, or the database was already 4106 // opened with a different comparison function(s). 4107 // 4108 // \retval MDBX_THREAD_MISMATCH Given transaction is not owned 4109 // 4110 // by current thread. 4111 func (tx *Tx) OpenDBI(name string, flags DBFlags) (DBI, Error) { 4112 if len(name) == 0 { 4113 var dbi DBI 4114 err := Error(C.mdbx_dbi_open(tx.txn, nil, (C.MDBX_db_flags_t)(flags), (*C.MDBX_dbi)(unsafe.Pointer(&dbi)))) 4115 return dbi, err 4116 } else { 4117 n := C.CString(name) 4118 defer C.free(unsafe.Pointer(n)) 4119 var dbi DBI 4120 err := Error(C.mdbx_dbi_open(tx.txn, n, (C.MDBX_db_flags_t)(flags), (*C.MDBX_dbi)(unsafe.Pointer(&dbi)))) 4121 return dbi, err 4122 } 4123 } 4124 4125 //// OpenDBIEx OpenDBI with custom comparators. 4126 //// \ref avoid_custom_comparators "avoid using custom comparators" and use 4127 //// \ref mdbx_dbi_open() instead. 4128 //// 4129 //// \ingroup c_dbi 4130 //// 4131 //// \param [in] txn transaction handle returned by \ref mdbx_txn_begin(). 4132 //// \param [in] name The name of the database to open. If only a single 4133 //// database is needed in the environment, 4134 //// this value may be NULL. 4135 //// \param [in] flags Special options for this database. 4136 //// \param [in] keycmp Optional custom key comparison function for a database. 4137 //// \param [in] datacmp Optional custom data comparison function for a database. 4138 //// \param [out] dbi Address where the new MDBX_dbi handle will be stored. 4139 //// \returns A non-zero error value on failure and 0 on success. 4140 //func (tx *Tx) OpenDBIEx(name string, flags DBFlags, keyCompare, dataCompare *Cmp) (DBI, Error) { 4141 // if len(name) == 0 { 4142 // var dbi DBI 4143 // err := Error(C.mdbx_dbi_open_ex(tx.txn, nil, (C.MDBX_db_flags_t)(flags), (*C.MDBX_dbi)(unsafe.Pointer(&dbi)), 4144 // (*C.MDBX_cmp_func)(unsafe.Pointer(keyCompare)), (*C.MDBX_cmp_func)(unsafe.Pointer(dataCompare)))) 4145 // return dbi, err 4146 // } else { 4147 // n := C.CString(name) 4148 // defer C.free(unsafe.Pointer(n)) 4149 // var dbi DBI 4150 // err := Error(C.mdbx_dbi_open_ex(tx.txn, n, (C.MDBX_db_flags_t)(flags), (*C.MDBX_dbi)(unsafe.Pointer(&dbi)), 4151 // (*C.MDBX_cmp_func)(unsafe.Pointer(keyCompare)), (*C.MDBX_cmp_func)(unsafe.Pointer(dataCompare)))) 4152 // return dbi, err 4153 // } 4154 //} 4155 4156 // Stats Statistics for a database in the environment 4157 // \ingroup c_statinfo 4158 // \see mdbx_env_stat_ex() \see mdbx_dbi_stat() 4159 type Stats struct { 4160 PageSize uint32 // Size of a database page. This is the same for all databases. 4161 Depth uint32 // Depth (height) of the B-tree 4162 BranchPages uint64 // Number of internal (non-leaf) pages 4163 LeafPages uint64 // Number of leaf pages 4164 OverflowPages uint64 // Number of overflow pages 4165 Entries uint64 // Number of data items 4166 ModTxnID uint64 // Transaction ID of committed last modification 4167 } 4168 4169 // DBIStat Retrieve statistics for a database. 4170 // \ingroup c_statinfo 4171 // 4172 // \param [in] txn A transaction handle returned by \ref mdbx_txn_begin(). 4173 // \param [in] dbi A database handle returned by \ref mdbx_dbi_open(). 4174 // \param [out] stat The address of an \ref MDBX_stat structure where 4175 // 4176 // the statistics will be copied. 4177 // 4178 // \param [in] bytes The size of \ref MDBX_stat. 4179 // 4180 // \returns A non-zero error value on failure and 0 on success, 4181 // 4182 // some possible errors are: 4183 // 4184 // \retval MDBX_THREAD_MISMATCH Given transaction is not owned 4185 // 4186 // by current thread. 4187 // 4188 // \retval MDBX_EINVAL An invalid parameter was specified. 4189 func (tx *Tx) DBIStat(dbi DBI, stat *Stats) Error { 4190 args := struct { 4191 txn uintptr 4192 stat uintptr 4193 size uintptr 4194 dbi uint32 4195 result Error 4196 }{ 4197 txn: uintptr(unsafe.Pointer(tx.txn)), 4198 stat: uintptr(unsafe.Pointer(stat)), 4199 size: unsafe.Sizeof(Stats{}), 4200 dbi: uint32(dbi), 4201 } 4202 ptr := uintptr(unsafe.Pointer(&args)) 4203 unsafecgo.NonBlocking((*byte)(C.do_mdbx_dbi_stat), ptr, 0) 4204 return args.result 4205 } 4206 4207 // DBIFlags Retrieve the DB flags and status for a database handle. 4208 // \ingroup c_statinfo 4209 // 4210 // \param [in] txn A transaction handle returned by \ref mdbx_txn_begin(). 4211 // \param [in] dbi A database handle returned by \ref mdbx_dbi_open(). 4212 // \param [out] flags Address where the flags will be returned. 4213 // \param [out] state Address where the state will be returned. 4214 // 4215 // \returns A non-zero error value on failure and 0 on success. 4216 func (tx *Tx) DBIFlags(dbi DBI) (DBFlags, DBIState, Error) { 4217 var flags DBFlags 4218 var state DBIState 4219 4220 args := struct { 4221 txn uintptr 4222 flags uintptr 4223 state uintptr 4224 dbi uint32 4225 result Error 4226 }{ 4227 txn: uintptr(unsafe.Pointer(tx.txn)), 4228 flags: uintptr(unsafe.Pointer(&flags)), 4229 state: uintptr(unsafe.Pointer(&state)), 4230 dbi: uint32(dbi), 4231 } 4232 ptr := uintptr(unsafe.Pointer(&args)) 4233 unsafecgo.NonBlocking((*byte)(C.do_mdbx_dbi_flags_ex), ptr, 0) 4234 return flags, state, args.result 4235 } 4236 4237 // Drop Empty or delete and close a database. 4238 // \ingroup c_crud 4239 // 4240 // \see mdbx_dbi_close() \see mdbx_dbi_open() 4241 // 4242 // \param [in] txn A transaction handle returned by \ref mdbx_txn_begin(). 4243 // \param [in] dbi A database handle returned by \ref mdbx_dbi_open(). 4244 // \param [in] del `false` to empty the DB, `true` to delete it 4245 // 4246 // from the environment and close the DB handle. 4247 // 4248 // \returns A non-zero error value on failure and 0 on success. 4249 func (tx *Tx) Drop(dbi DBI, del bool) Error { 4250 args := struct { 4251 txn uintptr 4252 del uintptr 4253 dbi uint32 4254 result Error 4255 }{ 4256 txn: uintptr(unsafe.Pointer(tx.txn)), 4257 dbi: uint32(dbi), 4258 } 4259 if del { 4260 args.del = 1 4261 } 4262 ptr := uintptr(unsafe.Pointer(&args)) 4263 unsafecgo.NonBlocking((*byte)(C.do_mdbx_drop), ptr, 0) 4264 return args.result 4265 } 4266 4267 // Get items from a database. 4268 // \ingroup c_crud 4269 // 4270 // This function retrieves key/data pairs from the database. The address 4271 // and length of the data associated with the specified key are returned 4272 // in the structure to which data refers. 4273 // If the database supports duplicate keys (\ref MDBX_DUPSORT) then the 4274 // first data item for the key will be returned. Retrieval of other 4275 // items requires the use of \ref mdbx_cursor_get(). 4276 // 4277 // \note The memory pointed to by the returned values is owned by the 4278 // database. The caller need not dispose of the memory, and may not 4279 // modify it in any way. For values returned in a read-only transaction 4280 // any modification attempts will cause a `SIGSEGV`. 4281 // 4282 // \note Values returned from the database are valid only until a 4283 // subsequent update operation, or the end of the transaction. 4284 // 4285 // \param [in] txn A transaction handle returned by \ref mdbx_txn_begin(). 4286 // \param [in] dbi A database handle returned by \ref mdbx_dbi_open(). 4287 // \param [in] key The key to search for in the database. 4288 // \param [in,out] data The data corresponding to the key. 4289 // 4290 // \returns A non-zero error value on failure and 0 on success, 4291 // 4292 // some possible errors are: 4293 // 4294 // \retval MDBX_THREAD_MISMATCH Given transaction is not owned 4295 // 4296 // by current thread. 4297 // 4298 // \retval MDBX_NOTFOUND The key was not in the database. 4299 // \retval MDBX_EINVAL An invalid parameter was specified. 4300 func (tx *Tx) Get(dbi DBI, key *Val, data *Val) Error { 4301 args := struct { 4302 txn uintptr 4303 key uintptr 4304 data uintptr 4305 dbi uint32 4306 result Error 4307 }{ 4308 txn: uintptr(unsafe.Pointer(tx.txn)), 4309 key: uintptr(unsafe.Pointer(key)), 4310 data: uintptr(unsafe.Pointer(data)), 4311 dbi: uint32(dbi), 4312 } 4313 ptr := uintptr(unsafe.Pointer(&args)) 4314 unsafecgo.NonBlocking((*byte)(C.do_mdbx_get), ptr, 0) 4315 return args.result 4316 } 4317 4318 // GetEqualOrGreat Get equal or great item from a database. 4319 // \ingroup c_crud 4320 // 4321 // Briefly this function does the same as \ref mdbx_get() with a few 4322 // differences: 4323 // 1. Return equal or great (due comparison function) key-value 4324 // pair, but not only exactly matching with the key. 4325 // 2. On success return \ref MDBX_SUCCESS if key found exactly, 4326 // and \ref MDBX_RESULT_TRUE otherwise. Moreover, for databases with 4327 // \ref MDBX_DUPSORT flag the data argument also will be used to match over 4328 // multi-value/duplicates, and \ref MDBX_SUCCESS will be returned only when 4329 // BOTH the key and the data match exactly. 4330 // 3. Updates BOTH the key and the data for pointing to the actual key-value 4331 // pair inside the database. 4332 // 4333 // \param [in] txn A transaction handle returned 4334 // 4335 // by \ref mdbx_txn_begin(). 4336 // 4337 // \param [in] dbi A database handle returned by \ref mdbx_dbi_open(). 4338 // \param [in,out] key The key to search for in the database. 4339 // \param [in,out] data The data corresponding to the key. 4340 // 4341 // \returns A non-zero error value on failure and \ref MDBX_RESULT_FALSE 4342 // 4343 // or \ref MDBX_RESULT_TRUE on success (as described above). 4344 // Some possible errors are: 4345 // 4346 // \retval MDBX_THREAD_MISMATCH Given transaction is not owned 4347 // 4348 // by current thread. 4349 // 4350 // \retval MDBX_NOTFOUND The key was not in the database. 4351 // \retval MDBX_EINVAL An invalid parameter was specified. 4352 func (tx *Tx) GetEqualOrGreat(dbi DBI, key *Val, data *Val) Error { 4353 args := struct { 4354 txn uintptr 4355 key uintptr 4356 data uintptr 4357 dbi uint32 4358 result Error 4359 }{ 4360 txn: uintptr(unsafe.Pointer(tx.txn)), 4361 key: uintptr(unsafe.Pointer(key)), 4362 data: uintptr(unsafe.Pointer(data)), 4363 dbi: uint32(dbi), 4364 } 4365 ptr := uintptr(unsafe.Pointer(&args)) 4366 unsafecgo.NonBlocking((*byte)(C.do_mdbx_get_equal_or_great), ptr, 0) 4367 return args.result 4368 } 4369 4370 // GetEx Get items from a database 4371 // and optionally number of data items for a given key. 4372 // 4373 // \ingroup c_crud 4374 // 4375 // Briefly this function does the same as \ref mdbx_get() with a few 4376 // differences: 4377 // 1. If values_count is NOT NULL, then returns the count 4378 // of multi-values/duplicates for a given key. 4379 // 2. Updates BOTH the key and the data for pointing to the actual key-value 4380 // pair inside the database. 4381 // 4382 // \param [in] txn A transaction handle returned 4383 // 4384 // by \ref mdbx_txn_begin(). 4385 // 4386 // \param [in] dbi A database handle returned by \ref mdbx_dbi_open(). 4387 // \param [in,out] key The key to search for in the database. 4388 // \param [in,out] data The data corresponding to the key. 4389 // \param [out] values_count The optional address to return number of values 4390 // 4391 // associated with given key: 4392 // = 0 - in case \ref MDBX_NOTFOUND error; 4393 // = 1 - exactly for databases 4394 // WITHOUT \ref MDBX_DUPSORT; 4395 // >= 1 for databases WITH \ref MDBX_DUPSORT. 4396 // 4397 // \returns A non-zero error value on failure and 0 on success, 4398 // 4399 // some possible errors are: 4400 // 4401 // \retval MDBX_THREAD_MISMATCH Given transaction is not owned 4402 // 4403 // by current thread. 4404 // 4405 // \retval MDBX_NOTFOUND The key was not in the database. 4406 // \retval MDBX_EINVAL An invalid parameter was specified. 4407 func (tx *Tx) GetEx(dbi DBI, key *Val, data *Val) (int, Error) { 4408 var valuesCount uintptr 4409 args := struct { 4410 txn uintptr 4411 key uintptr 4412 data uintptr 4413 valuesCount uintptr 4414 dbi uint32 4415 result Error 4416 }{ 4417 txn: uintptr(unsafe.Pointer(tx.txn)), 4418 key: uintptr(unsafe.Pointer(key)), 4419 data: uintptr(unsafe.Pointer(data)), 4420 valuesCount: uintptr(unsafe.Pointer(&valuesCount)), 4421 dbi: uint32(dbi), 4422 } 4423 ptr := uintptr(unsafe.Pointer(&args)) 4424 unsafecgo.NonBlocking((*byte)(C.do_mdbx_get_ex), ptr, 0) 4425 return int(valuesCount), args.result 4426 } 4427 4428 // Put Store items into a database. 4429 // \ingroup c_crud 4430 // 4431 // This function stores key/data pairs in the database. The default behavior 4432 // is to enter the new key/data pair, replacing any previously existing key 4433 // if duplicates are disallowed, or adding a duplicate data item if 4434 // duplicates are allowed (see \ref MDBX_DUPSORT). 4435 // 4436 // \param [in] txn A transaction handle returned 4437 // 4438 // by \ref mdbx_txn_begin(). 4439 // 4440 // \param [in] dbi A database handle returned by \ref mdbx_dbi_open(). 4441 // \param [in] key The key to store in the database. 4442 // \param [in,out] data The data to store. 4443 // \param [in] flags Special options for this operation. 4444 // 4445 // This parameter must be set to 0 or by bitwise OR'ing 4446 // together one or more of the values described here: 4447 // - \ref MDBX_NODUPDATA 4448 // Enter the new key-value pair only if it does not already appear 4449 // in the database. This flag may only be specified if the database 4450 // was opened with \ref MDBX_DUPSORT. The function will return 4451 // \ref MDBX_KEYEXIST if the key/data pair already appears in the database. 4452 // 4453 // - \ref MDBX_NOOVERWRITE 4454 // Enter the new key/data pair only if the key does not already appear 4455 // in the database. The function will return \ref MDBX_KEYEXIST if the key 4456 // already appears in the database, even if the database supports 4457 // duplicates (see \ref MDBX_DUPSORT). The data parameter will be set 4458 // to point to the existing item. 4459 // 4460 // - \ref MDBX_CURRENT 4461 // Update an single existing entry, but not add new ones. The function will 4462 // return \ref MDBX_NOTFOUND if the given key not exist in the database. 4463 // In case multi-values for the given key, with combination of 4464 // the \ref MDBX_ALLDUPS will replace all multi-values, 4465 // otherwise return the \ref MDBX_EMULTIVAL. 4466 // 4467 // - \ref MDBX_RESERVE 4468 // Reserve space for data of the given size, but don't copy the given 4469 // data. Instead, return a pointer to the reserved space, which the 4470 // caller can fill in later - before the next update operation or the 4471 // transaction ends. This saves an extra memcpy if the data is being 4472 // generated later. MDBX does nothing else with this memory, the caller 4473 // is expected to modify all of the space requested. This flag must not 4474 // be specified if the database was opened with \ref MDBX_DUPSORT. 4475 // 4476 // - \ref MDBX_APPEND 4477 // Append the given key/data pair to the end of the database. This option 4478 // allows fast bulk loading when keys are already known to be in the 4479 // correct order. Loading unsorted keys with this flag will cause 4480 // a \ref MDBX_EKEYMISMATCH error. 4481 // 4482 // - \ref MDBX_APPENDDUP 4483 // As above, but for sorted dup data. 4484 // 4485 // - \ref MDBX_MULTIPLE 4486 // Store multiple contiguous data elements in a single request. This flag 4487 // may only be specified if the database was opened with 4488 // \ref MDBX_DUPFIXED. With combination the \ref MDBX_ALLDUPS 4489 // will replace all multi-values. 4490 // The data argument must be an array of two \ref MDBX_val. The `iov_len` 4491 // of the first \ref MDBX_val must be the size of a single data element. 4492 // The `iov_base` of the first \ref MDBX_val must point to the beginning 4493 // of the array of contiguous data elements which must be properly aligned 4494 // in case of database with \ref MDBX_INTEGERDUP flag. 4495 // The `iov_len` of the second \ref MDBX_val must be the count of the 4496 // number of data elements to store. On return this field will be set to 4497 // the count of the number of elements actually written. The `iov_base` of 4498 // the second \ref MDBX_val is unused. 4499 // 4500 // \see \ref c_crud_hints "Quick reference for Insert/Update/Delete operations" 4501 // 4502 // \returns A non-zero error value on failure and 0 on success, 4503 // 4504 // some possible errors are: 4505 // 4506 // \retval MDBX_THREAD_MISMATCH Given transaction is not owned 4507 // 4508 // by current thread. 4509 // 4510 // \retval MDBX_KEYEXIST The key/value pair already exists in the database. 4511 // \retval MDBX_MAP_FULL The database is full, see \ref mdbx_env_set_mapsize(). 4512 // \retval MDBX_TXN_FULL The transaction has too many dirty pages. 4513 // \retval MDBX_EACCES An attempt was made to write 4514 // 4515 // in a read-only transaction. 4516 // 4517 // \retval MDBX_EINVAL An invalid parameter was specified. 4518 func (tx *Tx) Put(dbi DBI, key *Val, data *Val, flags PutFlags) Error { 4519 args := struct { 4520 txn uintptr 4521 key uintptr 4522 data uintptr 4523 dbi uint32 4524 flags uint32 4525 result Error 4526 }{ 4527 txn: uintptr(unsafe.Pointer(tx.txn)), 4528 key: uintptr(unsafe.Pointer(key)), 4529 data: uintptr(unsafe.Pointer(data)), 4530 dbi: uint32(dbi), 4531 flags: uint32(flags), 4532 } 4533 ptr := uintptr(unsafe.Pointer(&args)) 4534 unsafecgo.NonBlocking((*byte)(C.do_mdbx_put), ptr, 0) 4535 return args.result 4536 } 4537 4538 // Replace items in a database. 4539 // \ingroup c_crud 4540 // 4541 // This function allows to update or delete an existing value at the same time 4542 // as the previous value is retrieved. If the argument new_data equal is NULL 4543 // zero, the removal is performed, otherwise the update/insert. 4544 // 4545 // The current value may be in an already changed (aka dirty) page. In this 4546 // case, the page will be overwritten during the update, and the old value will 4547 // be lost. Therefore, an additional buffer must be passed via old_data 4548 // argument initially to copy the old value. If the buffer passed in is too 4549 // small, the function will return \ref MDBX_RESULT_TRUE by setting iov_len 4550 // field pointed by old_data argument to the appropriate value, without 4551 // performing any changes. 4552 // 4553 // For databases with non-unique keys (i.e. with \ref MDBX_DUPSORT flag), 4554 // another use case is also possible, when by old_data argument selects a 4555 // specific item from multi-value/duplicates with the same key for deletion or 4556 // update. To select this scenario in flags should simultaneously specify 4557 // \ref MDBX_CURRENT and \ref MDBX_NOOVERWRITE. This combination is chosen 4558 // because it makes no sense, and thus allows you to identify the request of 4559 // such a scenario. 4560 // 4561 // \param [in] txn A transaction handle returned 4562 // 4563 // by \ref mdbx_txn_begin(). 4564 // 4565 // \param [in] dbi A database handle returned by \ref mdbx_dbi_open(). 4566 // \param [in] key The key to store in the database. 4567 // \param [in] new_data The data to store, if NULL then deletion will 4568 // 4569 // be performed. 4570 // 4571 // \param [in,out] old_data The buffer for retrieve previous value as describe 4572 // 4573 // above. 4574 // 4575 // \param [in] flags Special options for this operation. 4576 // 4577 // This parameter must be set to 0 or by bitwise 4578 // OR'ing together one or more of the values 4579 // described in \ref mdbx_put() description above, 4580 // and additionally 4581 // (\ref MDBX_CURRENT | \ref MDBX_NOOVERWRITE) 4582 // combination for selection particular item from 4583 // multi-value/duplicates. 4584 // 4585 // \see \ref c_crud_hints "Quick reference for Insert/Update/Delete operations" 4586 // 4587 // \returns A non-zero error value on failure and 0 on success. 4588 func (tx *Tx) Replace(dbi DBI, key *Val, data *Val, oldData *Val, flags PutFlags) Error { 4589 args := struct { 4590 txn uintptr 4591 key uintptr 4592 data uintptr 4593 oldData uintptr 4594 dbi uint32 4595 flags uint32 4596 result Error 4597 }{ 4598 txn: uintptr(unsafe.Pointer(tx.txn)), 4599 key: uintptr(unsafe.Pointer(key)), 4600 data: uintptr(unsafe.Pointer(data)), 4601 oldData: uintptr(unsafe.Pointer(oldData)), 4602 dbi: uint32(dbi), 4603 flags: uint32(flags), 4604 } 4605 ptr := uintptr(unsafe.Pointer(&args)) 4606 unsafecgo.NonBlocking((*byte)(C.do_mdbx_replace), ptr, 0) 4607 return args.result 4608 } 4609 4610 // Delete items from a database. 4611 // \ingroup c_crud 4612 // 4613 // This function removes key/data pairs from the database. 4614 // 4615 // \note The data parameter is NOT ignored regardless the database does 4616 // support sorted duplicate data items or not. If the data parameter 4617 // is non-NULL only the matching data item will be deleted. Otherwise, if data 4618 // parameter is NULL, any/all value(s) for specified key will be deleted. 4619 // 4620 // This function will return \ref MDBX_NOTFOUND if the specified key/data 4621 // pair is not in the database. 4622 // 4623 // \see \ref c_crud_hints "Quick reference for Insert/Update/Delete operations" 4624 // 4625 // \param [in] txn A transaction handle returned by \ref mdbx_txn_begin(). 4626 // \param [in] dbi A database handle returned by \ref mdbx_dbi_open(). 4627 // \param [in] key The key to delete from the database. 4628 // \param [in] data The data to delete. 4629 // 4630 // \returns A non-zero error value on failure and 0 on success, 4631 // 4632 // some possible errors are: 4633 // 4634 // \retval MDBX_EACCES An attempt was made to write 4635 // 4636 // in a read-only transaction. 4637 // 4638 // \retval MDBX_EINVAL An invalid parameter was specified. 4639 func (tx *Tx) Delete(dbi DBI, key *Val, data *Val) Error { 4640 args := struct { 4641 txn uintptr 4642 key uintptr 4643 data uintptr 4644 dbi uint32 4645 result Error 4646 }{ 4647 txn: uintptr(unsafe.Pointer(tx.txn)), 4648 key: uintptr(unsafe.Pointer(key)), 4649 data: uintptr(unsafe.Pointer(data)), 4650 dbi: uint32(dbi), 4651 } 4652 ptr := uintptr(unsafe.Pointer(&args)) 4653 unsafecgo.NonBlocking((*byte)(C.do_mdbx_del), ptr, 0) 4654 return args.result 4655 } 4656 4657 ////////////////////////////////////////////////////////////////////////////////////////// 4658 // Cursor 4659 ////////////////////////////////////////////////////////////////////////////////////////// 4660 4661 type Cursor C.MDBX_cursor 4662 4663 // NewCursor Create a cursor handle but not bind it to transaction nor DBI handle. 4664 // \ingroup c_cursors 4665 // 4666 // An capable of operation cursor is associated with a specific transaction and 4667 // database. A cursor cannot be used when its database handle is closed. Nor 4668 // when its transaction has ended, except with \ref mdbx_cursor_bind() and 4669 // \ref mdbx_cursor_renew(). 4670 // Also it can be discarded with \ref mdbx_cursor_close(). 4671 // 4672 // A cursor must be closed explicitly always, before or after its transaction 4673 // ends. It can be reused with \ref mdbx_cursor_bind() 4674 // or \ref mdbx_cursor_renew() before finally closing it. 4675 // 4676 // \note In contrast to LMDB, the MDBX required that any opened cursors can be 4677 // reused and must be freed explicitly, regardless ones was opened in a 4678 // read-only or write transaction. The REASON for this is eliminates ambiguity 4679 // which helps to avoid errors such as: use-after-free, double-free, i.e. 4680 // memory corruption and segfaults. 4681 // 4682 // \param [in] context A pointer to application context to be associated with 4683 // 4684 // created cursor and could be retrieved by 4685 // \ref mdbx_cursor_get_userctx() until cursor closed. 4686 // 4687 // \returns Created cursor handle or NULL in case out of memory. 4688 func NewCursor() *Cursor { 4689 args := struct { 4690 context uintptr 4691 cursor uintptr 4692 }{} 4693 ptr := uintptr(unsafe.Pointer(&args)) 4694 unsafecgo.NonBlocking((*byte)(C.do_mdbx_cursor_create), ptr, 0) 4695 return (*Cursor)(unsafe.Pointer(args.cursor)) 4696 } 4697 4698 // Bind cursor to specified transaction and DBI handle. 4699 // \ingroup c_cursors 4700 // 4701 // Using of the `mdbx_cursor_bind()` is equivalent to calling 4702 // \ref mdbx_cursor_renew() but with specifying an arbitrary dbi handle. 4703 // 4704 // An capable of operation cursor is associated with a specific transaction and 4705 // database. The cursor may be associated with a new transaction, 4706 // and referencing a new or the same database handle as it was created with. 4707 // This may be done whether the previous transaction is live or dead. 4708 // 4709 // \note In contrast to LMDB, the MDBX required that any opened cursors can be 4710 // reused and must be freed explicitly, regardless ones was opened in a 4711 // read-only or write transaction. The REASON for this is eliminates ambiguity 4712 // which helps to avoid errors such as: use-after-free, double-free, i.e. 4713 // memory corruption and segfaults. 4714 // 4715 // \param [in] txn A transaction handle returned by \ref mdbx_txn_begin(). 4716 // \param [in] dbi A database handle returned by \ref mdbx_dbi_open(). 4717 // \param [out] cursor A cursor handle returned by \ref mdbx_cursor_create(). 4718 // 4719 // \returns A non-zero error value on failure and 0 on success, 4720 // 4721 // some possible errors are: 4722 // 4723 // \retval MDBX_THREAD_MISMATCH Given transaction is not owned 4724 // 4725 // by current thread. 4726 // 4727 // \retval MDBX_EINVAL An invalid parameter was specified. 4728 func (tx *Tx) Bind(cursor *Cursor, dbi DBI) Error { 4729 args := struct { 4730 txn uintptr 4731 cursor uintptr 4732 dbi DBI 4733 result Error 4734 }{ 4735 txn: uintptr(unsafe.Pointer(tx.txn)), 4736 cursor: uintptr(unsafe.Pointer(cursor)), 4737 dbi: dbi, 4738 } 4739 ptr := uintptr(unsafe.Pointer(&args)) 4740 unsafecgo.NonBlocking((*byte)(C.do_mdbx_cursor_bind), ptr, 0) 4741 return args.result 4742 } 4743 4744 // OpenCursor Create a cursor handle for the specified transaction and DBI handle. 4745 // \ingroup c_cursors 4746 // 4747 // Using of the `mdbx_cursor_open()` is equivalent to calling 4748 // \ref mdbx_cursor_create() and then \ref mdbx_cursor_bind() functions. 4749 // 4750 // An capable of operation cursor is associated with a specific transaction and 4751 // database. A cursor cannot be used when its database handle is closed. Nor 4752 // when its transaction has ended, except with \ref mdbx_cursor_bind() and 4753 // \ref mdbx_cursor_renew(). 4754 // Also it can be discarded with \ref mdbx_cursor_close(). 4755 // 4756 // A cursor must be closed explicitly always, before or after its transaction 4757 // ends. It can be reused with \ref mdbx_cursor_bind() 4758 // or \ref mdbx_cursor_renew() before finally closing it. 4759 // 4760 // \note In contrast to LMDB, the MDBX required that any opened cursors can be 4761 // reused and must be freed explicitly, regardless ones was opened in a 4762 // read-only or write transaction. The REASON for this is eliminates ambiguity 4763 // which helps to avoid errors such as: use-after-free, double-free, i.e. 4764 // memory corruption and segfaults. 4765 // 4766 // \param [in] txn A transaction handle returned by \ref mdbx_txn_begin(). 4767 // \param [in] dbi A database handle returned by \ref mdbx_dbi_open(). 4768 // \param [out] cursor Address where the new \ref MDBX_cursor handle will be 4769 // 4770 // stored. 4771 // 4772 // \returns A non-zero error value on failure and 0 on success, 4773 // 4774 // some possible errors are: 4775 // 4776 // \retval MDBX_THREAD_MISMATCH Given transaction is not owned 4777 // 4778 // by current thread. 4779 // 4780 // \retval MDBX_EINVAL An invalid parameter was specified. 4781 func (tx *Tx) OpenCursor(dbi DBI) (*Cursor, Error) { 4782 var cursor *C.MDBX_cursor 4783 args := struct { 4784 txn uintptr 4785 cursor uintptr 4786 dbi DBI 4787 result Error 4788 }{ 4789 txn: uintptr(unsafe.Pointer(tx.txn)), 4790 cursor: uintptr(unsafe.Pointer(&cursor)), 4791 dbi: dbi, 4792 } 4793 ptr := uintptr(unsafe.Pointer(&args)) 4794 unsafecgo.NonBlocking((*byte)(C.do_mdbx_cursor_open), ptr, 0) 4795 return (*Cursor)(unsafe.Pointer(cursor)), args.result 4796 } 4797 4798 // Close a cursor handle. 4799 // \ingroup c_cursors 4800 // 4801 // The cursor handle will be freed and must not be used again after this call, 4802 // but its transaction may still be live. 4803 // 4804 // \note In contrast to LMDB, the MDBX required that any opened cursors can be 4805 // reused and must be freed explicitly, regardless ones was opened in a 4806 // read-only or write transaction. The REASON for this is eliminates ambiguity 4807 // which helps to avoid errors such as: use-after-free, double-free, i.e. 4808 // memory corruption and segfaults. 4809 // 4810 // \param [in] cursor A cursor handle returned by \ref mdbx_cursor_open() 4811 // 4812 // or \ref mdbx_cursor_create(). 4813 func (cur *Cursor) Close() Error { 4814 ptr := uintptr(unsafe.Pointer(cur)) 4815 unsafecgo.NonBlocking((*byte)(C.do_mdbx_cursor_close), ptr, 0) 4816 return ErrSuccess 4817 } 4818 4819 // Renew a cursor handle. 4820 // \ingroup c_cursors 4821 // 4822 // An capable of operation cursor is associated with a specific transaction and 4823 // database. The cursor may be associated with a new transaction, 4824 // and referencing a new or the same database handle as it was created with. 4825 // This may be done whether the previous transaction is live or dead. 4826 // 4827 // Using of the `mdbx_cursor_renew()` is equivalent to calling 4828 // \ref mdbx_cursor_bind() with the DBI handle that previously 4829 // the cursor was used with. 4830 // 4831 // \note In contrast to LMDB, the MDBX allow any cursor to be re-used by using 4832 // \ref mdbx_cursor_renew(), to avoid unnecessary malloc/free overhead until it 4833 // freed by \ref mdbx_cursor_close(). 4834 // 4835 // \param [in] txn A transaction handle returned by \ref mdbx_txn_begin(). 4836 // \param [in] cursor A cursor handle returned by \ref mdbx_cursor_open(). 4837 // 4838 // \returns A non-zero error value on failure and 0 on success, 4839 // 4840 // some possible errors are: 4841 // 4842 // \retval MDBX_THREAD_MISMATCH Given transaction is not owned 4843 // 4844 // by current thread. 4845 // 4846 // \retval MDBX_EINVAL An invalid parameter was specified. 4847 func (cur *Cursor) Renew(tx *Tx) Error { 4848 args := struct { 4849 txn uintptr 4850 cursor uintptr 4851 result Error 4852 }{ 4853 txn: uintptr(unsafe.Pointer(tx.txn)), 4854 cursor: uintptr(unsafe.Pointer(cur)), 4855 } 4856 ptr := uintptr(unsafe.Pointer(&args)) 4857 unsafecgo.NonBlocking((*byte)(C.do_mdbx_cursor_renew), ptr, 0) 4858 return args.result 4859 } 4860 4861 // Tx Return the cursor's transaction handle. 4862 // \ingroup c_cursors 4863 // 4864 // \param [in] cursor A cursor handle returned by \ref mdbx_cursor_open(). 4865 func (cur *Cursor) Tx() *C.MDBX_txn { 4866 args := struct { 4867 cursor uintptr 4868 txn uintptr 4869 }{ 4870 cursor: uintptr(unsafe.Pointer(cur)), 4871 } 4872 ptr := uintptr(unsafe.Pointer(&args)) 4873 unsafecgo.NonBlocking((*byte)(C.do_mdbx_cursor_txn), ptr, 0) 4874 return (*C.MDBX_txn)(unsafe.Pointer(args.txn)) 4875 } 4876 4877 // DBI Return the cursor's database handle. 4878 // \ingroup c_cursors 4879 // 4880 // \param [in] cursor A cursor handle returned by \ref mdbx_cursor_open(). 4881 func (cur *Cursor) DBI() DBI { 4882 args := struct { 4883 cursor uintptr 4884 dbi DBI 4885 }{ 4886 cursor: uintptr(unsafe.Pointer(cur)), 4887 } 4888 ptr := uintptr(unsafe.Pointer(&args)) 4889 unsafecgo.NonBlocking((*byte)(C.do_mdbx_cursor_dbi), ptr, 0) 4890 return args.dbi 4891 } 4892 4893 // Copy cursor position and state. 4894 // \ingroup c_cursors 4895 // 4896 // \param [in] src A source cursor handle returned 4897 // by \ref mdbx_cursor_create() or \ref mdbx_cursor_open(). 4898 // 4899 // \param [in,out] dest A destination cursor handle returned 4900 // by \ref mdbx_cursor_create() or \ref mdbx_cursor_open(). 4901 // 4902 // \returns A non-zero error value on failure and 0 on success. 4903 func (cur *Cursor) Copy(dest *Cursor) Error { 4904 args := struct { 4905 src uintptr 4906 dest uintptr 4907 result Error 4908 }{ 4909 src: uintptr(unsafe.Pointer(cur)), 4910 dest: uintptr(unsafe.Pointer(dest)), 4911 } 4912 ptr := uintptr(unsafe.Pointer(&args)) 4913 unsafecgo.NonBlocking((*byte)(C.do_mdbx_cursor_copy), ptr, 0) 4914 return args.result 4915 } 4916 4917 // Get Retrieve by cursor. 4918 // \ingroup c_crud 4919 // 4920 // This function retrieves key/data pairs from the database. The address and 4921 // length of the key are returned in the object to which key refers (except 4922 // for the case of the \ref MDBX_SET option, in which the key object is 4923 // unchanged), and the address and length of the data are returned in the object 4924 // to which data refers. 4925 // \see mdbx_get() 4926 // 4927 // \param [in] cursor A cursor handle returned by \ref mdbx_cursor_open(). 4928 // \param [in,out] key The key for a retrieved item. 4929 // \param [in,out] data The data of a retrieved item. 4930 // \param [in] op A cursor operation \ref MDBX_cursor_op. 4931 // 4932 // \returns A non-zero error value on failure and 0 on success, 4933 // 4934 // some possible errors are: 4935 // 4936 // \retval MDBX_THREAD_MISMATCH Given transaction is not owned 4937 // 4938 // by current thread. 4939 // 4940 // \retval MDBX_NOTFOUND No matching key found. 4941 // \retval MDBX_EINVAL An invalid parameter was specified. 4942 func (cur *Cursor) Get(key *Val, data *Val, op CursorOp) Error { 4943 args := struct { 4944 cursor uintptr 4945 key uintptr 4946 data uintptr 4947 op CursorOp 4948 result Error 4949 }{ 4950 cursor: uintptr(unsafe.Pointer(cur)), 4951 key: uintptr(unsafe.Pointer(key)), 4952 data: uintptr(unsafe.Pointer(data)), 4953 op: op, 4954 } 4955 ptr := uintptr(unsafe.Pointer(&args)) 4956 unsafecgo.NonBlocking((*byte)(C.do_mdbx_cursor_get), ptr, 0) 4957 return args.result 4958 } 4959 4960 // Put Store by cursor. 4961 // \ingroup c_crud 4962 // 4963 // This function stores key/data pairs into the database. The cursor is 4964 // positioned at the new item, or on failure usually near it. 4965 // 4966 // \param [in] cursor A cursor handle returned by \ref mdbx_cursor_open(). 4967 // \param [in] key The key operated on. 4968 // \param [in,out] data The data operated on. 4969 // \param [in] flags Options for this operation. This parameter 4970 // 4971 // must be set to 0 or by bitwise OR'ing together 4972 // one or more of the values described here: 4973 // - \ref MDBX_CURRENT 4974 // Replace the item at the current cursor position. The key parameter 4975 // must still be provided, and must match it, otherwise the function 4976 // return \ref MDBX_EKEYMISMATCH. With combination the 4977 // \ref MDBX_ALLDUPS will replace all multi-values. 4978 // 4979 // \note MDBX allows (unlike LMDB) you to change the size of the data and 4980 // automatically handles reordering for sorted duplicates 4981 // (see \ref MDBX_DUPSORT). 4982 // 4983 // - \ref MDBX_NODUPDATA 4984 // Enter the new key-value pair only if it does not already appear in the 4985 // database. This flag may only be specified if the database was opened 4986 // with \ref MDBX_DUPSORT. The function will return \ref MDBX_KEYEXIST 4987 // if the key/data pair already appears in the database. 4988 // 4989 // - \ref MDBX_NOOVERWRITE 4990 // Enter the new key/data pair only if the key does not already appear 4991 // in the database. The function will return \ref MDBX_KEYEXIST if the key 4992 // already appears in the database, even if the database supports 4993 // duplicates (\ref MDBX_DUPSORT). 4994 // 4995 // - \ref MDBX_RESERVE 4996 // Reserve space for data of the given size, but don't copy the given 4997 // data. Instead, return a pointer to the reserved space, which the 4998 // caller can fill in later - before the next update operation or the 4999 // transaction ends. This saves an extra memcpy if the data is being 5000 // generated later. This flag must not be specified if the database 5001 // was opened with \ref MDBX_DUPSORT. 5002 // 5003 // - \ref MDBX_APPEND 5004 // Append the given key/data pair to the end of the database. No key 5005 // comparisons are performed. This option allows fast bulk loading when 5006 // keys are already known to be in the correct order. Loading unsorted 5007 // keys with this flag will cause a \ref MDBX_KEYEXIST error. 5008 // 5009 // - \ref MDBX_APPENDDUP 5010 // As above, but for sorted dup data. 5011 // 5012 // - \ref MDBX_MULTIPLE 5013 // Store multiple contiguous data elements in a single request. This flag 5014 // may only be specified if the database was opened with 5015 // \ref MDBX_DUPFIXED. With combination the \ref MDBX_ALLDUPS 5016 // will replace all multi-values. 5017 // The data argument must be an array of two \ref MDBX_val. The `iov_len` 5018 // of the first \ref MDBX_val must be the size of a single data element. 5019 // The `iov_base` of the first \ref MDBX_val must point to the beginning 5020 // of the array of contiguous data elements which must be properly aligned 5021 // in case of database with \ref MDBX_INTEGERDUP flag. 5022 // The `iov_len` of the second \ref MDBX_val must be the count of the 5023 // number of data elements to store. On return this field will be set to 5024 // the count of the number of elements actually written. The `iov_base` of 5025 // the second \ref MDBX_val is unused. 5026 // 5027 // \see \ref c_crud_hints "Quick reference for Insert/Update/Delete operations" 5028 // 5029 // \returns A non-zero error value on failure and 0 on success, 5030 // 5031 // some possible errors are: 5032 // 5033 // \retval MDBX_THREAD_MISMATCH Given transaction is not owned 5034 // 5035 // by current thread. 5036 // 5037 // \retval MDBX_EKEYMISMATCH The given key value is mismatched to the current 5038 // 5039 // cursor position 5040 // 5041 // \retval MDBX_MAP_FULL The database is full, 5042 // 5043 // see \ref mdbx_env_set_mapsize(). 5044 // 5045 // \retval MDBX_TXN_FULL The transaction has too many dirty pages. 5046 // \retval MDBX_EACCES An attempt was made to write in a read-only 5047 // 5048 // transaction. 5049 // 5050 // \retval MDBX_EINVAL An invalid parameter was specified. 5051 func (cur *Cursor) Put(key *Val, data *Val, flags PutFlags) Error { 5052 args := struct { 5053 cursor uintptr 5054 key uintptr 5055 data uintptr 5056 flags PutFlags 5057 result Error 5058 }{ 5059 cursor: uintptr(unsafe.Pointer(cur)), 5060 key: uintptr(unsafe.Pointer(key)), 5061 data: uintptr(unsafe.Pointer(data)), 5062 flags: flags, 5063 } 5064 ptr := uintptr(unsafe.Pointer(&args)) 5065 unsafecgo.NonBlocking((*byte)(C.do_mdbx_cursor_put), ptr, 0) 5066 return args.result 5067 } 5068 5069 // Delete current key/data pair. 5070 // \ingroup c_crud 5071 // 5072 // This function deletes the key/data pair to which the cursor refers. This 5073 // does not invalidate the cursor, so operations such as \ref MDBX_NEXT can 5074 // still be used on it. Both \ref MDBX_NEXT and \ref MDBX_GET_CURRENT will 5075 // return the same record after this operation. 5076 // 5077 // \param [in] cursor A cursor handle returned by mdbx_cursor_open(). 5078 // \param [in] flags Options for this operation. This parameter must be set 5079 // to one of the values described here. 5080 // 5081 // - \ref MDBX_CURRENT Delete only single entry at current cursor position. 5082 // - \ref MDBX_ALLDUPS 5083 // or \ref MDBX_NODUPDATA (supported for compatibility) 5084 // Delete all of the data items for the current key. This flag has effect 5085 // only for database(s) was created with \ref MDBX_DUPSORT. 5086 // 5087 // \see \ref c_crud_hints "Quick reference for Insert/Update/Delete operations" 5088 // 5089 // \returns A non-zero error value on failure and 0 on success, 5090 // 5091 // some possible errors are: 5092 // 5093 // \retval MDBX_THREAD_MISMATCH Given transaction is not owned 5094 // 5095 // by current thread. 5096 // 5097 // \retval MDBX_MAP_FULL The database is full, 5098 // 5099 // see \ref mdbx_env_set_mapsize(). 5100 // 5101 // \retval MDBX_TXN_FULL The transaction has too many dirty pages. 5102 // \retval MDBX_EACCES An attempt was made to write in a read-only 5103 // 5104 // transaction. 5105 // 5106 // \retval MDBX_EINVAL An invalid parameter was specified. 5107 func (cur *Cursor) Delete(flags PutFlags) Error { 5108 args := struct { 5109 cursor uintptr 5110 flags PutFlags 5111 result Error 5112 }{ 5113 cursor: uintptr(unsafe.Pointer(cur)), 5114 flags: flags, 5115 } 5116 ptr := uintptr(unsafe.Pointer(&args)) 5117 unsafecgo.NonBlocking((*byte)(C.do_mdbx_cursor_del), ptr, 0) 5118 return args.result 5119 } 5120 5121 // Count Return count of duplicates for current key. 5122 // \ingroup c_crud 5123 // 5124 // This call is valid for all databases, but reasonable only for that support 5125 // sorted duplicate data items \ref MDBX_DUPSORT. 5126 // 5127 // \param [in] cursor A cursor handle returned by \ref mdbx_cursor_open(). 5128 // \param [out] pcount Address where the count will be stored. 5129 // 5130 // \returns A non-zero error value on failure and 0 on success, 5131 // 5132 // some possible errors are: 5133 // 5134 // \retval MDBX_THREAD_MISMATCH Given transaction is not owned 5135 // 5136 // by current thread. 5137 // 5138 // \retval MDBX_EINVAL Cursor is not initialized, or an invalid parameter 5139 // 5140 // was specified. 5141 func (cur *Cursor) Count() (int, Error) { 5142 var count uintptr 5143 args := struct { 5144 cursor uintptr 5145 count uintptr 5146 result Error 5147 }{ 5148 cursor: uintptr(unsafe.Pointer(cur)), 5149 count: uintptr(unsafe.Pointer(&count)), 5150 } 5151 ptr := uintptr(unsafe.Pointer(&args)) 5152 unsafecgo.NonBlocking((*byte)(C.do_mdbx_cursor_count), ptr, 0) 5153 return int(count), args.result 5154 } 5155 5156 // EOF Determines whether the cursor is pointed to a key-value pair or not, 5157 // i.e. was not positioned or points to the end of data. 5158 // \ingroup c_cursors 5159 // 5160 // \param [in] cursor A cursor handle returned by \ref mdbx_cursor_open(). 5161 // 5162 // \returns A \ref MDBX_RESULT_TRUE or \ref MDBX_RESULT_FALSE value, 5163 // 5164 // otherwise the error code: 5165 // 5166 // \retval MDBX_RESULT_TRUE No more data available or cursor not 5167 // 5168 // positioned 5169 // 5170 // \retval MDBX_RESULT_FALSE A data is available 5171 // \retval Otherwise the error code 5172 func (cur *Cursor) EOF() Error { 5173 args := struct { 5174 cursor uintptr 5175 result Error 5176 }{ 5177 cursor: uintptr(unsafe.Pointer(cur)), 5178 } 5179 ptr := uintptr(unsafe.Pointer(&args)) 5180 unsafecgo.NonBlocking((*byte)(C.do_mdbx_cursor_eof), ptr, 0) 5181 return args.result 5182 } 5183 5184 // OnFirst Determines whether the cursor is pointed to the first key-value pair 5185 // or not. \ingroup c_cursors 5186 // 5187 // \param [in] cursor A cursor handle returned by \ref mdbx_cursor_open(). 5188 // 5189 // \returns A MDBX_RESULT_TRUE or MDBX_RESULT_FALSE value, 5190 // 5191 // otherwise the error code: 5192 // 5193 // \retval MDBX_RESULT_TRUE Cursor positioned to the first key-value pair 5194 // \retval MDBX_RESULT_FALSE Cursor NOT positioned to the first key-value 5195 // pair \retval Otherwise the error code 5196 func (cur *Cursor) OnFirst() Error { 5197 args := struct { 5198 cursor uintptr 5199 result Error 5200 }{ 5201 cursor: uintptr(unsafe.Pointer(cur)), 5202 } 5203 ptr := uintptr(unsafe.Pointer(&args)) 5204 unsafecgo.NonBlocking((*byte)(C.do_mdbx_cursor_on_first), ptr, 0) 5205 return args.result 5206 } 5207 5208 // OnLast Determines whether the cursor is pointed to the last key-value pair 5209 // or not. \ingroup c_cursors 5210 // 5211 // \param [in] cursor A cursor handle returned by \ref mdbx_cursor_open(). 5212 // 5213 // \returns A \ref MDBX_RESULT_TRUE or \ref MDBX_RESULT_FALSE value, 5214 // 5215 // otherwise the error code: 5216 // 5217 // \retval MDBX_RESULT_TRUE Cursor positioned to the last key-value pair 5218 // \retval MDBX_RESULT_FALSE Cursor NOT positioned to the last key-value pair 5219 // \retval Otherwise the error code 5220 func (cur *Cursor) OnLast() Error { 5221 args := struct { 5222 cursor uintptr 5223 result Error 5224 }{ 5225 cursor: uintptr(unsafe.Pointer(cur)), 5226 } 5227 ptr := uintptr(unsafe.Pointer(&args)) 5228 unsafecgo.NonBlocking((*byte)(C.do_mdbx_cursor_on_last), ptr, 0) 5229 return args.result 5230 } 5231 5232 // EstimateDistance 5233 // \details \note The estimation result varies greatly depending on the filling 5234 // of specific pages and the overall balance of the b-tree: 5235 // 5236 // 1. The number of items is estimated by analyzing the height and fullness of 5237 // the b-tree. The accuracy of the result directly depends on the balance of 5238 // the b-tree, which in turn is determined by the history of previous 5239 // insert/delete operations and the nature of the data (i.e. variability of 5240 // keys length and so on). Therefore, the accuracy of the estimation can vary 5241 // greatly in a particular situation. 5242 // 5243 // 2. To understand the potential spread of results, you should consider a 5244 // possible situations basing on the general criteria for splitting and merging 5245 // b-tree pages: 5246 // - the page is split into two when there is no space for added data; 5247 // - two pages merge if the result fits in half a page; 5248 // - thus, the b-tree can consist of an arbitrary combination of pages filled 5249 // both completely and only 1/4. Therefore, in the worst case, the result 5250 // can diverge 4 times for each level of the b-tree excepting the first and 5251 // the last. 5252 // 5253 // 3. In practice, the probability of extreme cases of the above situation is 5254 // close to zero and in most cases the error does not exceed a few percent. On 5255 // the other hand, it's just a chance you shouldn't overestimate./// 5256 5257 // EstimateDistance the distance between cursors as a number of elements. 5258 // \ingroup c_rqest 5259 // 5260 // This function performs a rough estimate based only on b-tree pages that are 5261 // common for the both cursor's stacks. The results of such estimation can be 5262 // used to build and/or optimize query execution plans. 5263 // 5264 // Please see notes on accuracy of the result in the details 5265 // of \ref c_rqest section. 5266 // 5267 // Both cursors must be initialized for the same database and the same 5268 // transaction. 5269 // 5270 // \param [in] first The first cursor for estimation. 5271 // \param [in] last The second cursor for estimation. 5272 // \param [out] distance_items The pointer to store estimated distance value, 5273 // 5274 // i.e. `*distance_items = distance(first, last)`. 5275 // 5276 // \returns A non-zero error value on failure and 0 on success. 5277 func EstimateDistance(first, last *Cursor) (int64, Error) { 5278 var distance int64 5279 args := struct { 5280 first uintptr 5281 last uintptr 5282 distance uintptr 5283 result Error 5284 }{ 5285 first: uintptr(unsafe.Pointer(first)), 5286 last: uintptr(unsafe.Pointer(last)), 5287 distance: uintptr(unsafe.Pointer(&distance)), 5288 } 5289 ptr := uintptr(unsafe.Pointer(&args)) 5290 unsafecgo.NonBlocking((*byte)(C.do_mdbx_estimate_distance), ptr, 0) 5291 return distance, args.result 5292 }