lmdb 0.4.1 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -4
- data/CHANGES +5 -0
- data/CONTRIBUTORS +1 -0
- data/Rakefile +59 -0
- data/ext/lmdb_ext/liblmdb/CHANGES +25 -1
- data/ext/lmdb_ext/liblmdb/COPYRIGHT +1 -1
- data/ext/lmdb_ext/liblmdb/lmdb.h +65 -21
- data/ext/lmdb_ext/liblmdb/mdb.c +626 -395
- data/ext/lmdb_ext/liblmdb/midl.c +1 -3
- data/ext/lmdb_ext/lmdb_ext.c +77 -4
- data/ext/lmdb_ext/lmdb_ext.h +15 -0
- data/lib/lmdb/version.rb +1 -1
- data/lmdb.gemspec +2 -2
- data/spec/helper.rb +3 -1
- data/spec/lmdb_spec.rb +16 -6
- metadata +11 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 19495dad2d084f39462d5938acbc27ad061f797e
|
4
|
+
data.tar.gz: 8dfca9b055ccf2fa62a8bddbd822b8a14b0cb6f5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9d671fbfae42a4d3ed1022deb479cebc57e31b740ba86fb2f125960b8fee38f8020fa0f008b2a35b9a6b2e62b6497b31bcb656dba9f95caafeab1d1f90710d54
|
7
|
+
data.tar.gz: 9912e57edd9db4d966fc13c2603488cc1f50acd0560b678e98a5eb965d285b2974b1c06874d89ac69cead95b42b64634b3c2d8d240df81710693b309a792bfdc
|
data/.travis.yml
CHANGED
data/CHANGES
CHANGED
data/CONTRIBUTORS
CHANGED
data/Rakefile
CHANGED
@@ -1,5 +1,9 @@
|
|
1
1
|
#!/usr/bin/env rake
|
2
2
|
|
3
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "lib"))
|
4
|
+
GEMSPEC = Dir['*.gemspec'].first
|
5
|
+
PRJ = File.basename(GEMSPEC, ".gemspec")
|
6
|
+
|
3
7
|
require 'bundler/setup'
|
4
8
|
require 'rspec/core/rake_task'
|
5
9
|
require 'rake/extensiontask'
|
@@ -8,3 +12,58 @@ RSpec::Core::RakeTask.new :spec
|
|
8
12
|
Rake::ExtensionTask.new :lmdb_ext
|
9
13
|
|
10
14
|
task :default => [:compile, :spec]
|
15
|
+
|
16
|
+
def version
|
17
|
+
@version ||= begin
|
18
|
+
require "#{PRJ}/version"
|
19
|
+
warn "LMDB::VERSION not a string" unless LMDB::VERSION.kind_of? String
|
20
|
+
LMDB::VERSION
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def tag
|
25
|
+
@tag ||= "v#{version}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def latest
|
29
|
+
@latest ||= `git describe --abbrev=0 --tags --match 'v*'`.chomp
|
30
|
+
end
|
31
|
+
|
32
|
+
desc "Commit, tag, and push repo; build and push gem"
|
33
|
+
task :release => "release:is_new_version" do
|
34
|
+
require 'tempfile'
|
35
|
+
|
36
|
+
sh "gem build #{GEMSPEC}"
|
37
|
+
|
38
|
+
file = Tempfile.new "template"
|
39
|
+
begin
|
40
|
+
file.puts "release #{version}"
|
41
|
+
file.close
|
42
|
+
sh "git commit --allow-empty -a -v -t #{file.path}"
|
43
|
+
ensure
|
44
|
+
file.close unless file.closed?
|
45
|
+
file.unlink
|
46
|
+
end
|
47
|
+
|
48
|
+
sh "git tag #{tag}"
|
49
|
+
sh "git push"
|
50
|
+
sh "git push --tags"
|
51
|
+
|
52
|
+
sh "gem push #{tag}.gem"
|
53
|
+
end
|
54
|
+
|
55
|
+
namespace :release do
|
56
|
+
desc "Diff to latest release"
|
57
|
+
task :diff do
|
58
|
+
sh "git diff #{latest}"
|
59
|
+
end
|
60
|
+
|
61
|
+
desc "Log to latest release"
|
62
|
+
task :log do
|
63
|
+
sh "git log #{latest}.."
|
64
|
+
end
|
65
|
+
|
66
|
+
task :is_new_version do
|
67
|
+
abort "#{tag} exists; update version!" unless `git tag -l #{tag}`.empty?
|
68
|
+
end
|
69
|
+
end
|
@@ -1,5 +1,29 @@
|
|
1
1
|
LMDB 0.9 Change Log
|
2
2
|
|
3
|
+
LMDB 0.9.12 Release (2014/06/13)
|
4
|
+
Fix MDB_GET_BOTH regression (ITS#7875,#7681)
|
5
|
+
Fix MDB_MULTIPLE writing multiple keys (ITS#7834)
|
6
|
+
Fix mdb_rebalance (ITS#7829)
|
7
|
+
Fix mdb_page_split (ITS#7815)
|
8
|
+
Fix md_entries count (ITS#7861,#7828,#7793)
|
9
|
+
Fix MDB_CURRENT (ITS#7793)
|
10
|
+
Fix possible crash on Windows DLL detach
|
11
|
+
Misc code cleanup
|
12
|
+
Documentation
|
13
|
+
mdb_cursor_put: cursor moves on error (ITS#7771)
|
14
|
+
|
15
|
+
|
16
|
+
LMDB 0.9.11 Release (2014/01/15)
|
17
|
+
Add mdb_env_set_assert() (ITS#7775)
|
18
|
+
Fix: invalidate txn on page allocation errors (ITS#7377)
|
19
|
+
Fix xcursor tracking in mdb_cursor_del0() (ITS#7771)
|
20
|
+
Fix corruption from deletes (ITS#7756)
|
21
|
+
Fix Windows/MSVC build issues
|
22
|
+
Raise safe limit of max MDB_MAXKEYSIZE
|
23
|
+
Misc code cleanup
|
24
|
+
Documentation
|
25
|
+
Remove spurious note about non-overlapping flags (ITS#7665)
|
26
|
+
|
3
27
|
LMDB 0.9.10 Release (2013/11/12)
|
4
28
|
Add MDB_NOMEMINIT option
|
5
29
|
Fix mdb_page_split() again (ITS#7589)
|
@@ -16,7 +40,7 @@ LMDB 0.9.9 Release (2013/10/24)
|
|
16
40
|
Fix mdb_page_merge() cursor fixup (ITS#7722)
|
17
41
|
Fix mdb_cursor_del() on last delete (ITS#7718)
|
18
42
|
Fix adding WRITEMAP on existing env (ITS#7715)
|
19
|
-
|
43
|
+
Fix nested txns (ITS#7515)
|
20
44
|
Fix mdb_env_copy() O_DIRECT bug (ITS#7682)
|
21
45
|
Fix mdb_cursor_set(SET_RANGE) return code (ITS#7681)
|
22
46
|
Fix mdb_rebalance() cursor fixup (ITS#7701)
|
data/ext/lmdb_ext/liblmdb/lmdb.h
CHANGED
@@ -119,7 +119,7 @@
|
|
119
119
|
*
|
120
120
|
* @author Howard Chu, Symas Corporation.
|
121
121
|
*
|
122
|
-
* @copyright Copyright 2011-
|
122
|
+
* @copyright Copyright 2011-2014 Howard Chu, Symas Corp. All rights reserved.
|
123
123
|
*
|
124
124
|
* Redistribution and use in source and binary forms, with or without
|
125
125
|
* modification, are permitted only as authorized by the OpenLDAP
|
@@ -184,7 +184,7 @@ typedef int mdb_filehandle_t;
|
|
184
184
|
/** Library minor version */
|
185
185
|
#define MDB_VERSION_MINOR 9
|
186
186
|
/** Library patch version */
|
187
|
-
#define MDB_VERSION_PATCH
|
187
|
+
#define MDB_VERSION_PATCH 12
|
188
188
|
|
189
189
|
/** Combine args a,b,c into a single integer for easy version comparisons */
|
190
190
|
#define MDB_VERINT(a,b,c) (((a) << 24) | ((b) << 16) | (c))
|
@@ -194,7 +194,7 @@ typedef int mdb_filehandle_t;
|
|
194
194
|
MDB_VERINT(MDB_VERSION_MAJOR,MDB_VERSION_MINOR,MDB_VERSION_PATCH)
|
195
195
|
|
196
196
|
/** The release date of this library version */
|
197
|
-
#define MDB_VERSION_DATE "
|
197
|
+
#define MDB_VERSION_DATE "June 13, 2014"
|
198
198
|
|
199
199
|
/** A stringifier for the version info */
|
200
200
|
#define MDB_VERSTR(a,b,c,d) "MDB " #a "." #b "." #c ": (" d ")"
|
@@ -263,8 +263,6 @@ typedef int (MDB_cmp_func)(const MDB_val *a, const MDB_val *b);
|
|
263
263
|
typedef void (MDB_rel_func)(MDB_val *item, void *oldptr, void *newptr, void *relctx);
|
264
264
|
|
265
265
|
/** @defgroup mdb_env Environment Flags
|
266
|
-
*
|
267
|
-
* Values do not overlap Database Flags.
|
268
266
|
* @{
|
269
267
|
*/
|
270
268
|
/** mmap at a fixed address (experimental) */
|
@@ -292,8 +290,6 @@ typedef void (MDB_rel_func)(MDB_val *item, void *oldptr, void *newptr, void *rel
|
|
292
290
|
/** @} */
|
293
291
|
|
294
292
|
/** @defgroup mdb_dbi_open Database Flags
|
295
|
-
*
|
296
|
-
* Values do not overlap Environment Flags.
|
297
293
|
* @{
|
298
294
|
*/
|
299
295
|
/** use reverse string keys */
|
@@ -412,7 +408,7 @@ typedef enum MDB_cursor_op {
|
|
412
408
|
#define MDB_BAD_RSLOT (-30783)
|
413
409
|
/** Transaction cannot recover - it must be aborted */
|
414
410
|
#define MDB_BAD_TXN (-30782)
|
415
|
-
/**
|
411
|
+
/** Unsupported size of key/DB name/data, or wrong DUPFIXED size */
|
416
412
|
#define MDB_BAD_VALSIZE (-30781)
|
417
413
|
#define MDB_LAST_ERRCODE MDB_BAD_VALSIZE
|
418
414
|
/** @} */
|
@@ -672,7 +668,8 @@ void mdb_env_close(MDB_env *env);
|
|
672
668
|
/** @brief Set environment flags.
|
673
669
|
*
|
674
670
|
* This may be used to set some flags in addition to those from
|
675
|
-
* #mdb_env_open(), or to unset these flags.
|
671
|
+
* #mdb_env_open(), or to unset these flags. If several threads
|
672
|
+
* change the flags at the same time, the result is undefined.
|
676
673
|
* @param[in] env An environment handle returned by #mdb_env_create()
|
677
674
|
* @param[in] flags The flags to change, bitwise OR'ed together
|
678
675
|
* @param[in] onoff A non-zero value sets the flags, zero clears them.
|
@@ -787,6 +784,10 @@ int mdb_env_get_maxreaders(MDB_env *env, unsigned int *readers);
|
|
787
784
|
* environment. Simpler applications that use the environment as a single
|
788
785
|
* unnamed database can ignore this option.
|
789
786
|
* This function may only be called after #mdb_env_create() and before #mdb_env_open().
|
787
|
+
*
|
788
|
+
* Currently a moderate number of slots are cheap but a huge number gets
|
789
|
+
* expensive: 7-120 words per transaction, and every #mdb_dbi_open()
|
790
|
+
* does a linear search of the opened slots.
|
790
791
|
* @param[in] env An environment handle returned by #mdb_env_create()
|
791
792
|
* @param[in] dbs The maximum number of databases
|
792
793
|
* @return A non-zero error value on failure and 0 on success. Some possible
|
@@ -797,15 +798,47 @@ int mdb_env_get_maxreaders(MDB_env *env, unsigned int *readers);
|
|
797
798
|
*/
|
798
799
|
int mdb_env_set_maxdbs(MDB_env *env, MDB_dbi dbs);
|
799
800
|
|
800
|
-
/** @brief Get the maximum size of
|
801
|
+
/** @brief Get the maximum size of keys and #MDB_DUPSORT data we can write.
|
801
802
|
*
|
802
|
-
*
|
803
|
+
* Depends on the compile-time constant #MDB_MAXKEYSIZE. Default 511.
|
803
804
|
* See @ref MDB_val.
|
804
805
|
* @param[in] env An environment handle returned by #mdb_env_create()
|
805
|
-
* @return The maximum size of a key
|
806
|
+
* @return The maximum size of a key we can write
|
806
807
|
*/
|
807
808
|
int mdb_env_get_maxkeysize(MDB_env *env);
|
808
809
|
|
810
|
+
/** @brief Set application information associated with the #MDB_env.
|
811
|
+
*
|
812
|
+
* @param[in] env An environment handle returned by #mdb_env_create()
|
813
|
+
* @param[in] ctx An arbitrary pointer for whatever the application needs.
|
814
|
+
* @return A non-zero error value on failure and 0 on success.
|
815
|
+
*/
|
816
|
+
int mdb_env_set_userctx(MDB_env *env, void *ctx);
|
817
|
+
|
818
|
+
/** @brief Get the application information associated with the #MDB_env.
|
819
|
+
*
|
820
|
+
* @param[in] env An environment handle returned by #mdb_env_create()
|
821
|
+
* @return The pointer set by #mdb_env_set_userctx().
|
822
|
+
*/
|
823
|
+
void *mdb_env_get_userctx(MDB_env *env);
|
824
|
+
|
825
|
+
/** @brief A callback function for most MDB assert() failures,
|
826
|
+
* called before printing the message and aborting.
|
827
|
+
*
|
828
|
+
* @param[in] env An environment handle returned by #mdb_env_create().
|
829
|
+
* @param[in] msg The assertion message, not including newline.
|
830
|
+
*/
|
831
|
+
typedef void MDB_assert_func(MDB_env *env, const char *msg);
|
832
|
+
|
833
|
+
/** Set or reset the assert() callback of the environment.
|
834
|
+
* Disabled if liblmdb is buillt with NDEBUG.
|
835
|
+
* @note This hack should become obsolete as lmdb's error handling matures.
|
836
|
+
* @param[in] env An environment handle returned by #mdb_env_create().
|
837
|
+
* @param[in] func An #MDB_assert_func function, or 0.
|
838
|
+
* @return A non-zero error value on failure and 0 on success.
|
839
|
+
*/
|
840
|
+
int mdb_env_set_assert(MDB_env *env, MDB_assert_func *func);
|
841
|
+
|
809
842
|
/** @brief Create a transaction for use with the environment.
|
810
843
|
*
|
811
844
|
* The transaction handle may be discarded using #mdb_txn_abort() or #mdb_txn_commit().
|
@@ -922,7 +955,7 @@ int mdb_txn_renew(MDB_txn *txn);
|
|
922
955
|
* independently of whether such a database exists.
|
923
956
|
* The database handle may be discarded by calling #mdb_dbi_close().
|
924
957
|
* The old database handle is returned if the database was already open.
|
925
|
-
* The handle
|
958
|
+
* The handle may only be closed once.
|
926
959
|
* The database handle will be private to the current transaction until
|
927
960
|
* the transaction is successfully committed. If the transaction is
|
928
961
|
* aborted the handle will be closed automatically.
|
@@ -934,7 +967,8 @@ int mdb_txn_renew(MDB_txn *txn);
|
|
934
967
|
* use this function.
|
935
968
|
*
|
936
969
|
* To use named databases (with name != NULL), #mdb_env_set_maxdbs()
|
937
|
-
* must be called before opening the environment.
|
970
|
+
* must be called before opening the environment. Database names
|
971
|
+
* are kept as keys in the unnamed database.
|
938
972
|
* @param[in] txn A transaction handle returned by #mdb_txn_begin()
|
939
973
|
* @param[in] name The name of the database to open. If only a single
|
940
974
|
* database is needed in the environment, this value may be NULL.
|
@@ -1004,12 +1038,19 @@ int mdb_stat(MDB_txn *txn, MDB_dbi dbi, MDB_stat *stat);
|
|
1004
1038
|
*/
|
1005
1039
|
int mdb_dbi_flags(MDB_txn *txn, MDB_dbi dbi, unsigned int *flags);
|
1006
1040
|
|
1007
|
-
/** @brief Close a database handle.
|
1041
|
+
/** @brief Close a database handle. Normally unnecessary. Use with care:
|
1008
1042
|
*
|
1009
1043
|
* This call is not mutex protected. Handles should only be closed by
|
1010
1044
|
* a single thread, and only if no other threads are going to reference
|
1011
1045
|
* the database handle or one of its cursors any further. Do not close
|
1012
1046
|
* a handle if an existing transaction has modified its database.
|
1047
|
+
* Doing so can cause misbehavior from database corruption to errors
|
1048
|
+
* like MDB_BAD_VALSIZE (since the DB name is gone).
|
1049
|
+
*
|
1050
|
+
* Closing a database handle is not necessary, but lets #mdb_dbi_open()
|
1051
|
+
* reuse the handle value. Usually it's better to set a bigger
|
1052
|
+
* #mdb_env_set_maxdbs(), unless that value would be large.
|
1053
|
+
*
|
1013
1054
|
* @param[in] env An environment handle returned by #mdb_env_create()
|
1014
1055
|
* @param[in] dbi A database handle returned by #mdb_dbi_open()
|
1015
1056
|
*/
|
@@ -1017,6 +1058,7 @@ void mdb_dbi_close(MDB_env *env, MDB_dbi dbi);
|
|
1017
1058
|
|
1018
1059
|
/** @brief Empty or delete+close a database.
|
1019
1060
|
*
|
1061
|
+
* See #mdb_dbi_close() for restrictions about closing the DB handle.
|
1020
1062
|
* @param[in] txn A transaction handle returned by #mdb_txn_begin()
|
1021
1063
|
* @param[in] dbi A database handle returned by #mdb_dbi_open()
|
1022
1064
|
* @param[in] del 0 to empty the DB, 1 to delete it from the
|
@@ -1294,9 +1336,9 @@ int mdb_cursor_get(MDB_cursor *cursor, MDB_val *key, MDB_val *data,
|
|
1294
1336
|
/** @brief Store by cursor.
|
1295
1337
|
*
|
1296
1338
|
* This function stores key/data pairs into the database.
|
1297
|
-
*
|
1298
|
-
*
|
1299
|
-
*
|
1339
|
+
* The cursor is positioned at the new item, or on failure usually near it.
|
1340
|
+
* @note Earlier documentation incorrectly said errors would leave the
|
1341
|
+
* state of the cursor unchanged.
|
1300
1342
|
* @param[in] cursor A cursor handle returned by #mdb_cursor_open()
|
1301
1343
|
* @param[in] key The key operated on.
|
1302
1344
|
* @param[in] data The data operated on.
|
@@ -1305,7 +1347,9 @@ int mdb_cursor_get(MDB_cursor *cursor, MDB_val *key, MDB_val *data,
|
|
1305
1347
|
* <ul>
|
1306
1348
|
* <li>#MDB_CURRENT - overwrite the data of the key/data pair to which
|
1307
1349
|
* the cursor refers with the specified data item. The \b key
|
1308
|
-
* parameter is
|
1350
|
+
* parameter is not used for positioning the cursor, but should
|
1351
|
+
* still be provided. If using sorted duplicates (#MDB_DUPSORT)
|
1352
|
+
* the data item must still sort into the same place.
|
1309
1353
|
* <li>#MDB_NODUPDATA - enter the new key/data pair only if it does not
|
1310
1354
|
* already appear in the database. This flag may only be specified
|
1311
1355
|
* if the database was opened with #MDB_DUPSORT. The function will
|
@@ -1409,7 +1453,7 @@ int mdb_dcmp(MDB_txn *txn, MDB_dbi dbi, const MDB_val *a, const MDB_val *b);
|
|
1409
1453
|
*
|
1410
1454
|
* @param[in] msg The string to be printed.
|
1411
1455
|
* @param[in] ctx An arbitrary context pointer for the callback.
|
1412
|
-
* @return < 0 on failure, 0 on success.
|
1456
|
+
* @return < 0 on failure, >= 0 on success.
|
1413
1457
|
*/
|
1414
1458
|
typedef int (MDB_msg_func)(const char *msg, void *ctx);
|
1415
1459
|
|
@@ -1418,7 +1462,7 @@ typedef int (MDB_msg_func)(const char *msg, void *ctx);
|
|
1418
1462
|
* @param[in] env An environment handle returned by #mdb_env_create()
|
1419
1463
|
* @param[in] func A #MDB_msg_func function
|
1420
1464
|
* @param[in] ctx Anything the message function needs
|
1421
|
-
* @return < 0 on failure, 0 on success.
|
1465
|
+
* @return < 0 on failure, >= 0 on success.
|
1422
1466
|
*/
|
1423
1467
|
int mdb_reader_list(MDB_env *env, MDB_msg_func *func, void *ctx);
|
1424
1468
|
|
data/ext/lmdb_ext/liblmdb/mdb.c
CHANGED
@@ -65,7 +65,6 @@
|
|
65
65
|
#include <fcntl.h>
|
66
66
|
#endif
|
67
67
|
|
68
|
-
#include <assert.h>
|
69
68
|
#include <errno.h>
|
70
69
|
#include <limits.h>
|
71
70
|
#include <stddef.h>
|
@@ -149,13 +148,24 @@
|
|
149
148
|
/** @defgroup internal MDB Internals
|
150
149
|
* @{
|
151
150
|
*/
|
152
|
-
/** @defgroup compat
|
151
|
+
/** @defgroup compat Compatibility Macros
|
153
152
|
* A bunch of macros to minimize the amount of platform-specific ifdefs
|
154
153
|
* needed throughout the rest of the code. When the features this library
|
155
154
|
* needs are similar enough to POSIX to be hidden in a one-or-two line
|
156
155
|
* replacement, this macro approach is used.
|
157
156
|
* @{
|
158
157
|
*/
|
158
|
+
|
159
|
+
/** Wrapper around __func__, which is a C99 feature */
|
160
|
+
#if __STDC_VERSION__ >= 199901L
|
161
|
+
# define mdb_func_ __func__
|
162
|
+
#elif __GNUC__ >= 2 || _MSC_VER >= 1300
|
163
|
+
# define mdb_func_ __FUNCTION__
|
164
|
+
#else
|
165
|
+
/* If a debug message says <mdb_unknown>(), update the #if statements above */
|
166
|
+
# define mdb_func_ "<mdb_unknown>"
|
167
|
+
#endif
|
168
|
+
|
159
169
|
#ifdef _WIN32
|
160
170
|
#define MDB_USE_HASH 1
|
161
171
|
#define MDB_PIDLOCK 0
|
@@ -327,7 +337,7 @@ static txnid_t mdb_debug_start;
|
|
327
337
|
*/
|
328
338
|
# define DPRINTF(args) ((void) ((mdb_debug) && DPRINTF0 args))
|
329
339
|
# define DPRINTF0(fmt, ...) \
|
330
|
-
fprintf(stderr, "%s:%d " fmt "\n",
|
340
|
+
fprintf(stderr, "%s:%d " fmt "\n", mdb_func_, __LINE__, __VA_ARGS__)
|
331
341
|
#else
|
332
342
|
# define DPRINTF(args) ((void) 0)
|
333
343
|
#endif
|
@@ -342,7 +352,7 @@ static txnid_t mdb_debug_start;
|
|
342
352
|
|
343
353
|
/** @brief The maximum size of a database page.
|
344
354
|
*
|
345
|
-
* This is 32k, since it must fit in #MDB_page
|
355
|
+
* This is 32k, since it must fit in #MDB_page.%mp_upper.
|
346
356
|
*
|
347
357
|
* LMDB will use database pages < OS pages if needed.
|
348
358
|
* That causes more I/O in write transactions: The OS must
|
@@ -382,20 +392,25 @@ static txnid_t mdb_debug_start;
|
|
382
392
|
/** The version number for a database's lockfile format. */
|
383
393
|
#define MDB_LOCK_VERSION 1
|
384
394
|
|
385
|
-
/** @brief The
|
386
|
-
*
|
387
|
-
* The library rejects bigger keys, and cannot deal with records
|
388
|
-
* with bigger keys stored by a library with bigger max keysize.
|
395
|
+
/** @brief The max size of a key we can write, or 0 for dynamic max.
|
389
396
|
*
|
390
|
-
*
|
391
|
-
*
|
392
|
-
*
|
397
|
+
* Define this as 0 to compute the max from the page size. 511
|
398
|
+
* is default for backwards compat: liblmdb <= 0.9.10 can break
|
399
|
+
* when modifying a DB with keys/dupsort data bigger than its max.
|
393
400
|
*
|
394
|
-
*
|
395
|
-
*
|
401
|
+
* Data items in an #MDB_DUPSORT database are also limited to
|
402
|
+
* this size, since they're actually keys of a sub-DB. Keys and
|
403
|
+
* #MDB_DUPSORT data items must fit on a node in a regular page.
|
396
404
|
*/
|
397
405
|
#ifndef MDB_MAXKEYSIZE
|
398
406
|
#define MDB_MAXKEYSIZE 511
|
407
|
+
#endif
|
408
|
+
|
409
|
+
/** The maximum size of a key we can write to the environment. */
|
410
|
+
#if MDB_MAXKEYSIZE
|
411
|
+
#define ENV_MAXKEY(env) (MDB_MAXKEYSIZE)
|
412
|
+
#else
|
413
|
+
#define ENV_MAXKEY(env) ((env)->me_maxkey)
|
399
414
|
#endif
|
400
415
|
|
401
416
|
/** @brief The maximum size of a data item.
|
@@ -405,11 +420,15 @@ static txnid_t mdb_debug_start;
|
|
405
420
|
#define MAXDATASIZE 0xffffffffUL
|
406
421
|
|
407
422
|
#if MDB_DEBUG
|
423
|
+
/** Key size which fits in a #DKBUF.
|
424
|
+
* @ingroup debug
|
425
|
+
*/
|
426
|
+
#define DKBUF_MAXKEYSIZE ((MDB_MAXKEYSIZE) > 0 ? (MDB_MAXKEYSIZE) : 511)
|
408
427
|
/** A key buffer.
|
409
428
|
* @ingroup debug
|
410
429
|
* This is used for printing a hex dump of a key's contents.
|
411
430
|
*/
|
412
|
-
#define DKBUF char kbuf[
|
431
|
+
#define DKBUF char kbuf[DKBUF_MAXKEYSIZE*2+1]
|
413
432
|
/** Display a key in hex.
|
414
433
|
* @ingroup debug
|
415
434
|
* Invoke a function to display a key in hex.
|
@@ -428,6 +447,9 @@ static txnid_t mdb_debug_start;
|
|
428
447
|
/** Test if the flags \b f are set in a flag word \b w. */
|
429
448
|
#define F_ISSET(w, f) (((w) & (f)) == (f))
|
430
449
|
|
450
|
+
/** Round \b n up to an even number. */
|
451
|
+
#define EVEN(n) (((n) + 1U) & -2) /* sign-extending -2 to match n+1U */
|
452
|
+
|
431
453
|
/** Used for offsets within a single page.
|
432
454
|
* Since memory pages are typically 4 or 8KB in size, 12-13 bits,
|
433
455
|
* this is plenty.
|
@@ -679,7 +701,8 @@ typedef struct MDB_page {
|
|
679
701
|
#define OVPAGES(size, psize) ((PAGEHDRSZ-1 + (size)) / (psize) + 1)
|
680
702
|
|
681
703
|
/** Header for a single key/data pair within a page.
|
682
|
-
*
|
704
|
+
* Used in pages of type #P_BRANCH and #P_LEAF without #P_LEAF2.
|
705
|
+
* We guarantee 2-byte alignment for 'MDB_node's.
|
683
706
|
*/
|
684
707
|
typedef struct MDB_node {
|
685
708
|
/** lo and hi are used for data size on leaf nodes and for
|
@@ -688,9 +711,11 @@ typedef struct MDB_node {
|
|
688
711
|
* They are in host byte order in case that lets some
|
689
712
|
* accesses be optimized into a 32-bit word access.
|
690
713
|
*/
|
691
|
-
#
|
692
|
-
|
693
|
-
|
714
|
+
#if BYTE_ORDER == LITTLE_ENDIAN
|
715
|
+
unsigned short mn_lo, mn_hi; /**< part of data size or pgno */
|
716
|
+
#else
|
717
|
+
unsigned short mn_hi, mn_lo;
|
718
|
+
#endif
|
694
719
|
/** @defgroup mdb_node Node Flags
|
695
720
|
* @ingroup internal
|
696
721
|
* Flags for node headers.
|
@@ -911,12 +936,12 @@ struct MDB_txn {
|
|
911
936
|
* @{
|
912
937
|
*/
|
913
938
|
#define MDB_TXN_RDONLY 0x01 /**< read-only transaction */
|
914
|
-
#define MDB_TXN_ERROR 0x02 /**< an error
|
939
|
+
#define MDB_TXN_ERROR 0x02 /**< txn is unusable after an error */
|
915
940
|
#define MDB_TXN_DIRTY 0x04 /**< must write, even if dirty list is empty */
|
916
941
|
#define MDB_TXN_SPILLS 0x08 /**< txn or a parent has spilled pages */
|
917
942
|
/** @} */
|
918
943
|
unsigned int mt_flags; /**< @ref mdb_txn */
|
919
|
-
/** dirty_list room: Array size -
|
944
|
+
/** #dirty_list room: Array size - \#dirty pages visible to this txn.
|
920
945
|
* Includes ancestor txns' dirty pages not hidden by other txns'
|
921
946
|
* dirty/spilled pages. Thus commit(nested txn) has room to merge
|
922
947
|
* dirty_list into mt_parent after freeing hidden mt_parent pages.
|
@@ -1009,8 +1034,6 @@ struct MDB_env {
|
|
1009
1034
|
#define MDB_ENV_ACTIVE 0x20000000U
|
1010
1035
|
/** me_txkey is set */
|
1011
1036
|
#define MDB_ENV_TXKEY 0x10000000U
|
1012
|
-
/** Have liveness lock in reader table */
|
1013
|
-
#define MDB_LIVE_READER 0x08000000U
|
1014
1037
|
uint32_t me_flags; /**< @ref mdb_env */
|
1015
1038
|
unsigned int me_psize; /**< DB page size, inited from me_os_psize */
|
1016
1039
|
unsigned int me_os_psize; /**< OS page size, from #GET_PAGESIZE */
|
@@ -1043,6 +1066,10 @@ struct MDB_env {
|
|
1043
1066
|
int me_maxfree_1pg;
|
1044
1067
|
/** Max size of a node on a page */
|
1045
1068
|
unsigned int me_nodemax;
|
1069
|
+
#if !(MDB_MAXKEYSIZE)
|
1070
|
+
unsigned int me_maxkey; /**< max size of a key */
|
1071
|
+
#endif
|
1072
|
+
int me_live_reader; /**< have liveness lock in reader table */
|
1046
1073
|
#ifdef _WIN32
|
1047
1074
|
int me_pidquery; /**< Used in OpenProcess */
|
1048
1075
|
HANDLE me_rmutex; /* Windows mutexes don't reside in shared mem */
|
@@ -1051,6 +1078,8 @@ struct MDB_env {
|
|
1051
1078
|
sem_t *me_rmutex; /* Shared mutexes are not supported */
|
1052
1079
|
sem_t *me_wmutex;
|
1053
1080
|
#endif
|
1081
|
+
void *me_userctx; /**< User-settable context */
|
1082
|
+
MDB_assert_func *me_assert_func; /**< Callback for assertion failures */
|
1054
1083
|
};
|
1055
1084
|
|
1056
1085
|
/** Nested transaction */
|
@@ -1066,9 +1095,13 @@ typedef struct MDB_ntxn {
|
|
1066
1095
|
#define MDB_COMMIT_PAGES IOV_MAX
|
1067
1096
|
#endif
|
1068
1097
|
|
1069
|
-
|
1098
|
+
/** max bytes to write in one call */
|
1070
1099
|
#define MAX_WRITE (0x80000000U >> (sizeof(ssize_t) == 4))
|
1071
1100
|
|
1101
|
+
/** Check \b txn and \b dbi arguments to a function */
|
1102
|
+
#define TXN_DBI_EXIST(txn, dbi) \
|
1103
|
+
((txn) && (dbi) < (txn)->mt_numdbs && ((txn)->mt_dbflags[dbi] & DB_VALID))
|
1104
|
+
|
1072
1105
|
static int mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp);
|
1073
1106
|
static int mdb_page_new(MDB_cursor *mc, uint32_t flags, int num, MDB_page **mp);
|
1074
1107
|
static int mdb_page_touch(MDB_cursor *mc);
|
@@ -1099,7 +1132,7 @@ static void mdb_env_close0(MDB_env *env, int excl);
|
|
1099
1132
|
static MDB_node *mdb_node_search(MDB_cursor *mc, MDB_val *key, int *exactp);
|
1100
1133
|
static int mdb_node_add(MDB_cursor *mc, indx_t indx,
|
1101
1134
|
MDB_val *key, MDB_val *data, pgno_t pgno, unsigned int flags);
|
1102
|
-
static void mdb_node_del(
|
1135
|
+
static void mdb_node_del(MDB_cursor *mc, int ksize);
|
1103
1136
|
static void mdb_node_shrink(MDB_page *mp, indx_t indx);
|
1104
1137
|
static int mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst);
|
1105
1138
|
static int mdb_node_read(MDB_txn *txn, MDB_node *leaf, MDB_val *data);
|
@@ -1112,7 +1145,8 @@ static int mdb_update_key(MDB_cursor *mc, MDB_val *key);
|
|
1112
1145
|
static void mdb_cursor_pop(MDB_cursor *mc);
|
1113
1146
|
static int mdb_cursor_push(MDB_cursor *mc, MDB_page *mp);
|
1114
1147
|
|
1115
|
-
static int mdb_cursor_del0(MDB_cursor *mc
|
1148
|
+
static int mdb_cursor_del0(MDB_cursor *mc);
|
1149
|
+
static int mdb_del0(MDB_txn *txn, MDB_dbi dbi, MDB_val *key, MDB_val *data, unsigned flags);
|
1116
1150
|
static int mdb_cursor_sibling(MDB_cursor *mc, int move_right);
|
1117
1151
|
static int mdb_cursor_next(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op);
|
1118
1152
|
static int mdb_cursor_prev(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op);
|
@@ -1168,7 +1202,7 @@ static char *const mdb_errstr[] = {
|
|
1168
1202
|
"MDB_INCOMPATIBLE: Operation and DB incompatible, or DB flags changed",
|
1169
1203
|
"MDB_BAD_RSLOT: Invalid reuse of reader locktable slot",
|
1170
1204
|
"MDB_BAD_TXN: Transaction cannot recover - it must be aborted",
|
1171
|
-
"MDB_BAD_VALSIZE:
|
1205
|
+
"MDB_BAD_VALSIZE: Unsupported size of key/DB name/data, or wrong DUPFIXED size",
|
1172
1206
|
};
|
1173
1207
|
|
1174
1208
|
char *
|
@@ -1186,7 +1220,43 @@ mdb_strerror(int err)
|
|
1186
1220
|
return strerror(err);
|
1187
1221
|
}
|
1188
1222
|
|
1223
|
+
/** assert(3) variant in cursor context */
|
1224
|
+
#define mdb_cassert(mc, expr) mdb_assert0((mc)->mc_txn->mt_env, expr, #expr)
|
1225
|
+
/** assert(3) variant in transaction context */
|
1226
|
+
#define mdb_tassert(mc, expr) mdb_assert0((txn)->mt_env, expr, #expr)
|
1227
|
+
/** assert(3) variant in environment context */
|
1228
|
+
#define mdb_eassert(env, expr) mdb_assert0(env, expr, #expr)
|
1229
|
+
|
1230
|
+
#ifndef NDEBUG
|
1231
|
+
# define mdb_assert0(env, expr, expr_txt) ((expr) ? (void)0 : \
|
1232
|
+
mdb_assert_fail(env, expr_txt, mdb_func_, __FILE__, __LINE__))
|
1233
|
+
|
1234
|
+
static void
|
1235
|
+
mdb_assert_fail(MDB_env *env, const char *expr_txt,
|
1236
|
+
const char *func, const char *file, int line)
|
1237
|
+
{
|
1238
|
+
char buf[400];
|
1239
|
+
sprintf(buf, "%.100s:%d: Assertion '%.200s' failed in %.40s()",
|
1240
|
+
file, line, expr_txt, func);
|
1241
|
+
if (env->me_assert_func)
|
1242
|
+
env->me_assert_func(env, buf);
|
1243
|
+
fprintf(stderr, "%s\n", buf);
|
1244
|
+
abort();
|
1245
|
+
}
|
1246
|
+
#else
|
1247
|
+
# define mdb_assert0(env, expr, expr_txt) ((void) 0)
|
1248
|
+
#endif /* NDEBUG */
|
1249
|
+
|
1189
1250
|
#if MDB_DEBUG
|
1251
|
+
/** Return the page number of \b mp which may be sub-page, for debug output */
|
1252
|
+
static pgno_t
|
1253
|
+
mdb_dbg_pgno(MDB_page *mp)
|
1254
|
+
{
|
1255
|
+
pgno_t ret;
|
1256
|
+
COPY_PGNO(ret, mp->mp_pgno);
|
1257
|
+
return ret;
|
1258
|
+
}
|
1259
|
+
|
1190
1260
|
/** Display a key in hexadecimal and return the address of the result.
|
1191
1261
|
* @param[in] key the key to display
|
1192
1262
|
* @param[in] buf the buffer to write into. Should always be #DKBUF.
|
@@ -1202,7 +1272,7 @@ mdb_dkey(MDB_val *key, char *buf)
|
|
1202
1272
|
if (!key)
|
1203
1273
|
return "";
|
1204
1274
|
|
1205
|
-
if (key->mv_size >
|
1275
|
+
if (key->mv_size > DKBUF_MAXKEYSIZE)
|
1206
1276
|
return "MDB_MAXKEYSIZE";
|
1207
1277
|
/* may want to make this a dynamic check: if the key is mostly
|
1208
1278
|
* printable characters, print it as-is instead of converting to hex.
|
@@ -1217,33 +1287,77 @@ mdb_dkey(MDB_val *key, char *buf)
|
|
1217
1287
|
return buf;
|
1218
1288
|
}
|
1219
1289
|
|
1290
|
+
static const char *
|
1291
|
+
mdb_leafnode_type(MDB_node *n)
|
1292
|
+
{
|
1293
|
+
static char *const tp[2][2] = {{"", ": DB"}, {": sub-page", ": sub-DB"}};
|
1294
|
+
return F_ISSET(n->mn_flags, F_BIGDATA) ? ": overflow page" :
|
1295
|
+
tp[F_ISSET(n->mn_flags, F_DUPDATA)][F_ISSET(n->mn_flags, F_SUBDATA)];
|
1296
|
+
}
|
1297
|
+
|
1220
1298
|
/** Display all the keys in the page. */
|
1221
1299
|
void
|
1222
1300
|
mdb_page_list(MDB_page *mp)
|
1223
1301
|
{
|
1302
|
+
pgno_t pgno = mdb_dbg_pgno(mp);
|
1303
|
+
const char *type, *state = (mp->mp_flags & P_DIRTY) ? ", dirty" : "";
|
1224
1304
|
MDB_node *node;
|
1225
|
-
unsigned int i, nkeys, nsize;
|
1305
|
+
unsigned int i, nkeys, nsize, total = 0;
|
1226
1306
|
MDB_val key;
|
1227
1307
|
DKBUF;
|
1228
1308
|
|
1309
|
+
switch (mp->mp_flags & (P_BRANCH|P_LEAF|P_LEAF2|P_META|P_OVERFLOW|P_SUBP)) {
|
1310
|
+
case P_BRANCH: type = "Branch page"; break;
|
1311
|
+
case P_LEAF: type = "Leaf page"; break;
|
1312
|
+
case P_LEAF|P_SUBP: type = "Sub-page"; break;
|
1313
|
+
case P_LEAF|P_LEAF2: type = "LEAF2 page"; break;
|
1314
|
+
case P_LEAF|P_LEAF2|P_SUBP: type = "LEAF2 sub-page"; break;
|
1315
|
+
case P_OVERFLOW:
|
1316
|
+
fprintf(stderr, "Overflow page %"Z"u pages %u%s\n",
|
1317
|
+
pgno, mp->mp_pages, state);
|
1318
|
+
return;
|
1319
|
+
case P_META:
|
1320
|
+
fprintf(stderr, "Meta-page %"Z"u txnid %"Z"u\n",
|
1321
|
+
pgno, ((MDB_meta *)METADATA(mp))->mm_txnid);
|
1322
|
+
return;
|
1323
|
+
default:
|
1324
|
+
fprintf(stderr, "Bad page %"Z"u flags 0x%u\n", pgno, mp->mp_flags);
|
1325
|
+
return;
|
1326
|
+
}
|
1327
|
+
|
1229
1328
|
nkeys = NUMKEYS(mp);
|
1230
|
-
fprintf(stderr, "
|
1329
|
+
fprintf(stderr, "%s %"Z"u numkeys %d%s\n", type, pgno, nkeys, state);
|
1330
|
+
|
1231
1331
|
for (i=0; i<nkeys; i++) {
|
1332
|
+
if (IS_LEAF2(mp)) { /* LEAF2 pages have no mp_ptrs[] or node headers */
|
1333
|
+
key.mv_size = nsize = mp->mp_pad;
|
1334
|
+
key.mv_data = LEAF2KEY(mp, i, nsize);
|
1335
|
+
total += nsize;
|
1336
|
+
fprintf(stderr, "key %d: nsize %d, %s\n", i, nsize, DKEY(&key));
|
1337
|
+
continue;
|
1338
|
+
}
|
1232
1339
|
node = NODEPTR(mp, i);
|
1233
1340
|
key.mv_size = node->mn_ksize;
|
1234
1341
|
key.mv_data = node->mn_data;
|
1235
|
-
nsize = NODESIZE +
|
1342
|
+
nsize = NODESIZE + key.mv_size;
|
1236
1343
|
if (IS_BRANCH(mp)) {
|
1237
1344
|
fprintf(stderr, "key %d: page %"Z"u, %s\n", i, NODEPGNO(node),
|
1238
1345
|
DKEY(&key));
|
1346
|
+
total += nsize;
|
1239
1347
|
} else {
|
1240
1348
|
if (F_ISSET(node->mn_flags, F_BIGDATA))
|
1241
1349
|
nsize += sizeof(pgno_t);
|
1242
1350
|
else
|
1243
1351
|
nsize += NODEDSZ(node);
|
1244
|
-
|
1352
|
+
total += nsize;
|
1353
|
+
nsize += sizeof(indx_t);
|
1354
|
+
fprintf(stderr, "key %d: nsize %d, %s%s\n",
|
1355
|
+
i, nsize, DKEY(&key), mdb_leafnode_type(node));
|
1245
1356
|
}
|
1357
|
+
total = EVEN(total);
|
1246
1358
|
}
|
1359
|
+
fprintf(stderr, "Total: header %d + contents %d + unused %d\n",
|
1360
|
+
IS_LEAF2(mp) ? PAGEHDRSZ : mp->mp_lower, total, SIZELEFT(mp));
|
1247
1361
|
}
|
1248
1362
|
|
1249
1363
|
void
|
@@ -1269,6 +1383,7 @@ mdb_cursor_chk(MDB_cursor *mc)
|
|
1269
1383
|
/** Count all the pages in each DB and in the freelist
|
1270
1384
|
* and make sure it matches the actual number of pages
|
1271
1385
|
* being used.
|
1386
|
+
* All named DBs must be open for a correct count.
|
1272
1387
|
*/
|
1273
1388
|
static void mdb_audit(MDB_txn *txn)
|
1274
1389
|
{
|
@@ -1282,10 +1397,13 @@ static void mdb_audit(MDB_txn *txn)
|
|
1282
1397
|
mdb_cursor_init(&mc, txn, FREE_DBI, NULL);
|
1283
1398
|
while ((rc = mdb_cursor_get(&mc, &key, &data, MDB_NEXT)) == 0)
|
1284
1399
|
freecount += *(MDB_ID *)data.mv_data;
|
1400
|
+
mdb_tassert(txn, rc == MDB_NOTFOUND);
|
1285
1401
|
|
1286
1402
|
count = 0;
|
1287
1403
|
for (i = 0; i<txn->mt_numdbs; i++) {
|
1288
1404
|
MDB_xcursor mx;
|
1405
|
+
if (!(txn->mt_dbflags[i] & DB_VALID))
|
1406
|
+
continue;
|
1289
1407
|
mdb_cursor_init(&mc, txn, i, &mx);
|
1290
1408
|
if (txn->mt_dbs[i].md_root == P_INVALID)
|
1291
1409
|
continue;
|
@@ -1293,8 +1411,8 @@ static void mdb_audit(MDB_txn *txn)
|
|
1293
1411
|
txn->mt_dbs[i].md_leaf_pages +
|
1294
1412
|
txn->mt_dbs[i].md_overflow_pages;
|
1295
1413
|
if (txn->mt_dbs[i].md_flags & MDB_DUPSORT) {
|
1296
|
-
mdb_page_search(&mc, NULL, MDB_PS_FIRST);
|
1297
|
-
|
1414
|
+
rc = mdb_page_search(&mc, NULL, MDB_PS_FIRST);
|
1415
|
+
for (; rc == MDB_SUCCESS; rc = mdb_cursor_sibling(&mc, 1)) {
|
1298
1416
|
unsigned j;
|
1299
1417
|
MDB_page *mp;
|
1300
1418
|
mp = mc.mc_pg[mc.mc_top];
|
@@ -1308,7 +1426,7 @@ static void mdb_audit(MDB_txn *txn)
|
|
1308
1426
|
}
|
1309
1427
|
}
|
1310
1428
|
}
|
1311
|
-
|
1429
|
+
mdb_tassert(txn, rc == MDB_NOTFOUND);
|
1312
1430
|
}
|
1313
1431
|
}
|
1314
1432
|
if (freecount + count + 2 /* metapages */ != txn->mt_next_pgno) {
|
@@ -1357,11 +1475,13 @@ mdb_page_malloc(MDB_txn *txn, unsigned num)
|
|
1357
1475
|
off = sz - psize;
|
1358
1476
|
}
|
1359
1477
|
if ((ret = malloc(sz)) != NULL) {
|
1478
|
+
VGMEMP_ALLOC(env, ret, sz);
|
1360
1479
|
if (!(env->me_flags & MDB_NOMEMINIT)) {
|
1361
1480
|
memset((char *)ret + off, 0, psize);
|
1362
1481
|
ret->mp_pad = 0;
|
1363
1482
|
}
|
1364
|
-
|
1483
|
+
} else {
|
1484
|
+
txn->mt_flags |= MDB_TXN_ERROR;
|
1365
1485
|
}
|
1366
1486
|
return ret;
|
1367
1487
|
}
|
@@ -1627,7 +1747,7 @@ static void
|
|
1627
1747
|
mdb_page_dirty(MDB_txn *txn, MDB_page *mp)
|
1628
1748
|
{
|
1629
1749
|
MDB_ID2 mid;
|
1630
|
-
int (*insert)(MDB_ID2L, MDB_ID2 *);
|
1750
|
+
int rc, (*insert)(MDB_ID2L, MDB_ID2 *);
|
1631
1751
|
|
1632
1752
|
if (txn->mt_env->me_flags & MDB_WRITEMAP) {
|
1633
1753
|
insert = mdb_mid2l_append;
|
@@ -1636,7 +1756,8 @@ mdb_page_dirty(MDB_txn *txn, MDB_page *mp)
|
|
1636
1756
|
}
|
1637
1757
|
mid.mid = mp->mp_pgno;
|
1638
1758
|
mid.mptr = mp;
|
1639
|
-
insert(txn->mt_u.dirty_list, &mid);
|
1759
|
+
rc = insert(txn->mt_u.dirty_list, &mid);
|
1760
|
+
mdb_tassert(txn, rc == 0);
|
1640
1761
|
txn->mt_dirty_room--;
|
1641
1762
|
}
|
1642
1763
|
|
@@ -1669,11 +1790,11 @@ mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp)
|
|
1669
1790
|
#else
|
1670
1791
|
enum { Paranoid = 0, Max_retries = INT_MAX /*infinite*/ };
|
1671
1792
|
#endif
|
1672
|
-
int rc,
|
1793
|
+
int rc, retry = Max_retries;
|
1673
1794
|
MDB_txn *txn = mc->mc_txn;
|
1674
1795
|
MDB_env *env = txn->mt_env;
|
1675
1796
|
pgno_t pgno, *mop = env->me_pghead;
|
1676
|
-
unsigned i, j, k, mop_len = mop ? mop[0] : 0;
|
1797
|
+
unsigned i, j, k, mop_len = mop ? mop[0] : 0, n2 = num-1;
|
1677
1798
|
MDB_page *np;
|
1678
1799
|
txnid_t oldest = 0, last;
|
1679
1800
|
MDB_cursor_op op;
|
@@ -1682,8 +1803,10 @@ mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp)
|
|
1682
1803
|
*mp = NULL;
|
1683
1804
|
|
1684
1805
|
/* If our dirty list is already full, we can't do anything */
|
1685
|
-
if (txn->mt_dirty_room == 0)
|
1686
|
-
|
1806
|
+
if (txn->mt_dirty_room == 0) {
|
1807
|
+
rc = MDB_TXN_FULL;
|
1808
|
+
goto fail;
|
1809
|
+
}
|
1687
1810
|
|
1688
1811
|
for (op = MDB_FIRST;; op = MDB_NEXT) {
|
1689
1812
|
MDB_val key, data;
|
@@ -1693,13 +1816,13 @@ mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp)
|
|
1693
1816
|
/* Seek a big enough contiguous page range. Prefer
|
1694
1817
|
* pages at the tail, just truncating the list.
|
1695
1818
|
*/
|
1696
|
-
if (mop_len
|
1819
|
+
if (mop_len > n2) {
|
1697
1820
|
i = mop_len;
|
1698
1821
|
do {
|
1699
1822
|
pgno = mop[i];
|
1700
1823
|
if (mop[i-n2] == pgno+n2)
|
1701
1824
|
goto search_done;
|
1702
|
-
} while (--i
|
1825
|
+
} while (--i > n2);
|
1703
1826
|
if (Max_retries < INT_MAX && --retry < 0)
|
1704
1827
|
break;
|
1705
1828
|
}
|
@@ -1728,7 +1851,7 @@ mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp)
|
|
1728
1851
|
if (rc) {
|
1729
1852
|
if (rc == MDB_NOTFOUND)
|
1730
1853
|
break;
|
1731
|
-
|
1854
|
+
goto fail;
|
1732
1855
|
}
|
1733
1856
|
last = *(txnid_t*)key.mv_data;
|
1734
1857
|
if (oldest <= last)
|
@@ -1741,11 +1864,13 @@ mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp)
|
|
1741
1864
|
idl = (MDB_ID *) data.mv_data;
|
1742
1865
|
i = idl[0];
|
1743
1866
|
if (!mop) {
|
1744
|
-
if (!(env->me_pghead = mop = mdb_midl_alloc(i)))
|
1745
|
-
|
1867
|
+
if (!(env->me_pghead = mop = mdb_midl_alloc(i))) {
|
1868
|
+
rc = ENOMEM;
|
1869
|
+
goto fail;
|
1870
|
+
}
|
1746
1871
|
} else {
|
1747
1872
|
if ((rc = mdb_midl_need(&env->me_pghead, i)) != 0)
|
1748
|
-
|
1873
|
+
goto fail;
|
1749
1874
|
mop = env->me_pghead;
|
1750
1875
|
}
|
1751
1876
|
env->me_pglast = last;
|
@@ -1774,15 +1899,18 @@ mdb_page_alloc(MDB_cursor *mc, int num, MDB_page **mp)
|
|
1774
1899
|
pgno = txn->mt_next_pgno;
|
1775
1900
|
if (pgno + num >= env->me_maxpg) {
|
1776
1901
|
DPUTS("DB size maxed out");
|
1777
|
-
|
1902
|
+
rc = MDB_MAP_FULL;
|
1903
|
+
goto fail;
|
1778
1904
|
}
|
1779
1905
|
|
1780
1906
|
search_done:
|
1781
1907
|
if (env->me_flags & MDB_WRITEMAP) {
|
1782
1908
|
np = (MDB_page *)(env->me_map + env->me_psize * pgno);
|
1783
1909
|
} else {
|
1784
|
-
if (!(np = mdb_page_malloc(txn, num)))
|
1785
|
-
|
1910
|
+
if (!(np = mdb_page_malloc(txn, num))) {
|
1911
|
+
rc = ENOMEM;
|
1912
|
+
goto fail;
|
1913
|
+
}
|
1786
1914
|
}
|
1787
1915
|
if (i) {
|
1788
1916
|
mop[0] = mop_len -= num;
|
@@ -1797,6 +1925,10 @@ search_done:
|
|
1797
1925
|
*mp = np;
|
1798
1926
|
|
1799
1927
|
return MDB_SUCCESS;
|
1928
|
+
|
1929
|
+
fail:
|
1930
|
+
txn->mt_flags |= MDB_TXN_ERROR;
|
1931
|
+
return rc;
|
1800
1932
|
}
|
1801
1933
|
|
1802
1934
|
/** Copy the used portions of a non-overflow page.
|
@@ -1827,7 +1959,7 @@ mdb_page_copy(MDB_page *dst, MDB_page *src, unsigned int psize)
|
|
1827
1959
|
* If a page being referenced was spilled to disk in this txn, bring
|
1828
1960
|
* it back and make it dirty/writable again.
|
1829
1961
|
* @param[in] txn the transaction handle.
|
1830
|
-
* @param[in] mp the page being referenced.
|
1962
|
+
* @param[in] mp the page being referenced. It must not be dirty.
|
1831
1963
|
* @param[out] ret the writable page, if any. ret is unchanged if
|
1832
1964
|
* mp wasn't spilled.
|
1833
1965
|
*/
|
@@ -1903,17 +2035,17 @@ mdb_page_touch(MDB_cursor *mc)
|
|
1903
2035
|
np = NULL;
|
1904
2036
|
rc = mdb_page_unspill(txn, mp, &np);
|
1905
2037
|
if (rc)
|
1906
|
-
|
2038
|
+
goto fail;
|
1907
2039
|
if (np)
|
1908
2040
|
goto done;
|
1909
2041
|
}
|
1910
2042
|
if ((rc = mdb_midl_need(&txn->mt_free_pgs, 1)) ||
|
1911
2043
|
(rc = mdb_page_alloc(mc, 1, &np)))
|
1912
|
-
|
2044
|
+
goto fail;
|
1913
2045
|
pgno = np->mp_pgno;
|
1914
2046
|
DPRINTF(("touched db %d page %"Z"u -> %"Z"u", DDBI(mc),
|
1915
2047
|
mp->mp_pgno, pgno));
|
1916
|
-
|
2048
|
+
mdb_cassert(mc, mp->mp_pgno != pgno);
|
1917
2049
|
mdb_midl_xappend(txn->mt_free_pgs, mp->mp_pgno);
|
1918
2050
|
/* Update the parent page, if any, to point to the new page */
|
1919
2051
|
if (mc->mc_top) {
|
@@ -1934,19 +2066,21 @@ mdb_page_touch(MDB_cursor *mc)
|
|
1934
2066
|
if (x <= dl[0].mid && dl[x].mid == pgno) {
|
1935
2067
|
if (mp != dl[x].mptr) { /* bad cursor? */
|
1936
2068
|
mc->mc_flags &= ~(C_INITIALIZED|C_EOF);
|
2069
|
+
txn->mt_flags |= MDB_TXN_ERROR;
|
1937
2070
|
return MDB_CORRUPTED;
|
1938
2071
|
}
|
1939
2072
|
return 0;
|
1940
2073
|
}
|
1941
2074
|
}
|
1942
|
-
|
2075
|
+
mdb_cassert(mc, dl[0].mid < MDB_IDL_UM_MAX);
|
1943
2076
|
/* No - copy it */
|
1944
2077
|
np = mdb_page_malloc(txn, 1);
|
1945
2078
|
if (!np)
|
1946
2079
|
return ENOMEM;
|
1947
2080
|
mid.mid = pgno;
|
1948
2081
|
mid.mptr = np;
|
1949
|
-
mdb_mid2l_insert(dl, &mid);
|
2082
|
+
rc = mdb_mid2l_insert(dl, &mid);
|
2083
|
+
mdb_cassert(mc, rc == 0);
|
1950
2084
|
} else {
|
1951
2085
|
return 0;
|
1952
2086
|
}
|
@@ -1972,6 +2106,7 @@ done:
|
|
1972
2106
|
if (m2->mc_pg[mc->mc_top] == mp) {
|
1973
2107
|
m2->mc_pg[mc->mc_top] = np;
|
1974
2108
|
if ((mc->mc_db->md_flags & MDB_DUPSORT) &&
|
2109
|
+
IS_LEAF(np) &&
|
1975
2110
|
m2->mc_ki[mc->mc_top] == mc->mc_ki[mc->mc_top])
|
1976
2111
|
{
|
1977
2112
|
MDB_node *leaf = NODEPTR(np, mc->mc_ki[mc->mc_top]);
|
@@ -1982,6 +2117,10 @@ done:
|
|
1982
2117
|
}
|
1983
2118
|
}
|
1984
2119
|
return 0;
|
2120
|
+
|
2121
|
+
fail:
|
2122
|
+
txn->mt_flags |= MDB_TXN_ERROR;
|
2123
|
+
return rc;
|
1985
2124
|
}
|
1986
2125
|
|
1987
2126
|
int
|
@@ -2177,13 +2316,11 @@ mdb_txn_renew0(MDB_txn *txn)
|
|
2177
2316
|
MDB_PID_T pid = env->me_pid;
|
2178
2317
|
pthread_t tid = pthread_self();
|
2179
2318
|
|
2180
|
-
if (!
|
2319
|
+
if (!env->me_live_reader) {
|
2181
2320
|
rc = mdb_reader_pid(env, Pidset, pid);
|
2182
|
-
if (rc)
|
2183
|
-
UNLOCK_MUTEX_R(env);
|
2321
|
+
if (rc)
|
2184
2322
|
return rc;
|
2185
|
-
|
2186
|
-
env->me_flags |= MDB_LIVE_READER;
|
2323
|
+
env->me_live_reader = 1;
|
2187
2324
|
}
|
2188
2325
|
|
2189
2326
|
LOCK_MUTEX_R(env);
|
@@ -2543,7 +2680,7 @@ mdb_freelist_save(MDB_txn *txn)
|
|
2543
2680
|
return rc;
|
2544
2681
|
pglast = head_id = *(txnid_t *)key.mv_data;
|
2545
2682
|
total_room = head_room = 0;
|
2546
|
-
|
2683
|
+
mdb_tassert(txn, pglast <= env->me_pglast);
|
2547
2684
|
rc = mdb_cursor_del(&mc, 0);
|
2548
2685
|
if (rc)
|
2549
2686
|
return rc;
|
@@ -2633,22 +2770,20 @@ mdb_freelist_save(MDB_txn *txn)
|
|
2633
2770
|
mop += mop_len;
|
2634
2771
|
rc = mdb_cursor_first(&mc, &key, &data);
|
2635
2772
|
for (; !rc; rc = mdb_cursor_next(&mc, &key, &data, MDB_NEXT)) {
|
2636
|
-
unsigned flags = MDB_CURRENT;
|
2637
2773
|
txnid_t id = *(txnid_t *)key.mv_data;
|
2638
2774
|
ssize_t len = (ssize_t)(data.mv_size / sizeof(MDB_ID)) - 1;
|
2639
2775
|
MDB_ID save;
|
2640
2776
|
|
2641
|
-
|
2777
|
+
mdb_tassert(txn, len >= 0 && id <= env->me_pglast);
|
2642
2778
|
key.mv_data = &id;
|
2643
2779
|
if (len > mop_len) {
|
2644
2780
|
len = mop_len;
|
2645
2781
|
data.mv_size = (len + 1) * sizeof(MDB_ID);
|
2646
|
-
flags = 0;
|
2647
2782
|
}
|
2648
2783
|
data.mv_data = mop -= len;
|
2649
2784
|
save = mop[0];
|
2650
2785
|
mop[0] = len;
|
2651
|
-
rc = mdb_cursor_put(&mc, &key, &data,
|
2786
|
+
rc = mdb_cursor_put(&mc, &key, &data, MDB_CURRENT);
|
2652
2787
|
mop[0] = save;
|
2653
2788
|
if (rc || !(mop_len -= len))
|
2654
2789
|
break;
|
@@ -2804,8 +2939,8 @@ mdb_txn_commit(MDB_txn *txn)
|
|
2804
2939
|
unsigned int i;
|
2805
2940
|
MDB_env *env;
|
2806
2941
|
|
2807
|
-
|
2808
|
-
|
2942
|
+
if (txn == NULL || txn->mt_env == NULL)
|
2943
|
+
return EINVAL;
|
2809
2944
|
|
2810
2945
|
if (txn->mt_child) {
|
2811
2946
|
rc = mdb_txn_commit(txn->mt_child);
|
@@ -2913,7 +3048,7 @@ mdb_txn_commit(MDB_txn *txn)
|
|
2913
3048
|
if (yp == dst[x].mid)
|
2914
3049
|
free(dst[x--].mptr);
|
2915
3050
|
}
|
2916
|
-
|
3051
|
+
mdb_tassert(txn, i == x);
|
2917
3052
|
dst[0].mid = len;
|
2918
3053
|
free(txn->mt_u.dirty_list);
|
2919
3054
|
parent->mt_dirty_room = txn->mt_dirty_room;
|
@@ -3146,9 +3281,6 @@ mdb_env_write_meta(MDB_txn *txn)
|
|
3146
3281
|
int r2;
|
3147
3282
|
#endif
|
3148
3283
|
|
3149
|
-
assert(txn != NULL);
|
3150
|
-
assert(txn->mt_env != NULL);
|
3151
|
-
|
3152
3284
|
toggle = txn->mt_txnid & 1;
|
3153
3285
|
DPRINTF(("writing meta page %d for root page %"Z"u",
|
3154
3286
|
toggle, txn->mt_dbs[MAIN_DBI].md_root));
|
@@ -3470,7 +3602,7 @@ mdb_env_open2(MDB_env *env)
|
|
3470
3602
|
env->me_mapsize = minsize;
|
3471
3603
|
}
|
3472
3604
|
|
3473
|
-
rc = mdb_env_map(env, meta.mm_address, newenv);
|
3605
|
+
rc = mdb_env_map(env, meta.mm_address, newenv || env->me_mapsize != meta.mm_mapsize);
|
3474
3606
|
if (rc)
|
3475
3607
|
return rc;
|
3476
3608
|
|
@@ -3482,10 +3614,15 @@ mdb_env_open2(MDB_env *env)
|
|
3482
3614
|
return i;
|
3483
3615
|
}
|
3484
3616
|
}
|
3485
|
-
env->me_maxfree_1pg = (env->me_psize - PAGEHDRSZ) / sizeof(pgno_t) - 1;
|
3486
|
-
env->me_nodemax = (env->me_psize - PAGEHDRSZ) / MDB_MINKEYS;
|
3487
3617
|
|
3618
|
+
env->me_maxfree_1pg = (env->me_psize - PAGEHDRSZ) / sizeof(pgno_t) - 1;
|
3619
|
+
env->me_nodemax = (((env->me_psize - PAGEHDRSZ) / MDB_MINKEYS) & -2)
|
3620
|
+
- sizeof(indx_t);
|
3621
|
+
#if !(MDB_MAXKEYSIZE)
|
3622
|
+
env->me_maxkey = env->me_nodemax - (NODESIZE + sizeof(MDB_db));
|
3623
|
+
#endif
|
3488
3624
|
env->me_maxpg = env->me_mapsize / env->me_psize;
|
3625
|
+
|
3489
3626
|
#if MDB_DEBUG
|
3490
3627
|
{
|
3491
3628
|
int toggle = mdb_env_pick_meta(env);
|
@@ -3540,7 +3677,9 @@ static void NTAPI mdb_tls_callback(PVOID module, DWORD reason, PVOID ptr)
|
|
3540
3677
|
case DLL_THREAD_DETACH:
|
3541
3678
|
for (i=0; i<mdb_tls_nkeys; i++) {
|
3542
3679
|
MDB_reader *r = pthread_getspecific(mdb_tls_keys[i]);
|
3543
|
-
|
3680
|
+
if (r) {
|
3681
|
+
mdb_env_reader_dest(r);
|
3682
|
+
}
|
3544
3683
|
}
|
3545
3684
|
break;
|
3546
3685
|
case DLL_PROCESS_DETACH: break;
|
@@ -3985,6 +4124,10 @@ fail:
|
|
3985
4124
|
#define CHANGELESS (MDB_FIXEDMAP|MDB_NOSUBDIR|MDB_RDONLY|MDB_WRITEMAP| \
|
3986
4125
|
MDB_NOTLS|MDB_NOLOCK|MDB_NORDAHEAD)
|
3987
4126
|
|
4127
|
+
#if VALID_FLAGS & PERSISTENT_FLAGS & (CHANGEABLE|CHANGELESS)
|
4128
|
+
# error "Persistent DB flags & env flags overlap, but both go in mm_flags"
|
4129
|
+
#endif
|
4130
|
+
|
3988
4131
|
int
|
3989
4132
|
mdb_env_open(MDB_env *env, const char *path, unsigned int flags, mdb_mode_t mode)
|
3990
4133
|
{
|
@@ -4403,6 +4546,13 @@ mdb_cmp_cint(const MDB_val *a, const MDB_val *b)
|
|
4403
4546
|
#endif
|
4404
4547
|
}
|
4405
4548
|
|
4549
|
+
/** Compare two items pointing at size_t's of unknown alignment. */
|
4550
|
+
#ifdef MISALIGNED_OK
|
4551
|
+
# define mdb_cmp_clong mdb_cmp_long
|
4552
|
+
#else
|
4553
|
+
# define mdb_cmp_clong mdb_cmp_cint
|
4554
|
+
#endif
|
4555
|
+
|
4406
4556
|
/** Compare two items lexically */
|
4407
4557
|
static int
|
4408
4558
|
mdb_cmp_memn(const MDB_val *a, const MDB_val *b)
|
@@ -4469,17 +4619,9 @@ mdb_node_search(MDB_cursor *mc, MDB_val *key, int *exactp)
|
|
4469
4619
|
|
4470
4620
|
nkeys = NUMKEYS(mp);
|
4471
4621
|
|
4472
|
-
#if MDB_DEBUG
|
4473
|
-
{
|
4474
|
-
pgno_t pgno;
|
4475
|
-
COPY_PGNO(pgno, mp->mp_pgno);
|
4476
4622
|
DPRINTF(("searching %u keys in %s %spage %"Z"u",
|
4477
4623
|
nkeys, IS_LEAF(mp) ? "leaf" : "branch", IS_SUBP(mp) ? "sub-" : "",
|
4478
|
-
|
4479
|
-
}
|
4480
|
-
#endif
|
4481
|
-
|
4482
|
-
assert(nkeys > 0);
|
4624
|
+
mdb_dbg_pgno(mp)));
|
4483
4625
|
|
4484
4626
|
low = IS_LEAF(mp) ? 0 : 1;
|
4485
4627
|
high = nkeys - 1;
|
@@ -4543,7 +4685,7 @@ mdb_node_search(MDB_cursor *mc, MDB_val *key, int *exactp)
|
|
4543
4685
|
node = NODEPTR(mp, i);
|
4544
4686
|
}
|
4545
4687
|
if (exactp)
|
4546
|
-
*exactp = (rc == 0);
|
4688
|
+
*exactp = (rc == 0 && nkeys > 0);
|
4547
4689
|
/* store the key index */
|
4548
4690
|
mc->mc_ki[mc->mc_top] = i;
|
4549
4691
|
if (i >= nkeys)
|
@@ -4593,7 +4735,7 @@ mdb_cursor_push(MDB_cursor *mc, MDB_page *mp)
|
|
4593
4735
|
DDBI(mc), (void *) mc));
|
4594
4736
|
|
4595
4737
|
if (mc->mc_snum >= CURSOR_STACK) {
|
4596
|
-
|
4738
|
+
mc->mc_txn->mt_flags |= MDB_TXN_ERROR;
|
4597
4739
|
return MDB_CURSOR_FULL;
|
4598
4740
|
}
|
4599
4741
|
|
@@ -4653,7 +4795,7 @@ mdb_page_get(MDB_txn *txn, pgno_t pgno, MDB_page **ret, int *lvl)
|
|
4653
4795
|
p = (MDB_page *)(env->me_map + env->me_psize * pgno);
|
4654
4796
|
} else {
|
4655
4797
|
DPRINTF(("page %"Z"u not found", pgno));
|
4656
|
-
|
4798
|
+
txn->mt_flags |= MDB_TXN_ERROR;
|
4657
4799
|
return MDB_PAGE_NOTFOUND;
|
4658
4800
|
}
|
4659
4801
|
|
@@ -4679,7 +4821,7 @@ mdb_page_search_root(MDB_cursor *mc, MDB_val *key, int flags)
|
|
4679
4821
|
indx_t i;
|
4680
4822
|
|
4681
4823
|
DPRINTF(("branch page %"Z"u has %u keys", mp->mp_pgno, NUMKEYS(mp)));
|
4682
|
-
|
4824
|
+
mdb_cassert(mc, NUMKEYS(mp) > 1);
|
4683
4825
|
DPRINTF(("found index 0 to page %"Z"u", NODEPGNO(NODEPTR(mp, 0))));
|
4684
4826
|
|
4685
4827
|
if (flags & (MDB_PS_FIRST|MDB_PS_LAST)) {
|
@@ -4694,14 +4836,14 @@ mdb_page_search_root(MDB_cursor *mc, MDB_val *key, int flags)
|
|
4694
4836
|
else {
|
4695
4837
|
i = mc->mc_ki[mc->mc_top];
|
4696
4838
|
if (!exact) {
|
4697
|
-
|
4839
|
+
mdb_cassert(mc, i > 0);
|
4698
4840
|
i--;
|
4699
4841
|
}
|
4700
4842
|
}
|
4701
4843
|
DPRINTF(("following index %u for key [%s]", i, DKEY(key)));
|
4702
4844
|
}
|
4703
4845
|
|
4704
|
-
|
4846
|
+
mdb_cassert(mc, i < NUMKEYS(mp));
|
4705
4847
|
node = NODEPTR(mp, i);
|
4706
4848
|
|
4707
4849
|
if ((rc = mdb_page_get(mc->mc_txn, NODEPGNO(node), &mp, NULL)) != 0)
|
@@ -4721,6 +4863,7 @@ mdb_page_search_root(MDB_cursor *mc, MDB_val *key, int flags)
|
|
4721
4863
|
if (!IS_LEAF(mp)) {
|
4722
4864
|
DPRINTF(("internal error, index points to a %02X page!?",
|
4723
4865
|
mp->mp_flags));
|
4866
|
+
mc->mc_txn->mt_flags |= MDB_TXN_ERROR;
|
4724
4867
|
return MDB_CORRUPTED;
|
4725
4868
|
}
|
4726
4869
|
|
@@ -4815,7 +4958,7 @@ mdb_page_search(MDB_cursor *mc, MDB_val *key, int flags)
|
|
4815
4958
|
}
|
4816
4959
|
}
|
4817
4960
|
|
4818
|
-
|
4961
|
+
mdb_cassert(mc, root > 1);
|
4819
4962
|
if (!mc->mc_pg[0] || mc->mc_pg[0]->mp_pgno != root)
|
4820
4963
|
if ((rc = mdb_page_get(mc->mc_txn, root, &mc->mc_pg[0], NULL)) != 0)
|
4821
4964
|
return rc;
|
@@ -4885,7 +5028,7 @@ mdb_ovpage_free(MDB_cursor *mc, MDB_page *mp)
|
|
4885
5028
|
iy = dl[x];
|
4886
5029
|
dl[x] = ix;
|
4887
5030
|
} else {
|
4888
|
-
|
5031
|
+
mdb_cassert(mc, x > 1);
|
4889
5032
|
j = ++(dl[0].mid);
|
4890
5033
|
dl[j] = ix; /* Unsorted. OK when MDB_TXN_ERROR. */
|
4891
5034
|
txn->mt_flags |= MDB_TXN_ERROR;
|
@@ -4953,20 +5096,14 @@ mdb_get(MDB_txn *txn, MDB_dbi dbi,
|
|
4953
5096
|
int exact = 0;
|
4954
5097
|
DKBUF;
|
4955
5098
|
|
4956
|
-
assert(key);
|
4957
|
-
assert(data);
|
4958
5099
|
DPRINTF(("===> get db %u key [%s]", dbi, DKEY(key)));
|
4959
5100
|
|
4960
|
-
if (
|
5101
|
+
if (!key || !data || dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
|
4961
5102
|
return EINVAL;
|
4962
5103
|
|
4963
5104
|
if (txn->mt_flags & MDB_TXN_ERROR)
|
4964
5105
|
return MDB_BAD_TXN;
|
4965
5106
|
|
4966
|
-
if (key->mv_size > MDB_MAXKEYSIZE) {
|
4967
|
-
return MDB_BAD_VALSIZE;
|
4968
|
-
}
|
4969
|
-
|
4970
5107
|
mdb_cursor_init(&mc, txn, dbi, &mx);
|
4971
5108
|
return mdb_cursor_set(&mc, key, data, MDB_SET, &exact);
|
4972
5109
|
}
|
@@ -5012,7 +5149,7 @@ mdb_cursor_sibling(MDB_cursor *mc, int move_right)
|
|
5012
5149
|
DPRINTF(("just moving to %s index key %u",
|
5013
5150
|
move_right ? "right" : "left", mc->mc_ki[mc->mc_top]));
|
5014
5151
|
}
|
5015
|
-
|
5152
|
+
mdb_cassert(mc, IS_BRANCH(mc->mc_pg[mc->mc_top]));
|
5016
5153
|
|
5017
5154
|
indx = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
|
5018
5155
|
if ((rc = mdb_page_get(mc->mc_txn, NODEPGNO(indx), &mp, NULL)) != 0) {
|
@@ -5040,7 +5177,7 @@ mdb_cursor_next(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op)
|
|
5040
5177
|
return MDB_NOTFOUND;
|
5041
5178
|
}
|
5042
5179
|
|
5043
|
-
|
5180
|
+
mdb_cassert(mc, mc->mc_flags & C_INITIALIZED);
|
5044
5181
|
|
5045
5182
|
mp = mc->mc_pg[mc->mc_top];
|
5046
5183
|
|
@@ -5062,7 +5199,8 @@ mdb_cursor_next(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op)
|
|
5062
5199
|
}
|
5063
5200
|
}
|
5064
5201
|
|
5065
|
-
DPRINTF(("cursor_next: top page is %"Z"u in cursor %p",
|
5202
|
+
DPRINTF(("cursor_next: top page is %"Z"u in cursor %p",
|
5203
|
+
mdb_dbg_pgno(mp), (void *) mc));
|
5066
5204
|
if (mc->mc_flags & C_DEL)
|
5067
5205
|
goto skip;
|
5068
5206
|
|
@@ -5079,7 +5217,7 @@ mdb_cursor_next(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op)
|
|
5079
5217
|
|
5080
5218
|
skip:
|
5081
5219
|
DPRINTF(("==> cursor points to page %"Z"u with %u keys, key index %u",
|
5082
|
-
mp
|
5220
|
+
mdb_dbg_pgno(mp), NUMKEYS(mp), mc->mc_ki[mc->mc_top]));
|
5083
5221
|
|
5084
5222
|
if (IS_LEAF2(mp)) {
|
5085
5223
|
key->mv_size = mc->mc_db->md_pad;
|
@@ -5087,7 +5225,7 @@ skip:
|
|
5087
5225
|
return MDB_SUCCESS;
|
5088
5226
|
}
|
5089
5227
|
|
5090
|
-
|
5228
|
+
mdb_cassert(mc, IS_LEAF(mp));
|
5091
5229
|
leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
|
5092
5230
|
|
5093
5231
|
if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
|
@@ -5116,7 +5254,7 @@ mdb_cursor_prev(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op)
|
|
5116
5254
|
MDB_node *leaf;
|
5117
5255
|
int rc;
|
5118
5256
|
|
5119
|
-
|
5257
|
+
mdb_cassert(mc, mc->mc_flags & C_INITIALIZED);
|
5120
5258
|
|
5121
5259
|
mp = mc->mc_pg[mc->mc_top];
|
5122
5260
|
|
@@ -5138,7 +5276,8 @@ mdb_cursor_prev(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op)
|
|
5138
5276
|
}
|
5139
5277
|
}
|
5140
5278
|
|
5141
|
-
DPRINTF(("cursor_prev: top page is %"Z"u in cursor %p",
|
5279
|
+
DPRINTF(("cursor_prev: top page is %"Z"u in cursor %p",
|
5280
|
+
mdb_dbg_pgno(mp), (void *) mc));
|
5142
5281
|
|
5143
5282
|
if (mc->mc_ki[mc->mc_top] == 0) {
|
5144
5283
|
DPUTS("=====> move to prev sibling page");
|
@@ -5154,7 +5293,7 @@ mdb_cursor_prev(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op)
|
|
5154
5293
|
mc->mc_flags &= ~C_EOF;
|
5155
5294
|
|
5156
5295
|
DPRINTF(("==> cursor points to page %"Z"u with %u keys, key index %u",
|
5157
|
-
mp
|
5296
|
+
mdb_dbg_pgno(mp), NUMKEYS(mp), mc->mc_ki[mc->mc_top]));
|
5158
5297
|
|
5159
5298
|
if (IS_LEAF2(mp)) {
|
5160
5299
|
key->mv_size = mc->mc_db->md_pad;
|
@@ -5162,7 +5301,7 @@ mdb_cursor_prev(MDB_cursor *mc, MDB_val *key, MDB_val *data, MDB_cursor_op op)
|
|
5162
5301
|
return MDB_SUCCESS;
|
5163
5302
|
}
|
5164
5303
|
|
5165
|
-
|
5304
|
+
mdb_cassert(mc, IS_LEAF(mp));
|
5166
5305
|
leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
|
5167
5306
|
|
5168
5307
|
if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
|
@@ -5193,8 +5332,6 @@ mdb_cursor_set(MDB_cursor *mc, MDB_val *key, MDB_val *data,
|
|
5193
5332
|
MDB_node *leaf = NULL;
|
5194
5333
|
DKBUF;
|
5195
5334
|
|
5196
|
-
assert(mc);
|
5197
|
-
assert(key);
|
5198
5335
|
if (key->mv_size == 0)
|
5199
5336
|
return MDB_BAD_VALSIZE;
|
5200
5337
|
|
@@ -5284,7 +5421,7 @@ mdb_cursor_set(MDB_cursor *mc, MDB_val *key, MDB_val *data,
|
|
5284
5421
|
if (!mc->mc_top) {
|
5285
5422
|
/* There are no other pages */
|
5286
5423
|
mc->mc_ki[mc->mc_top] = 0;
|
5287
|
-
if (op == MDB_SET_RANGE) {
|
5424
|
+
if (op == MDB_SET_RANGE && !exactp) {
|
5288
5425
|
rc = 0;
|
5289
5426
|
goto set1;
|
5290
5427
|
} else
|
@@ -5297,7 +5434,7 @@ mdb_cursor_set(MDB_cursor *mc, MDB_val *key, MDB_val *data,
|
|
5297
5434
|
return rc;
|
5298
5435
|
|
5299
5436
|
mp = mc->mc_pg[mc->mc_top];
|
5300
|
-
|
5437
|
+
mdb_cassert(mc, IS_LEAF(mp));
|
5301
5438
|
|
5302
5439
|
set2:
|
5303
5440
|
leaf = mdb_node_search(mc, key, exactp);
|
@@ -5311,7 +5448,7 @@ set2:
|
|
5311
5448
|
if ((rc = mdb_cursor_sibling(mc, 1)) != MDB_SUCCESS)
|
5312
5449
|
return rc; /* no entries matched */
|
5313
5450
|
mp = mc->mc_pg[mc->mc_top];
|
5314
|
-
|
5451
|
+
mdb_cassert(mc, IS_LEAF(mp));
|
5315
5452
|
leaf = NODEPTR(mp, 0);
|
5316
5453
|
}
|
5317
5454
|
|
@@ -5353,6 +5490,7 @@ set1:
|
|
5353
5490
|
if (op == MDB_GET_BOTH || rc > 0)
|
5354
5491
|
return MDB_NOTFOUND;
|
5355
5492
|
rc = 0;
|
5493
|
+
*data = d2;
|
5356
5494
|
}
|
5357
5495
|
|
5358
5496
|
} else {
|
@@ -5386,7 +5524,7 @@ mdb_cursor_first(MDB_cursor *mc, MDB_val *key, MDB_val *data)
|
|
5386
5524
|
if (rc != MDB_SUCCESS)
|
5387
5525
|
return rc;
|
5388
5526
|
}
|
5389
|
-
|
5527
|
+
mdb_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top]));
|
5390
5528
|
|
5391
5529
|
leaf = NODEPTR(mc->mc_pg[mc->mc_top], 0);
|
5392
5530
|
mc->mc_flags |= C_INITIALIZED;
|
@@ -5432,7 +5570,7 @@ mdb_cursor_last(MDB_cursor *mc, MDB_val *key, MDB_val *data)
|
|
5432
5570
|
if (rc != MDB_SUCCESS)
|
5433
5571
|
return rc;
|
5434
5572
|
}
|
5435
|
-
|
5573
|
+
mdb_cassert(mc, IS_LEAF(mc->mc_pg[mc->mc_top]));
|
5436
5574
|
|
5437
5575
|
}
|
5438
5576
|
mc->mc_ki[mc->mc_top] = NUMKEYS(mc->mc_pg[mc->mc_top]) - 1;
|
@@ -5469,7 +5607,8 @@ mdb_cursor_get(MDB_cursor *mc, MDB_val *key, MDB_val *data,
|
|
5469
5607
|
int exact = 0;
|
5470
5608
|
int (*mfunc)(MDB_cursor *mc, MDB_val *key, MDB_val *data);
|
5471
5609
|
|
5472
|
-
|
5610
|
+
if (mc == NULL)
|
5611
|
+
return EINVAL;
|
5473
5612
|
|
5474
5613
|
if (mc->mc_txn->mt_flags & MDB_TXN_ERROR)
|
5475
5614
|
return MDB_BAD_TXN;
|
@@ -5521,12 +5660,10 @@ mdb_cursor_get(MDB_cursor *mc, MDB_val *key, MDB_val *data,
|
|
5521
5660
|
case MDB_SET_RANGE:
|
5522
5661
|
if (key == NULL) {
|
5523
5662
|
rc = EINVAL;
|
5524
|
-
} else
|
5525
|
-
rc =
|
5526
|
-
|
5527
|
-
|
5528
|
-
else
|
5529
|
-
rc = mdb_cursor_set(mc, key, data, op, &exact);
|
5663
|
+
} else {
|
5664
|
+
rc = mdb_cursor_set(mc, key, data, op,
|
5665
|
+
op == MDB_SET_RANGE ? NULL : &exact);
|
5666
|
+
}
|
5530
5667
|
break;
|
5531
5668
|
case MDB_GET_MULTIPLE:
|
5532
5669
|
if (data == NULL || !(mc->mc_flags & C_INITIALIZED)) {
|
@@ -5663,18 +5800,24 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data,
|
|
5663
5800
|
unsigned int flags)
|
5664
5801
|
{
|
5665
5802
|
enum { MDB_NO_ROOT = MDB_LAST_ERRCODE+10 }; /* internal code */
|
5666
|
-
MDB_env *env
|
5803
|
+
MDB_env *env;
|
5667
5804
|
MDB_node *leaf = NULL;
|
5668
|
-
|
5805
|
+
MDB_page *fp, *mp;
|
5806
|
+
uint16_t fp_flags;
|
5807
|
+
MDB_val xdata, *rdata, dkey, olddata;
|
5669
5808
|
MDB_db dummy;
|
5670
|
-
int do_sub = 0,
|
5809
|
+
int do_sub = 0, insert_key, insert_data;
|
5671
5810
|
unsigned int mcount = 0, dcount = 0, nospill;
|
5672
5811
|
size_t nsize;
|
5673
5812
|
int rc, rc2;
|
5674
|
-
char dbuf[MDB_MAXKEYSIZE+1];
|
5675
5813
|
unsigned int nflags;
|
5676
5814
|
DKBUF;
|
5677
5815
|
|
5816
|
+
if (mc == NULL || key == NULL)
|
5817
|
+
return EINVAL;
|
5818
|
+
|
5819
|
+
env = mc->mc_txn->mt_env;
|
5820
|
+
|
5678
5821
|
/* Check this first so counter will always be zero on any
|
5679
5822
|
* early failures.
|
5680
5823
|
*/
|
@@ -5691,14 +5834,14 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data,
|
|
5691
5834
|
if (mc->mc_txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_ERROR))
|
5692
5835
|
return (mc->mc_txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN;
|
5693
5836
|
|
5694
|
-
if (
|
5695
|
-
return MDB_BAD_VALSIZE;
|
5696
|
-
|
5697
|
-
if (F_ISSET(mc->mc_db->md_flags, MDB_DUPSORT) && data->mv_size > MDB_MAXKEYSIZE)
|
5837
|
+
if (key->mv_size-1 >= ENV_MAXKEY(env))
|
5698
5838
|
return MDB_BAD_VALSIZE;
|
5699
5839
|
|
5700
5840
|
#if SIZE_MAX > MAXDATASIZE
|
5701
|
-
if (data->mv_size > MAXDATASIZE)
|
5841
|
+
if (data->mv_size > ((mc->mc_db->md_flags & MDB_DUPSORT) ? ENV_MAXKEY(env) : MAXDATASIZE))
|
5842
|
+
return MDB_BAD_VALSIZE;
|
5843
|
+
#else
|
5844
|
+
if ((mc->mc_db->md_flags & MDB_DUPSORT) && data->mv_size > ENV_MAXKEY(env))
|
5702
5845
|
return MDB_BAD_VALSIZE;
|
5703
5846
|
#endif
|
5704
5847
|
|
@@ -5782,11 +5925,21 @@ mdb_cursor_put(MDB_cursor *mc, MDB_val *key, MDB_val *data,
|
|
5782
5925
|
return rc2;
|
5783
5926
|
}
|
5784
5927
|
|
5785
|
-
|
5786
|
-
if (
|
5787
|
-
|
5788
|
-
|
5789
|
-
|
5928
|
+
insert_key = insert_data = rc;
|
5929
|
+
if (insert_key) {
|
5930
|
+
/* The key does not exist */
|
5931
|
+
DPRINTF(("inserting key at index %i", mc->mc_ki[mc->mc_top]));
|
5932
|
+
if ((mc->mc_db->md_flags & MDB_DUPSORT) &&
|
5933
|
+
LEAFSIZE(key, data) > env->me_nodemax)
|
5934
|
+
{
|
5935
|
+
/* Too big for a node, insert in sub-DB */
|
5936
|
+
fp_flags = P_LEAF|P_DIRTY;
|
5937
|
+
fp = env->me_pbuf;
|
5938
|
+
fp->mp_pad = data->mv_size; /* used if MDB_DUPFIXED */
|
5939
|
+
fp->mp_lower = fp->mp_upper = olddata.mv_size = PAGEHDRSZ;
|
5940
|
+
goto prep_subDB;
|
5941
|
+
}
|
5942
|
+
} else {
|
5790
5943
|
/* there's only a key anyway, so this is a no-op */
|
5791
5944
|
if (IS_LEAF2(mc->mc_pg[mc->mc_top])) {
|
5792
5945
|
unsigned int ksize = mc->mc_db->md_pad;
|
@@ -5806,6 +5959,12 @@ more:
|
|
5806
5959
|
|
5807
5960
|
/* DB has dups? */
|
5808
5961
|
if (F_ISSET(mc->mc_db->md_flags, MDB_DUPSORT)) {
|
5962
|
+
/* Prepare (sub-)page/sub-DB to accept the new item,
|
5963
|
+
* if needed. fp: old sub-page or a header faking
|
5964
|
+
* it. mp: new (sub-)page. offset: growth in page
|
5965
|
+
* size. xdata: node data with new page or DB.
|
5966
|
+
*/
|
5967
|
+
unsigned i, offset = 0;
|
5809
5968
|
mp = fp = xdata.mv_data = env->me_pbuf;
|
5810
5969
|
mp->mp_pgno = mc->mc_pg[mc->mc_top]->mp_pgno;
|
5811
5970
|
|
@@ -5815,29 +5974,23 @@ more:
|
|
5815
5974
|
if (flags == MDB_CURRENT)
|
5816
5975
|
goto current;
|
5817
5976
|
|
5818
|
-
dkey = olddata;
|
5819
5977
|
#if UINT_MAX < SIZE_MAX
|
5820
|
-
if (mc->mc_dbx->md_dcmp == mdb_cmp_int &&
|
5821
|
-
|
5822
|
-
mc->mc_dbx->md_dcmp = mdb_cmp_long;
|
5823
|
-
#else
|
5824
|
-
mc->mc_dbx->md_dcmp = mdb_cmp_cint;
|
5825
|
-
#endif
|
5978
|
+
if (mc->mc_dbx->md_dcmp == mdb_cmp_int && olddata.mv_size == sizeof(size_t))
|
5979
|
+
mc->mc_dbx->md_dcmp = mdb_cmp_clong;
|
5826
5980
|
#endif
|
5827
5981
|
/* if data matches, skip it */
|
5828
|
-
if (!mc->mc_dbx->md_dcmp(data, &
|
5982
|
+
if (!mc->mc_dbx->md_dcmp(data, &olddata)) {
|
5829
5983
|
if (flags & MDB_NODUPDATA)
|
5830
|
-
|
5831
|
-
|
5832
|
-
|
5833
|
-
else
|
5834
|
-
rc = MDB_SUCCESS;
|
5835
|
-
return rc;
|
5984
|
+
return MDB_KEYEXIST;
|
5985
|
+
rc = MDB_SUCCESS;
|
5986
|
+
goto next_sub;
|
5836
5987
|
}
|
5837
5988
|
|
5838
|
-
/*
|
5839
|
-
|
5840
|
-
dkey.mv_data =
|
5989
|
+
/* Back up original data item */
|
5990
|
+
dkey.mv_size = olddata.mv_size;
|
5991
|
+
dkey.mv_data = memcpy(fp+1, olddata.mv_data, olddata.mv_size);
|
5992
|
+
|
5993
|
+
/* Make sub-page header for the dup items, with dummy body */
|
5841
5994
|
fp->mp_flags = P_LEAF|P_DIRTY|P_SUBP;
|
5842
5995
|
fp->mp_lower = PAGEHDRSZ;
|
5843
5996
|
xdata.mv_size = PAGEHDRSZ + dkey.mv_size + data->mv_size;
|
@@ -5850,22 +6003,19 @@ more:
|
|
5850
6003
|
(dkey.mv_size & 1) + (data->mv_size & 1);
|
5851
6004
|
}
|
5852
6005
|
fp->mp_upper = xdata.mv_size;
|
6006
|
+
olddata.mv_size = fp->mp_upper; /* pretend olddata is fp */
|
5853
6007
|
} else if (leaf->mn_flags & F_SUBDATA) {
|
5854
6008
|
/* Data is on sub-DB, just store it */
|
5855
6009
|
flags |= F_DUPDATA|F_SUBDATA;
|
5856
6010
|
goto put_sub;
|
5857
6011
|
} else {
|
5858
|
-
/*
|
5859
|
-
unsigned int offset;
|
5860
|
-
unsigned int i;
|
5861
|
-
uint16_t fp_flags;
|
5862
|
-
|
6012
|
+
/* Data is on sub-page */
|
5863
6013
|
fp = olddata.mv_data;
|
5864
6014
|
switch (flags) {
|
5865
6015
|
default:
|
5866
6016
|
if (!(mc->mc_db->md_flags & MDB_DUPFIXED)) {
|
5867
|
-
offset = NODESIZE + sizeof(indx_t) +
|
5868
|
-
|
6017
|
+
offset = EVEN(NODESIZE + sizeof(indx_t) +
|
6018
|
+
data->mv_size);
|
5869
6019
|
break;
|
5870
6020
|
}
|
5871
6021
|
offset = fp->mp_pad;
|
@@ -5881,12 +6031,16 @@ more:
|
|
5881
6031
|
flags |= F_DUPDATA;
|
5882
6032
|
goto put_sub;
|
5883
6033
|
}
|
5884
|
-
fp_flags = fp->mp_flags;
|
5885
6034
|
xdata.mv_size = olddata.mv_size + offset;
|
5886
|
-
|
5887
|
-
|
5888
|
-
|
6035
|
+
}
|
6036
|
+
|
6037
|
+
fp_flags = fp->mp_flags;
|
6038
|
+
if (NODESIZE + NODEKSZ(leaf) + xdata.mv_size > env->me_nodemax) {
|
6039
|
+
/* Too big for a sub-page, convert to sub-DB */
|
6040
|
+
fp_flags &= ~P_SUBP;
|
6041
|
+
prep_subDB:
|
5889
6042
|
if (mc->mc_db->md_flags & MDB_DUPFIXED) {
|
6043
|
+
fp_flags |= P_LEAF2;
|
5890
6044
|
dummy.md_pad = fp->mp_pad;
|
5891
6045
|
dummy.md_flags = MDB_DUPFIXED;
|
5892
6046
|
if (mc->mc_db->md_flags & MDB_INTEGERDUP)
|
@@ -5907,13 +6061,13 @@ more:
|
|
5907
6061
|
offset = env->me_psize - olddata.mv_size;
|
5908
6062
|
flags |= F_DUPDATA|F_SUBDATA;
|
5909
6063
|
dummy.md_root = mp->mp_pgno;
|
5910
|
-
|
5911
|
-
|
6064
|
+
}
|
6065
|
+
if (mp != fp) {
|
5912
6066
|
mp->mp_flags = fp_flags | P_DIRTY;
|
5913
6067
|
mp->mp_pad = fp->mp_pad;
|
5914
6068
|
mp->mp_lower = fp->mp_lower;
|
5915
6069
|
mp->mp_upper = fp->mp_upper + offset;
|
5916
|
-
if (
|
6070
|
+
if (fp_flags & P_LEAF2) {
|
5917
6071
|
memcpy(METADATA(mp), METADATA(fp), NUMKEYS(fp) * fp->mp_pad);
|
5918
6072
|
} else {
|
5919
6073
|
memcpy((char *)mp + mp->mp_upper, (char *)fp + fp->mp_upper,
|
@@ -5926,7 +6080,8 @@ more:
|
|
5926
6080
|
rdata = &xdata;
|
5927
6081
|
flags |= F_DUPDATA;
|
5928
6082
|
do_sub = 1;
|
5929
|
-
|
6083
|
+
if (!insert_key)
|
6084
|
+
mdb_node_del(mc, 0);
|
5930
6085
|
goto new_sub;
|
5931
6086
|
}
|
5932
6087
|
current:
|
@@ -5966,7 +6121,8 @@ current:
|
|
5966
6121
|
return ENOMEM;
|
5967
6122
|
id2.mid = pg;
|
5968
6123
|
id2.mptr = np;
|
5969
|
-
mdb_mid2l_insert(mc->mc_txn->mt_u.dirty_list, &id2);
|
6124
|
+
rc2 = mdb_mid2l_insert(mc->mc_txn->mt_u.dirty_list, &id2);
|
6125
|
+
mdb_cassert(mc, rc2 == 0);
|
5970
6126
|
if (!(flags & MDB_RESERVE)) {
|
5971
6127
|
/* Copy end of page, adjusting alignment so
|
5972
6128
|
* compiler may copy words instead of bytes.
|
@@ -5984,7 +6140,7 @@ current:
|
|
5984
6140
|
data->mv_data = METADATA(omp);
|
5985
6141
|
else
|
5986
6142
|
memcpy(METADATA(omp), data->mv_data, data->mv_size);
|
5987
|
-
|
6143
|
+
return MDB_SUCCESS;
|
5988
6144
|
}
|
5989
6145
|
}
|
5990
6146
|
if ((rc2 = mdb_ovpage_free(mc, omp)) != MDB_SUCCESS)
|
@@ -5996,17 +6152,13 @@ current:
|
|
5996
6152
|
*/
|
5997
6153
|
if (F_ISSET(flags, MDB_RESERVE))
|
5998
6154
|
data->mv_data = olddata.mv_data;
|
5999
|
-
else if (
|
6155
|
+
else if (!(mc->mc_flags & C_SUB))
|
6000
6156
|
memcpy(olddata.mv_data, data->mv_data, data->mv_size);
|
6001
6157
|
else
|
6002
6158
|
memcpy(NODEKEY(leaf), key->mv_data, key->mv_size);
|
6003
|
-
|
6159
|
+
return MDB_SUCCESS;
|
6004
6160
|
}
|
6005
|
-
mdb_node_del(mc
|
6006
|
-
mc->mc_db->md_entries--;
|
6007
|
-
} else {
|
6008
|
-
DPRINTF(("inserting key at index %i", mc->mc_ki[mc->mc_top]));
|
6009
|
-
insert = 1;
|
6161
|
+
mdb_node_del(mc, 0);
|
6010
6162
|
}
|
6011
6163
|
|
6012
6164
|
rdata = data;
|
@@ -6016,14 +6168,14 @@ new_sub:
|
|
6016
6168
|
nsize = IS_LEAF2(mc->mc_pg[mc->mc_top]) ? key->mv_size : mdb_leaf_size(env, key, rdata);
|
6017
6169
|
if (SIZELEFT(mc->mc_pg[mc->mc_top]) < nsize) {
|
6018
6170
|
if (( flags & (F_DUPDATA|F_SUBDATA)) == F_DUPDATA )
|
6019
|
-
nflags &= ~MDB_APPEND;
|
6020
|
-
if (!
|
6171
|
+
nflags &= ~MDB_APPEND; /* sub-page may need room to grow */
|
6172
|
+
if (!insert_key)
|
6021
6173
|
nflags |= MDB_SPLIT_REPLACE;
|
6022
6174
|
rc = mdb_page_split(mc, key, rdata, P_INVALID, nflags);
|
6023
6175
|
} else {
|
6024
6176
|
/* There is room already in this leaf page. */
|
6025
6177
|
rc = mdb_node_add(mc, mc->mc_ki[mc->mc_top], key, rdata, 0, nflags);
|
6026
|
-
if (rc == 0 &&
|
6178
|
+
if (rc == 0 && insert_key) {
|
6027
6179
|
/* Adjust other cursors pointing to mp */
|
6028
6180
|
MDB_cursor *m2, *m3;
|
6029
6181
|
MDB_dbi dbi = mc->mc_dbi;
|
@@ -6043,9 +6195,7 @@ new_sub:
|
|
6043
6195
|
}
|
6044
6196
|
}
|
6045
6197
|
|
6046
|
-
if (rc
|
6047
|
-
mc->mc_txn->mt_flags |= MDB_TXN_ERROR;
|
6048
|
-
else {
|
6198
|
+
if (rc == MDB_SUCCESS) {
|
6049
6199
|
/* Now store the actual data in the child DB. Note that we're
|
6050
6200
|
* storing the user data in the keys field, so there are strict
|
6051
6201
|
* size limits on dupdata. The actual data fields of the child
|
@@ -6053,6 +6203,7 @@ new_sub:
|
|
6053
6203
|
*/
|
6054
6204
|
if (do_sub) {
|
6055
6205
|
int xflags;
|
6206
|
+
size_t ecount;
|
6056
6207
|
put_sub:
|
6057
6208
|
xdata.mv_size = 0;
|
6058
6209
|
xdata.mv_data = "";
|
@@ -6068,7 +6219,7 @@ put_sub:
|
|
6068
6219
|
if (dkey.mv_size) {
|
6069
6220
|
rc = mdb_cursor_put(&mc->mc_xcursor->mx_cursor, &dkey, &xdata, xflags);
|
6070
6221
|
if (rc)
|
6071
|
-
|
6222
|
+
goto bad_sub;
|
6072
6223
|
{
|
6073
6224
|
/* Adjust other cursors pointing to mp */
|
6074
6225
|
MDB_cursor *m2;
|
@@ -6086,6 +6237,7 @@ put_sub:
|
|
6086
6237
|
/* we've done our job */
|
6087
6238
|
dkey.mv_size = 0;
|
6088
6239
|
}
|
6240
|
+
ecount = mc->mc_xcursor->mx_db.md_entries;
|
6089
6241
|
if (flags & MDB_APPENDDUP)
|
6090
6242
|
xflags |= MDB_APPEND;
|
6091
6243
|
rc = mdb_cursor_put(&mc->mc_xcursor->mx_cursor, data, &xdata, xflags);
|
@@ -6093,31 +6245,39 @@ put_sub:
|
|
6093
6245
|
void *db = NODEDATA(leaf);
|
6094
6246
|
memcpy(db, &mc->mc_xcursor->mx_db, sizeof(MDB_db));
|
6095
6247
|
}
|
6248
|
+
insert_data = mc->mc_xcursor->mx_db.md_entries - ecount;
|
6096
6249
|
}
|
6097
|
-
/*
|
6098
|
-
|
6099
|
-
*/
|
6100
|
-
if (!rc && !(flags & MDB_CURRENT))
|
6250
|
+
/* Increment count unless we just replaced an existing item. */
|
6251
|
+
if (insert_data)
|
6101
6252
|
mc->mc_db->md_entries++;
|
6253
|
+
if (insert_key) {
|
6254
|
+
/* Invalidate txn if we created an empty sub-DB */
|
6255
|
+
if (rc)
|
6256
|
+
goto bad_sub;
|
6257
|
+
/* If we succeeded and the key didn't exist before,
|
6258
|
+
* make sure the cursor is marked valid.
|
6259
|
+
*/
|
6260
|
+
mc->mc_flags |= C_INITIALIZED;
|
6261
|
+
}
|
6262
|
+
next_sub:
|
6102
6263
|
if (flags & MDB_MULTIPLE) {
|
6103
6264
|
if (!rc) {
|
6104
|
-
next_mult:
|
6105
6265
|
mcount++;
|
6106
6266
|
/* let caller know how many succeeded, if any */
|
6107
6267
|
data[1].mv_size = mcount;
|
6108
6268
|
if (mcount < dcount) {
|
6109
6269
|
data[0].mv_data = (char *)data[0].mv_data + data[0].mv_size;
|
6270
|
+
insert_key = insert_data = 0;
|
6110
6271
|
goto more;
|
6111
6272
|
}
|
6112
6273
|
}
|
6113
6274
|
}
|
6275
|
+
return rc;
|
6276
|
+
bad_sub:
|
6277
|
+
if (rc == MDB_KEYEXIST) /* should not happen, we deleted that item */
|
6278
|
+
rc = MDB_CORRUPTED;
|
6114
6279
|
}
|
6115
|
-
|
6116
|
-
/* If we succeeded and the key didn't exist before, make sure
|
6117
|
-
* the cursor is marked valid.
|
6118
|
-
*/
|
6119
|
-
if (!rc && insert)
|
6120
|
-
mc->mc_flags |= C_INITIALIZED;
|
6280
|
+
mc->mc_txn->mt_flags |= MDB_TXN_ERROR;
|
6121
6281
|
return rc;
|
6122
6282
|
}
|
6123
6283
|
|
@@ -6145,14 +6305,21 @@ mdb_cursor_del(MDB_cursor *mc, unsigned int flags)
|
|
6145
6305
|
return rc;
|
6146
6306
|
|
6147
6307
|
mp = mc->mc_pg[mc->mc_top];
|
6308
|
+
if (IS_LEAF2(mp))
|
6309
|
+
goto del_key;
|
6148
6310
|
leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
|
6149
6311
|
|
6150
|
-
if (
|
6151
|
-
if (
|
6312
|
+
if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
|
6313
|
+
if (flags & MDB_NODUPDATA) {
|
6314
|
+
/* mdb_cursor_del0() will subtract the final entry */
|
6315
|
+
mc->mc_db->md_entries -= mc->mc_xcursor->mx_db.md_entries - 1;
|
6316
|
+
} else {
|
6152
6317
|
if (!F_ISSET(leaf->mn_flags, F_SUBDATA)) {
|
6153
6318
|
mc->mc_xcursor->mx_cursor.mc_pg[0] = NODEDATA(leaf);
|
6154
6319
|
}
|
6155
6320
|
rc = mdb_cursor_del(&mc->mc_xcursor->mx_cursor, MDB_NOSPILL);
|
6321
|
+
if (rc)
|
6322
|
+
return rc;
|
6156
6323
|
/* If sub-DB still has entries, we're done */
|
6157
6324
|
if (mc->mc_xcursor->mx_db.md_entries) {
|
6158
6325
|
if (leaf->mn_flags & F_SUBDATA) {
|
@@ -6183,14 +6350,28 @@ mdb_cursor_del(MDB_cursor *mc, unsigned int flags)
|
|
6183
6350
|
if (leaf->mn_flags & F_SUBDATA) {
|
6184
6351
|
/* add all the child DB's pages to the free list */
|
6185
6352
|
rc = mdb_drop0(&mc->mc_xcursor->mx_cursor, 0);
|
6186
|
-
if (rc
|
6187
|
-
|
6188
|
-
mc->mc_xcursor->mx_db.md_entries;
|
6189
|
-
}
|
6353
|
+
if (rc)
|
6354
|
+
goto fail;
|
6190
6355
|
}
|
6191
6356
|
}
|
6192
6357
|
|
6193
|
-
|
6358
|
+
/* add overflow pages to free list */
|
6359
|
+
if (F_ISSET(leaf->mn_flags, F_BIGDATA)) {
|
6360
|
+
MDB_page *omp;
|
6361
|
+
pgno_t pg;
|
6362
|
+
|
6363
|
+
memcpy(&pg, NODEDATA(leaf), sizeof(pg));
|
6364
|
+
if ((rc = mdb_page_get(mc->mc_txn, pg, &omp, NULL)) ||
|
6365
|
+
(rc = mdb_ovpage_free(mc, omp)))
|
6366
|
+
goto fail;
|
6367
|
+
}
|
6368
|
+
|
6369
|
+
del_key:
|
6370
|
+
return mdb_cursor_del0(mc);
|
6371
|
+
|
6372
|
+
fail:
|
6373
|
+
mc->mc_txn->mt_flags |= MDB_TXN_ERROR;
|
6374
|
+
return rc;
|
6194
6375
|
}
|
6195
6376
|
|
6196
6377
|
/** Allocate and initialize new pages for a database.
|
@@ -6245,13 +6426,12 @@ mdb_leaf_size(MDB_env *env, MDB_val *key, MDB_val *data)
|
|
6245
6426
|
size_t sz;
|
6246
6427
|
|
6247
6428
|
sz = LEAFSIZE(key, data);
|
6248
|
-
if (sz
|
6429
|
+
if (sz > env->me_nodemax) {
|
6249
6430
|
/* put on overflow page */
|
6250
6431
|
sz -= data->mv_size - sizeof(pgno_t);
|
6251
6432
|
}
|
6252
|
-
sz += sz & 1;
|
6253
6433
|
|
6254
|
-
return sz + sizeof(indx_t);
|
6434
|
+
return EVEN(sz + sizeof(indx_t));
|
6255
6435
|
}
|
6256
6436
|
|
6257
6437
|
/** Calculate the size of a branch node.
|
@@ -6270,7 +6450,7 @@ mdb_branch_size(MDB_env *env, MDB_val *key)
|
|
6270
6450
|
size_t sz;
|
6271
6451
|
|
6272
6452
|
sz = INDXSIZE(key);
|
6273
|
-
if (sz
|
6453
|
+
if (sz > env->me_nodemax) {
|
6274
6454
|
/* put on overflow page */
|
6275
6455
|
/* not implemented */
|
6276
6456
|
/* sz -= key->size - sizeof(pgno_t); */
|
@@ -6307,12 +6487,12 @@ mdb_node_add(MDB_cursor *mc, indx_t indx,
|
|
6307
6487
|
MDB_page *ofp = NULL; /* overflow page */
|
6308
6488
|
DKBUF;
|
6309
6489
|
|
6310
|
-
|
6490
|
+
mdb_cassert(mc, mp->mp_upper >= mp->mp_lower);
|
6311
6491
|
|
6312
6492
|
DPRINTF(("add to %s %spage %"Z"u index %i, data size %"Z"u key size %"Z"u [%s]",
|
6313
6493
|
IS_LEAF(mp) ? "leaf" : "branch",
|
6314
6494
|
IS_SUBP(mp) ? "sub-" : "",
|
6315
|
-
|
6495
|
+
mdb_dbg_pgno(mp), indx, data ? data->mv_size : 0,
|
6316
6496
|
key ? key->mv_size : 0, key ? DKEY(key) : "null"));
|
6317
6497
|
|
6318
6498
|
if (IS_LEAF2(mp)) {
|
@@ -6335,17 +6515,17 @@ mdb_node_add(MDB_cursor *mc, indx_t indx,
|
|
6335
6515
|
if (key != NULL)
|
6336
6516
|
node_size += key->mv_size;
|
6337
6517
|
if (IS_LEAF(mp)) {
|
6338
|
-
|
6518
|
+
mdb_cassert(mc, data);
|
6339
6519
|
if (F_ISSET(flags, F_BIGDATA)) {
|
6340
6520
|
/* Data already on overflow page. */
|
6341
6521
|
node_size += sizeof(pgno_t);
|
6342
|
-
} else if (node_size + data->mv_size
|
6522
|
+
} else if (node_size + data->mv_size > mc->mc_txn->mt_env->me_nodemax) {
|
6343
6523
|
int ovpages = OVPAGES(data->mv_size, mc->mc_txn->mt_env->me_psize);
|
6344
6524
|
int rc;
|
6345
6525
|
/* Put data on overflow page. */
|
6346
6526
|
DPRINTF(("data size is %"Z"u, node would be %"Z"u, put data on overflow page",
|
6347
6527
|
data->mv_size, node_size+data->mv_size));
|
6348
|
-
node_size
|
6528
|
+
node_size = EVEN(node_size + sizeof(pgno_t));
|
6349
6529
|
if ((ssize_t)node_size > room)
|
6350
6530
|
goto full;
|
6351
6531
|
if ((rc = mdb_page_new(mc, P_OVERFLOW, ovpages, &ofp)))
|
@@ -6357,7 +6537,7 @@ mdb_node_add(MDB_cursor *mc, indx_t indx,
|
|
6357
6537
|
node_size += data->mv_size;
|
6358
6538
|
}
|
6359
6539
|
}
|
6360
|
-
node_size
|
6540
|
+
node_size = EVEN(node_size);
|
6361
6541
|
if ((ssize_t)node_size > room)
|
6362
6542
|
goto full;
|
6363
6543
|
|
@@ -6368,7 +6548,7 @@ update:
|
|
6368
6548
|
|
6369
6549
|
/* Adjust free space offsets. */
|
6370
6550
|
ofs = mp->mp_upper - node_size;
|
6371
|
-
|
6551
|
+
mdb_cassert(mc, ofs >= mp->mp_lower + sizeof(indx_t));
|
6372
6552
|
mp->mp_ptrs[indx] = ofs;
|
6373
6553
|
mp->mp_upper = ofs;
|
6374
6554
|
mp->mp_lower += sizeof(indx_t);
|
@@ -6386,7 +6566,7 @@ update:
|
|
6386
6566
|
memcpy(NODEKEY(node), key->mv_data, key->mv_size);
|
6387
6567
|
|
6388
6568
|
if (IS_LEAF(mp)) {
|
6389
|
-
|
6569
|
+
mdb_cassert(mc, key);
|
6390
6570
|
if (ofp == NULL) {
|
6391
6571
|
if (F_ISSET(flags, F_BIGDATA))
|
6392
6572
|
memcpy(node->mn_data + key->mv_size, data->mv_data,
|
@@ -6410,38 +6590,35 @@ update:
|
|
6410
6590
|
|
6411
6591
|
full:
|
6412
6592
|
DPRINTF(("not enough room in page %"Z"u, got %u ptrs",
|
6413
|
-
mp
|
6593
|
+
mdb_dbg_pgno(mp), NUMKEYS(mp)));
|
6414
6594
|
DPRINTF(("upper-lower = %u - %u = %"Z"d", mp->mp_upper,mp->mp_lower,room));
|
6415
6595
|
DPRINTF(("node size = %"Z"u", node_size));
|
6596
|
+
mc->mc_txn->mt_flags |= MDB_TXN_ERROR;
|
6416
6597
|
return MDB_PAGE_FULL;
|
6417
6598
|
}
|
6418
6599
|
|
6419
6600
|
/** Delete the specified node from a page.
|
6420
|
-
* @param[in]
|
6421
|
-
* @param[in] indx The index of the node to delete.
|
6601
|
+
* @param[in] mc Cursor pointing to the node to delete.
|
6422
6602
|
* @param[in] ksize The size of a node. Only used if the page is
|
6423
6603
|
* part of a #MDB_DUPFIXED database.
|
6424
6604
|
*/
|
6425
6605
|
static void
|
6426
|
-
mdb_node_del(
|
6606
|
+
mdb_node_del(MDB_cursor *mc, int ksize)
|
6427
6607
|
{
|
6608
|
+
MDB_page *mp = mc->mc_pg[mc->mc_top];
|
6609
|
+
indx_t indx = mc->mc_ki[mc->mc_top];
|
6428
6610
|
unsigned int sz;
|
6429
6611
|
indx_t i, j, numkeys, ptr;
|
6430
6612
|
MDB_node *node;
|
6431
6613
|
char *base;
|
6432
6614
|
|
6433
|
-
#if MDB_DEBUG
|
6434
|
-
{
|
6435
|
-
pgno_t pgno;
|
6436
|
-
COPY_PGNO(pgno, mp->mp_pgno);
|
6437
6615
|
DPRINTF(("delete node %u on %s page %"Z"u", indx,
|
6438
|
-
IS_LEAF(mp) ? "leaf" : "branch",
|
6439
|
-
|
6440
|
-
|
6441
|
-
assert(indx < NUMKEYS(mp));
|
6616
|
+
IS_LEAF(mp) ? "leaf" : "branch", mdb_dbg_pgno(mp)));
|
6617
|
+
numkeys = NUMKEYS(mp);
|
6618
|
+
mdb_cassert(mc, indx < numkeys);
|
6442
6619
|
|
6443
6620
|
if (IS_LEAF2(mp)) {
|
6444
|
-
int x =
|
6621
|
+
int x = numkeys - 1 - indx;
|
6445
6622
|
base = LEAF2KEY(mp, indx, ksize);
|
6446
6623
|
if (x)
|
6447
6624
|
memmove(base, base + ksize, x * ksize);
|
@@ -6458,10 +6635,9 @@ mdb_node_del(MDB_page *mp, indx_t indx, int ksize)
|
|
6458
6635
|
else
|
6459
6636
|
sz += NODEDSZ(node);
|
6460
6637
|
}
|
6461
|
-
sz
|
6638
|
+
sz = EVEN(sz);
|
6462
6639
|
|
6463
6640
|
ptr = mp->mp_ptrs[indx];
|
6464
|
-
numkeys = NUMKEYS(mp);
|
6465
6641
|
for (i = j = 0; i < numkeys; i++) {
|
6466
6642
|
if (i != indx) {
|
6467
6643
|
mp->mp_ptrs[j] = mp->mp_ptrs[i];
|
@@ -6488,25 +6664,22 @@ mdb_node_shrink(MDB_page *mp, indx_t indx)
|
|
6488
6664
|
MDB_node *node;
|
6489
6665
|
MDB_page *sp, *xp;
|
6490
6666
|
char *base;
|
6491
|
-
int
|
6492
|
-
int delta;
|
6667
|
+
int nsize, delta;
|
6493
6668
|
indx_t i, numkeys, ptr;
|
6494
6669
|
|
6495
6670
|
node = NODEPTR(mp, indx);
|
6496
6671
|
sp = (MDB_page *)NODEDATA(node);
|
6497
|
-
|
6498
|
-
|
6499
|
-
delta = sp->mp_upper - sp->mp_lower;
|
6500
|
-
SETDSZ(node, osize - delta);
|
6672
|
+
delta = SIZELEFT(sp);
|
6501
6673
|
xp = (MDB_page *)((char *)sp + delta);
|
6502
6674
|
|
6503
6675
|
/* shift subpage upward */
|
6504
6676
|
if (IS_LEAF2(sp)) {
|
6505
6677
|
nsize = NUMKEYS(sp) * sp->mp_pad;
|
6678
|
+
if (nsize & 1)
|
6679
|
+
return; /* do not make the node uneven-sized */
|
6506
6680
|
memmove(METADATA(xp), METADATA(sp), nsize);
|
6507
6681
|
} else {
|
6508
6682
|
int i;
|
6509
|
-
nsize = osize - sp->mp_upper;
|
6510
6683
|
numkeys = NUMKEYS(sp);
|
6511
6684
|
for (i=numkeys-1; i>=0; i--)
|
6512
6685
|
xp->mp_ptrs[i] = sp->mp_ptrs[i] - delta;
|
@@ -6517,6 +6690,9 @@ mdb_node_shrink(MDB_page *mp, indx_t indx)
|
|
6517
6690
|
xp->mp_pad = sp->mp_pad;
|
6518
6691
|
COPY_PGNO(xp->mp_pgno, mp->mp_pgno);
|
6519
6692
|
|
6693
|
+
nsize = NODEDSZ(node) - delta;
|
6694
|
+
SETDSZ(node, nsize);
|
6695
|
+
|
6520
6696
|
/* shift lower nodes upward */
|
6521
6697
|
ptr = mp->mp_ptrs[indx];
|
6522
6698
|
numkeys = NUMKEYS(mp);
|
@@ -6604,11 +6780,7 @@ mdb_xcursor_init1(MDB_cursor *mc, MDB_node *node)
|
|
6604
6780
|
mx->mx_dbflag = DB_VALID|DB_DIRTY; /* DB_DIRTY guides mdb_cursor_touch */
|
6605
6781
|
#if UINT_MAX < SIZE_MAX
|
6606
6782
|
if (mx->mx_dbx.md_cmp == mdb_cmp_int && mx->mx_db.md_pad == sizeof(size_t))
|
6607
|
-
|
6608
|
-
mx->mx_dbx.md_cmp = mdb_cmp_long;
|
6609
|
-
#else
|
6610
|
-
mx->mx_dbx.md_cmp = mdb_cmp_cint;
|
6611
|
-
#endif
|
6783
|
+
mx->mx_dbx.md_cmp = mdb_cmp_clong;
|
6612
6784
|
#endif
|
6613
6785
|
}
|
6614
6786
|
|
@@ -6628,7 +6800,7 @@ mdb_cursor_init(MDB_cursor *mc, MDB_txn *txn, MDB_dbi dbi, MDB_xcursor *mx)
|
|
6628
6800
|
mc->mc_pg[0] = 0;
|
6629
6801
|
mc->mc_flags = 0;
|
6630
6802
|
if (txn->mt_dbs[dbi].md_flags & MDB_DUPSORT) {
|
6631
|
-
|
6803
|
+
mdb_tassert(txn, mx != NULL);
|
6632
6804
|
mc->mc_xcursor = mx;
|
6633
6805
|
mdb_xcursor_init0(mc);
|
6634
6806
|
} else {
|
@@ -6645,7 +6817,7 @@ mdb_cursor_open(MDB_txn *txn, MDB_dbi dbi, MDB_cursor **ret)
|
|
6645
6817
|
MDB_cursor *mc;
|
6646
6818
|
size_t size = sizeof(MDB_cursor);
|
6647
6819
|
|
6648
|
-
if (
|
6820
|
+
if (!ret || !TXN_DBI_EXIST(txn, dbi))
|
6649
6821
|
return EINVAL;
|
6650
6822
|
|
6651
6823
|
if (txn->mt_flags & MDB_TXN_ERROR)
|
@@ -6677,12 +6849,15 @@ mdb_cursor_open(MDB_txn *txn, MDB_dbi dbi, MDB_cursor **ret)
|
|
6677
6849
|
int
|
6678
6850
|
mdb_cursor_renew(MDB_txn *txn, MDB_cursor *mc)
|
6679
6851
|
{
|
6680
|
-
if (
|
6852
|
+
if (!mc || !TXN_DBI_EXIST(txn, mc->mc_dbi))
|
6681
6853
|
return EINVAL;
|
6682
6854
|
|
6683
6855
|
if ((mc->mc_flags & C_UNTRACK) || txn->mt_cursors)
|
6684
6856
|
return EINVAL;
|
6685
6857
|
|
6858
|
+
if (txn->mt_flags & MDB_TXN_ERROR)
|
6859
|
+
return MDB_BAD_TXN;
|
6860
|
+
|
6686
6861
|
mdb_cursor_init(mc, txn, mc->mc_dbi, mc->mc_xcursor);
|
6687
6862
|
return MDB_SUCCESS;
|
6688
6863
|
}
|
@@ -6699,6 +6874,9 @@ mdb_cursor_count(MDB_cursor *mc, size_t *countp)
|
|
6699
6874
|
if (mc->mc_xcursor == NULL)
|
6700
6875
|
return MDB_INCOMPATIBLE;
|
6701
6876
|
|
6877
|
+
if (mc->mc_txn->mt_flags & MDB_TXN_ERROR)
|
6878
|
+
return MDB_BAD_TXN;
|
6879
|
+
|
6702
6880
|
leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
|
6703
6881
|
if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) {
|
6704
6882
|
*countp = 1;
|
@@ -6736,11 +6914,10 @@ mdb_cursor_txn(MDB_cursor *mc)
|
|
6736
6914
|
MDB_dbi
|
6737
6915
|
mdb_cursor_dbi(MDB_cursor *mc)
|
6738
6916
|
{
|
6739
|
-
assert(mc != NULL);
|
6740
6917
|
return mc->mc_dbi;
|
6741
6918
|
}
|
6742
6919
|
|
6743
|
-
/** Replace the key for a node with a new key.
|
6920
|
+
/** Replace the key for a branch node with a new key.
|
6744
6921
|
* @param[in] mc Cursor pointing to the node to operate on.
|
6745
6922
|
* @param[in] key The new key to use.
|
6746
6923
|
* @return 0 on success, non-zero on failure.
|
@@ -6752,7 +6929,7 @@ mdb_update_key(MDB_cursor *mc, MDB_val *key)
|
|
6752
6929
|
MDB_node *node;
|
6753
6930
|
char *base;
|
6754
6931
|
size_t len;
|
6755
|
-
int
|
6932
|
+
int delta, ksize, oksize;
|
6756
6933
|
indx_t ptr, i, numkeys, indx;
|
6757
6934
|
DKBUF;
|
6758
6935
|
|
@@ -6763,7 +6940,7 @@ mdb_update_key(MDB_cursor *mc, MDB_val *key)
|
|
6763
6940
|
#if MDB_DEBUG
|
6764
6941
|
{
|
6765
6942
|
MDB_val k2;
|
6766
|
-
char kbuf2[
|
6943
|
+
char kbuf2[DKBUF_MAXKEYSIZE*2+1];
|
6767
6944
|
k2.mv_data = NODEKEY(node);
|
6768
6945
|
k2.mv_size = node->mn_ksize;
|
6769
6946
|
DPRINTF(("update key %u (ofs %u) [%s] to [%s] on page %"Z"u",
|
@@ -6774,19 +6951,19 @@ mdb_update_key(MDB_cursor *mc, MDB_val *key)
|
|
6774
6951
|
}
|
6775
6952
|
#endif
|
6776
6953
|
|
6777
|
-
|
6954
|
+
/* Sizes must be 2-byte aligned. */
|
6955
|
+
ksize = EVEN(key->mv_size);
|
6956
|
+
oksize = EVEN(node->mn_ksize);
|
6957
|
+
delta = ksize - oksize;
|
6778
6958
|
|
6779
|
-
/*
|
6780
|
-
* shorter by 1, the shift will be skipped.
|
6781
|
-
*/
|
6782
|
-
delta += (delta & 1);
|
6959
|
+
/* Shift node contents if EVEN(key length) changed. */
|
6783
6960
|
if (delta) {
|
6784
6961
|
if (delta > 0 && SIZELEFT(mp) < delta) {
|
6785
6962
|
pgno_t pgno;
|
6786
6963
|
/* not enough space left, do a delete and split */
|
6787
6964
|
DPRINTF(("Not enough room, delta = %d, splitting...", delta));
|
6788
6965
|
pgno = NODEPGNO(node);
|
6789
|
-
mdb_node_del(mc
|
6966
|
+
mdb_node_del(mc, 0);
|
6790
6967
|
return mdb_page_split(mc, key, NULL, pgno, MDB_SPLIT_REPLACE);
|
6791
6968
|
}
|
6792
6969
|
|
@@ -6805,7 +6982,7 @@ mdb_update_key(MDB_cursor *mc, MDB_val *key)
|
|
6805
6982
|
}
|
6806
6983
|
|
6807
6984
|
/* But even if no shift was needed, update ksize */
|
6808
|
-
if (
|
6985
|
+
if (node->mn_ksize != key->mv_size)
|
6809
6986
|
node->mn_ksize = key->mv_size;
|
6810
6987
|
|
6811
6988
|
if (key->mv_size)
|
@@ -6837,7 +7014,6 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst)
|
|
6837
7014
|
return rc;
|
6838
7015
|
|
6839
7016
|
if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) {
|
6840
|
-
srcnode = NODEPTR(csrc->mc_pg[csrc->mc_top], 0); /* fake */
|
6841
7017
|
key.mv_size = csrc->mc_db->md_pad;
|
6842
7018
|
key.mv_data = LEAF2KEY(csrc->mc_pg[csrc->mc_top], csrc->mc_ki[csrc->mc_top], key.mv_size);
|
6843
7019
|
data.mv_size = 0;
|
@@ -6846,14 +7022,16 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst)
|
|
6846
7022
|
flags = 0;
|
6847
7023
|
} else {
|
6848
7024
|
srcnode = NODEPTR(csrc->mc_pg[csrc->mc_top], csrc->mc_ki[csrc->mc_top]);
|
6849
|
-
|
7025
|
+
mdb_cassert(csrc, !((size_t)srcnode & 1));
|
6850
7026
|
srcpg = NODEPGNO(srcnode);
|
6851
7027
|
flags = srcnode->mn_flags;
|
6852
7028
|
if (csrc->mc_ki[csrc->mc_top] == 0 && IS_BRANCH(csrc->mc_pg[csrc->mc_top])) {
|
6853
7029
|
unsigned int snum = csrc->mc_snum;
|
6854
7030
|
MDB_node *s2;
|
6855
7031
|
/* must find the lowest key below src */
|
6856
|
-
mdb_page_search_lowest(csrc);
|
7032
|
+
rc = mdb_page_search_lowest(csrc);
|
7033
|
+
if (rc)
|
7034
|
+
return rc;
|
6857
7035
|
if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) {
|
6858
7036
|
key.mv_size = csrc->mc_db->md_pad;
|
6859
7037
|
key.mv_data = LEAF2KEY(csrc->mc_pg[csrc->mc_top], 0, key.mv_size);
|
@@ -6876,7 +7054,9 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst)
|
|
6876
7054
|
MDB_node *s2;
|
6877
7055
|
MDB_val bkey;
|
6878
7056
|
/* must find the lowest key below dst */
|
6879
|
-
mdb_page_search_lowest(cdst);
|
7057
|
+
rc = mdb_page_search_lowest(cdst);
|
7058
|
+
if (rc)
|
7059
|
+
return rc;
|
6880
7060
|
if (IS_LEAF2(cdst->mc_pg[cdst->mc_top])) {
|
6881
7061
|
bkey.mv_size = cdst->mc_db->md_pad;
|
6882
7062
|
bkey.mv_data = LEAF2KEY(cdst->mc_pg[cdst->mc_top], 0, bkey.mv_size);
|
@@ -6909,7 +7089,7 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst)
|
|
6909
7089
|
|
6910
7090
|
/* Delete the node from the source page.
|
6911
7091
|
*/
|
6912
|
-
mdb_node_del(csrc
|
7092
|
+
mdb_node_del(csrc, key.mv_size);
|
6913
7093
|
|
6914
7094
|
{
|
6915
7095
|
/* Adjust other cursors pointing to mp */
|
@@ -6957,7 +7137,7 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst)
|
|
6957
7137
|
csrc->mc_ki[csrc->mc_top] = 0;
|
6958
7138
|
rc = mdb_update_key(csrc, &nullkey);
|
6959
7139
|
csrc->mc_ki[csrc->mc_top] = ix;
|
6960
|
-
|
7140
|
+
mdb_cassert(csrc, rc == MDB_SUCCESS);
|
6961
7141
|
}
|
6962
7142
|
}
|
6963
7143
|
|
@@ -6985,7 +7165,7 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst)
|
|
6985
7165
|
cdst->mc_ki[cdst->mc_top] = 0;
|
6986
7166
|
rc = mdb_update_key(cdst, &nullkey);
|
6987
7167
|
cdst->mc_ki[cdst->mc_top] = ix;
|
6988
|
-
|
7168
|
+
mdb_cassert(csrc, rc == MDB_SUCCESS);
|
6989
7169
|
}
|
6990
7170
|
}
|
6991
7171
|
|
@@ -6998,6 +7178,7 @@ mdb_node_move(MDB_cursor *csrc, MDB_cursor *cdst)
|
|
6998
7178
|
* the \b csrc page will be freed.
|
6999
7179
|
* @param[in] csrc Cursor pointing to the source page.
|
7000
7180
|
* @param[in] cdst Cursor pointing to the destination page.
|
7181
|
+
* @return 0 on success, non-zero on failure.
|
7001
7182
|
*/
|
7002
7183
|
static int
|
7003
7184
|
mdb_page_merge(MDB_cursor *csrc, MDB_cursor *cdst)
|
@@ -7011,8 +7192,8 @@ mdb_page_merge(MDB_cursor *csrc, MDB_cursor *cdst)
|
|
7011
7192
|
DPRINTF(("merging page %"Z"u into %"Z"u", csrc->mc_pg[csrc->mc_top]->mp_pgno,
|
7012
7193
|
cdst->mc_pg[cdst->mc_top]->mp_pgno));
|
7013
7194
|
|
7014
|
-
|
7015
|
-
|
7195
|
+
mdb_cassert(csrc, csrc->mc_snum > 1); /* can't merge root page */
|
7196
|
+
mdb_cassert(csrc, cdst->mc_snum > 1);
|
7016
7197
|
|
7017
7198
|
/* Mark dst as dirty. */
|
7018
7199
|
if ((rc = mdb_page_touch(cdst)))
|
@@ -7037,7 +7218,9 @@ mdb_page_merge(MDB_cursor *csrc, MDB_cursor *cdst)
|
|
7037
7218
|
unsigned int snum = csrc->mc_snum;
|
7038
7219
|
MDB_node *s2;
|
7039
7220
|
/* must find the lowest key below src */
|
7040
|
-
mdb_page_search_lowest(csrc);
|
7221
|
+
rc = mdb_page_search_lowest(csrc);
|
7222
|
+
if (rc)
|
7223
|
+
return rc;
|
7041
7224
|
if (IS_LEAF2(csrc->mc_pg[csrc->mc_top])) {
|
7042
7225
|
key.mv_size = csrc->mc_db->md_pad;
|
7043
7226
|
key.mv_data = LEAF2KEY(csrc->mc_pg[csrc->mc_top], 0, key.mv_size);
|
@@ -7067,15 +7250,17 @@ mdb_page_merge(MDB_cursor *csrc, MDB_cursor *cdst)
|
|
7067
7250
|
|
7068
7251
|
/* Unlink the src page from parent and add to free list.
|
7069
7252
|
*/
|
7070
|
-
|
7071
|
-
|
7253
|
+
csrc->mc_top--;
|
7254
|
+
mdb_node_del(csrc, 0);
|
7255
|
+
if (csrc->mc_ki[csrc->mc_top] == 0) {
|
7072
7256
|
key.mv_size = 0;
|
7073
|
-
csrc->mc_top--;
|
7074
7257
|
rc = mdb_update_key(csrc, &key);
|
7075
|
-
|
7076
|
-
|
7258
|
+
if (rc) {
|
7259
|
+
csrc->mc_top++;
|
7077
7260
|
return rc;
|
7261
|
+
}
|
7078
7262
|
}
|
7263
|
+
csrc->mc_top++;
|
7079
7264
|
|
7080
7265
|
rc = mdb_midl_append(&csrc->mc_txn->mt_free_pgs,
|
7081
7266
|
csrc->mc_pg[csrc->mc_top]->mp_pgno);
|
@@ -7104,9 +7289,18 @@ mdb_page_merge(MDB_cursor *csrc, MDB_cursor *cdst)
|
|
7104
7289
|
}
|
7105
7290
|
}
|
7106
7291
|
}
|
7107
|
-
|
7108
|
-
|
7109
|
-
|
7292
|
+
{
|
7293
|
+
unsigned int snum = cdst->mc_snum;
|
7294
|
+
uint16_t depth = cdst->mc_db->md_depth;
|
7295
|
+
mdb_cursor_pop(cdst);
|
7296
|
+
rc = mdb_rebalance(cdst);
|
7297
|
+
/* Did the tree shrink? */
|
7298
|
+
if (depth > cdst->mc_db->md_depth)
|
7299
|
+
snum--;
|
7300
|
+
cdst->mc_snum = snum;
|
7301
|
+
cdst->mc_top = snum-1;
|
7302
|
+
}
|
7303
|
+
return rc;
|
7110
7304
|
}
|
7111
7305
|
|
7112
7306
|
/** Copy the contents of a cursor.
|
@@ -7144,27 +7338,18 @@ mdb_rebalance(MDB_cursor *mc)
|
|
7144
7338
|
int rc;
|
7145
7339
|
unsigned int ptop, minkeys;
|
7146
7340
|
MDB_cursor mn;
|
7341
|
+
indx_t oldki;
|
7147
7342
|
|
7148
7343
|
minkeys = 1 + (IS_BRANCH(mc->mc_pg[mc->mc_top]));
|
7149
|
-
#if MDB_DEBUG
|
7150
|
-
{
|
7151
|
-
pgno_t pgno;
|
7152
|
-
COPY_PGNO(pgno, mc->mc_pg[mc->mc_top]->mp_pgno);
|
7153
7344
|
DPRINTF(("rebalancing %s page %"Z"u (has %u keys, %.1f%% full)",
|
7154
7345
|
IS_LEAF(mc->mc_pg[mc->mc_top]) ? "leaf" : "branch",
|
7155
|
-
|
7346
|
+
mdb_dbg_pgno(mc->mc_pg[mc->mc_top]), NUMKEYS(mc->mc_pg[mc->mc_top]),
|
7156
7347
|
(float)PAGEFILL(mc->mc_txn->mt_env, mc->mc_pg[mc->mc_top]) / 10));
|
7157
|
-
}
|
7158
|
-
#endif
|
7159
7348
|
|
7160
7349
|
if (PAGEFILL(mc->mc_txn->mt_env, mc->mc_pg[mc->mc_top]) >= FILL_THRESHOLD &&
|
7161
7350
|
NUMKEYS(mc->mc_pg[mc->mc_top]) >= minkeys) {
|
7162
|
-
#if MDB_DEBUG
|
7163
|
-
pgno_t pgno;
|
7164
|
-
COPY_PGNO(pgno, mc->mc_pg[mc->mc_top]->mp_pgno);
|
7165
7351
|
DPRINTF(("no need to rebalance page %"Z"u, above fill threshold",
|
7166
|
-
|
7167
|
-
#endif
|
7352
|
+
mdb_dbg_pgno(mc->mc_pg[mc->mc_top])));
|
7168
7353
|
return MDB_SUCCESS;
|
7169
7354
|
}
|
7170
7355
|
|
@@ -7204,6 +7389,7 @@ mdb_rebalance(MDB_cursor *mc)
|
|
7204
7389
|
}
|
7205
7390
|
}
|
7206
7391
|
} else if (IS_BRANCH(mp) && NUMKEYS(mp) == 1) {
|
7392
|
+
int i;
|
7207
7393
|
DPUTS("collapsing root page!");
|
7208
7394
|
rc = mdb_midl_append(&mc->mc_txn->mt_free_pgs, mp->mp_pgno);
|
7209
7395
|
if (rc)
|
@@ -7215,6 +7401,10 @@ mdb_rebalance(MDB_cursor *mc)
|
|
7215
7401
|
mc->mc_db->md_depth--;
|
7216
7402
|
mc->mc_db->md_branch_pages--;
|
7217
7403
|
mc->mc_ki[0] = mc->mc_ki[1];
|
7404
|
+
for (i = 1; i<mc->mc_db->md_depth; i++) {
|
7405
|
+
mc->mc_pg[i] = mc->mc_pg[i+1];
|
7406
|
+
mc->mc_ki[i] = mc->mc_ki[i+1];
|
7407
|
+
}
|
7218
7408
|
{
|
7219
7409
|
/* Adjust other cursors pointing to mp */
|
7220
7410
|
MDB_cursor *m2, *m3;
|
@@ -7227,7 +7417,6 @@ mdb_rebalance(MDB_cursor *mc)
|
|
7227
7417
|
m3 = m2;
|
7228
7418
|
if (m3 == mc || m3->mc_snum < mc->mc_snum) continue;
|
7229
7419
|
if (m3->mc_pg[0] == mp) {
|
7230
|
-
int i;
|
7231
7420
|
m3->mc_snum--;
|
7232
7421
|
m3->mc_top--;
|
7233
7422
|
for (i=0; i<m3->mc_snum; i++) {
|
@@ -7246,7 +7435,7 @@ mdb_rebalance(MDB_cursor *mc)
|
|
7246
7435
|
* otherwise the tree is invalid.
|
7247
7436
|
*/
|
7248
7437
|
ptop = mc->mc_top-1;
|
7249
|
-
|
7438
|
+
mdb_cassert(mc, NUMKEYS(mc->mc_pg[ptop]) > 1);
|
7250
7439
|
|
7251
7440
|
/* Leaf page fill factor is below the threshold.
|
7252
7441
|
* Try to move keys from left or right neighbor, or
|
@@ -7258,6 +7447,7 @@ mdb_rebalance(MDB_cursor *mc)
|
|
7258
7447
|
mdb_cursor_copy(mc, &mn);
|
7259
7448
|
mn.mc_xcursor = NULL;
|
7260
7449
|
|
7450
|
+
oldki = mc->mc_ki[mc->mc_top];
|
7261
7451
|
if (mc->mc_ki[ptop] == 0) {
|
7262
7452
|
/* We're the leftmost leaf in our parent.
|
7263
7453
|
*/
|
@@ -7291,113 +7481,115 @@ mdb_rebalance(MDB_cursor *mc)
|
|
7291
7481
|
* (A branch page must never have less than 2 keys.)
|
7292
7482
|
*/
|
7293
7483
|
minkeys = 1 + (IS_BRANCH(mn.mc_pg[mn.mc_top]));
|
7294
|
-
if (PAGEFILL(mc->mc_txn->mt_env, mn.mc_pg[mn.mc_top]) >= FILL_THRESHOLD && NUMKEYS(mn.mc_pg[mn.mc_top]) > minkeys)
|
7295
|
-
|
7296
|
-
|
7297
|
-
|
7484
|
+
if (PAGEFILL(mc->mc_txn->mt_env, mn.mc_pg[mn.mc_top]) >= FILL_THRESHOLD && NUMKEYS(mn.mc_pg[mn.mc_top]) > minkeys) {
|
7485
|
+
rc = mdb_node_move(&mn, mc);
|
7486
|
+
if (mc->mc_ki[ptop]) {
|
7487
|
+
oldki++;
|
7488
|
+
}
|
7489
|
+
} else {
|
7490
|
+
if (mc->mc_ki[ptop] == 0) {
|
7298
7491
|
rc = mdb_page_merge(&mn, mc);
|
7299
|
-
else {
|
7492
|
+
} else {
|
7493
|
+
oldki += NUMKEYS(mn.mc_pg[mn.mc_top]);
|
7300
7494
|
mn.mc_ki[mn.mc_top] += mc->mc_ki[mn.mc_top] + 1;
|
7301
7495
|
rc = mdb_page_merge(mc, &mn);
|
7302
7496
|
mdb_cursor_copy(&mn, mc);
|
7303
7497
|
}
|
7304
|
-
mc->mc_flags &= ~
|
7498
|
+
mc->mc_flags &= ~C_EOF;
|
7305
7499
|
}
|
7500
|
+
mc->mc_ki[mc->mc_top] = oldki;
|
7306
7501
|
return rc;
|
7307
7502
|
}
|
7308
7503
|
|
7309
7504
|
/** Complete a delete operation started by #mdb_cursor_del(). */
|
7310
7505
|
static int
|
7311
|
-
mdb_cursor_del0(MDB_cursor *mc
|
7506
|
+
mdb_cursor_del0(MDB_cursor *mc)
|
7312
7507
|
{
|
7313
7508
|
int rc;
|
7314
7509
|
MDB_page *mp;
|
7315
7510
|
indx_t ki;
|
7316
7511
|
unsigned int nkeys;
|
7317
7512
|
|
7318
|
-
mp = mc->mc_pg[mc->mc_top];
|
7319
7513
|
ki = mc->mc_ki[mc->mc_top];
|
7320
|
-
|
7321
|
-
/* add overflow pages to free list */
|
7322
|
-
if (!IS_LEAF2(mp) && F_ISSET(leaf->mn_flags, F_BIGDATA)) {
|
7323
|
-
MDB_page *omp;
|
7324
|
-
pgno_t pg;
|
7325
|
-
|
7326
|
-
memcpy(&pg, NODEDATA(leaf), sizeof(pg));
|
7327
|
-
if ((rc = mdb_page_get(mc->mc_txn, pg, &omp, NULL)) ||
|
7328
|
-
(rc = mdb_ovpage_free(mc, omp)))
|
7329
|
-
return rc;
|
7330
|
-
}
|
7331
|
-
mdb_node_del(mp, ki, mc->mc_db->md_pad);
|
7514
|
+
mdb_node_del(mc, mc->mc_db->md_pad);
|
7332
7515
|
mc->mc_db->md_entries--;
|
7333
7516
|
rc = mdb_rebalance(mc);
|
7334
|
-
|
7335
|
-
|
7336
|
-
|
7337
|
-
MDB_cursor *m2;
|
7517
|
+
|
7518
|
+
if (rc == MDB_SUCCESS) {
|
7519
|
+
MDB_cursor *m2, *m3;
|
7338
7520
|
MDB_dbi dbi = mc->mc_dbi;
|
7339
7521
|
|
7340
7522
|
mp = mc->mc_pg[mc->mc_top];
|
7341
7523
|
nkeys = NUMKEYS(mp);
|
7342
7524
|
|
7343
7525
|
/* if mc points past last node in page, find next sibling */
|
7344
|
-
if (mc->mc_ki[mc->mc_top] >= nkeys)
|
7345
|
-
mdb_cursor_sibling(mc, 1);
|
7526
|
+
if (mc->mc_ki[mc->mc_top] >= nkeys) {
|
7527
|
+
rc = mdb_cursor_sibling(mc, 1);
|
7528
|
+
if (rc == MDB_NOTFOUND)
|
7529
|
+
rc = MDB_SUCCESS;
|
7530
|
+
}
|
7346
7531
|
|
7347
7532
|
/* Adjust other cursors pointing to mp */
|
7348
|
-
for (m2 = mc->mc_txn->mt_cursors[dbi]; m2; m2=m2->mc_next) {
|
7349
|
-
|
7533
|
+
for (m2 = mc->mc_txn->mt_cursors[dbi]; !rc && m2; m2=m2->mc_next) {
|
7534
|
+
m3 = (mc->mc_flags & C_SUB) ? &m2->mc_xcursor->mx_cursor : m2;
|
7535
|
+
if (! (m2->mc_flags & m3->mc_flags & C_INITIALIZED))
|
7350
7536
|
continue;
|
7351
|
-
if (
|
7537
|
+
if (m3 == mc || m3->mc_snum < mc->mc_snum)
|
7352
7538
|
continue;
|
7353
|
-
if (
|
7354
|
-
if (
|
7355
|
-
|
7356
|
-
if (
|
7357
|
-
|
7539
|
+
if (m3->mc_pg[mc->mc_top] == mp) {
|
7540
|
+
if (m3->mc_ki[mc->mc_top] >= ki) {
|
7541
|
+
m3->mc_flags |= C_DEL;
|
7542
|
+
if (m3->mc_ki[mc->mc_top] > ki)
|
7543
|
+
m3->mc_ki[mc->mc_top]--;
|
7544
|
+
}
|
7545
|
+
if (m3->mc_ki[mc->mc_top] >= nkeys) {
|
7546
|
+
rc = mdb_cursor_sibling(m3, 1);
|
7547
|
+
if (rc == MDB_NOTFOUND)
|
7548
|
+
rc = MDB_SUCCESS;
|
7358
7549
|
}
|
7359
|
-
if (m2->mc_ki[mc->mc_top] >= nkeys)
|
7360
|
-
mdb_cursor_sibling(m2, 1);
|
7361
7550
|
}
|
7362
7551
|
}
|
7363
7552
|
mc->mc_flags |= C_DEL;
|
7364
7553
|
}
|
7365
7554
|
|
7555
|
+
if (rc)
|
7556
|
+
mc->mc_txn->mt_flags |= MDB_TXN_ERROR;
|
7366
7557
|
return rc;
|
7367
7558
|
}
|
7368
7559
|
|
7369
7560
|
int
|
7370
7561
|
mdb_del(MDB_txn *txn, MDB_dbi dbi,
|
7371
7562
|
MDB_val *key, MDB_val *data)
|
7563
|
+
{
|
7564
|
+
if (!key || dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
|
7565
|
+
return EINVAL;
|
7566
|
+
|
7567
|
+
if (txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_ERROR))
|
7568
|
+
return (txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN;
|
7569
|
+
|
7570
|
+
if (!F_ISSET(txn->mt_dbs[dbi].md_flags, MDB_DUPSORT)) {
|
7571
|
+
/* must ignore any data */
|
7572
|
+
data = NULL;
|
7573
|
+
}
|
7574
|
+
|
7575
|
+
return mdb_del0(txn, dbi, key, data, 0);
|
7576
|
+
}
|
7577
|
+
|
7578
|
+
static int
|
7579
|
+
mdb_del0(MDB_txn *txn, MDB_dbi dbi,
|
7580
|
+
MDB_val *key, MDB_val *data, unsigned flags)
|
7372
7581
|
{
|
7373
7582
|
MDB_cursor mc;
|
7374
7583
|
MDB_xcursor mx;
|
7375
7584
|
MDB_cursor_op op;
|
7376
7585
|
MDB_val rdata, *xdata;
|
7377
|
-
int rc, exact;
|
7586
|
+
int rc, exact = 0;
|
7378
7587
|
DKBUF;
|
7379
7588
|
|
7380
|
-
assert(key != NULL);
|
7381
|
-
|
7382
7589
|
DPRINTF(("====> delete db %u key [%s]", dbi, DKEY(key)));
|
7383
7590
|
|
7384
|
-
if (txn == NULL || !dbi || dbi >= txn->mt_numdbs || !(txn->mt_dbflags[dbi] & DB_VALID))
|
7385
|
-
return EINVAL;
|
7386
|
-
|
7387
|
-
if (txn->mt_flags & (MDB_TXN_RDONLY|MDB_TXN_ERROR))
|
7388
|
-
return (txn->mt_flags & MDB_TXN_RDONLY) ? EACCES : MDB_BAD_TXN;
|
7389
|
-
|
7390
|
-
if (key->mv_size > MDB_MAXKEYSIZE) {
|
7391
|
-
return MDB_BAD_VALSIZE;
|
7392
|
-
}
|
7393
|
-
|
7394
7591
|
mdb_cursor_init(&mc, txn, dbi, &mx);
|
7395
7592
|
|
7396
|
-
exact = 0;
|
7397
|
-
if (!F_ISSET(txn->mt_dbs[dbi].md_flags, MDB_DUPSORT)) {
|
7398
|
-
/* must ignore any data */
|
7399
|
-
data = NULL;
|
7400
|
-
}
|
7401
7593
|
if (data) {
|
7402
7594
|
op = MDB_GET_BOTH;
|
7403
7595
|
rdata = *data;
|
@@ -7405,6 +7597,7 @@ mdb_del(MDB_txn *txn, MDB_dbi dbi,
|
|
7405
7597
|
} else {
|
7406
7598
|
op = MDB_SET;
|
7407
7599
|
xdata = NULL;
|
7600
|
+
flags |= MDB_NODUPDATA;
|
7408
7601
|
}
|
7409
7602
|
rc = mdb_cursor_set(&mc, key, xdata, op, &exact);
|
7410
7603
|
if (rc == 0) {
|
@@ -7419,7 +7612,7 @@ mdb_del(MDB_txn *txn, MDB_dbi dbi,
|
|
7419
7612
|
mc.mc_flags |= C_UNTRACK;
|
7420
7613
|
mc.mc_next = txn->mt_cursors[dbi];
|
7421
7614
|
txn->mt_cursors[dbi] = &mc;
|
7422
|
-
rc = mdb_cursor_del(&mc,
|
7615
|
+
rc = mdb_cursor_del(&mc, flags);
|
7423
7616
|
txn->mt_cursors[dbi] = mc.mc_next;
|
7424
7617
|
}
|
7425
7618
|
return rc;
|
@@ -7468,7 +7661,7 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
|
|
7468
7661
|
|
7469
7662
|
if (mc->mc_snum < 2) {
|
7470
7663
|
if ((rc = mdb_page_new(mc, P_BRANCH, 1, &pp)))
|
7471
|
-
|
7664
|
+
goto done;
|
7472
7665
|
/* shift current top to make room for new parent */
|
7473
7666
|
mc->mc_pg[1] = mc->mc_pg[0];
|
7474
7667
|
mc->mc_ki[1] = mc->mc_ki[0];
|
@@ -7486,7 +7679,7 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
|
|
7486
7679
|
mc->mc_ki[0] = mc->mc_ki[1];
|
7487
7680
|
mc->mc_db->md_root = mp->mp_pgno;
|
7488
7681
|
mc->mc_db->md_depth--;
|
7489
|
-
|
7682
|
+
goto done;
|
7490
7683
|
}
|
7491
7684
|
mc->mc_snum = 2;
|
7492
7685
|
mc->mc_top = 1;
|
@@ -7515,7 +7708,6 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
|
|
7515
7708
|
int x;
|
7516
7709
|
unsigned int lsize, rsize, ksize;
|
7517
7710
|
/* Move half of the keys to the right sibling */
|
7518
|
-
copy = NULL;
|
7519
7711
|
x = mc->mc_ki[mc->mc_top] - split_indx;
|
7520
7712
|
ksize = mc->mc_db->md_pad;
|
7521
7713
|
split = LEAF2KEY(mp, split_indx, ksize);
|
@@ -7558,12 +7750,14 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
|
|
7558
7750
|
nsize = mdb_leaf_size(env, newkey, newdata);
|
7559
7751
|
else
|
7560
7752
|
nsize = mdb_branch_size(env, newkey);
|
7561
|
-
nsize
|
7753
|
+
nsize = EVEN(nsize);
|
7562
7754
|
|
7563
7755
|
/* grab a page to hold a temporary copy */
|
7564
7756
|
copy = mdb_page_malloc(mc->mc_txn, 1);
|
7565
|
-
if (copy == NULL)
|
7566
|
-
|
7757
|
+
if (copy == NULL) {
|
7758
|
+
rc = ENOMEM;
|
7759
|
+
goto done;
|
7760
|
+
}
|
7567
7761
|
copy->mp_pgno = mp->mp_pgno;
|
7568
7762
|
copy->mp_flags = mp->mp_flags;
|
7569
7763
|
copy->mp_lower = PAGEHDRSZ;
|
@@ -7615,7 +7809,7 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
|
|
7615
7809
|
else
|
7616
7810
|
psize += NODEDSZ(node);
|
7617
7811
|
}
|
7618
|
-
psize
|
7812
|
+
psize = EVEN(psize);
|
7619
7813
|
}
|
7620
7814
|
if (psize > pmax || i == k-j) {
|
7621
7815
|
split_indx = i + (j<0);
|
@@ -7643,6 +7837,8 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
|
|
7643
7837
|
mn.mc_top--;
|
7644
7838
|
did_split = 1;
|
7645
7839
|
rc = mdb_page_split(&mn, &sepkey, NULL, rp->mp_pgno, 0);
|
7840
|
+
if (rc)
|
7841
|
+
goto done;
|
7646
7842
|
|
7647
7843
|
/* root split? */
|
7648
7844
|
if (mn.mc_snum == mc->mc_snum) {
|
@@ -7664,7 +7860,13 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
|
|
7664
7860
|
mc->mc_ki[i] = mn.mc_ki[i];
|
7665
7861
|
}
|
7666
7862
|
mc->mc_pg[ptop] = mn.mc_pg[ptop];
|
7667
|
-
|
7863
|
+
if (mn.mc_ki[ptop]) {
|
7864
|
+
mc->mc_ki[ptop] = mn.mc_ki[ptop] - 1;
|
7865
|
+
} else {
|
7866
|
+
/* find right page's left sibling */
|
7867
|
+
mc->mc_ki[ptop] = mn.mc_ki[ptop];
|
7868
|
+
mdb_cursor_sibling(mc, 0);
|
7869
|
+
}
|
7668
7870
|
}
|
7669
7871
|
} else {
|
7670
7872
|
mn.mc_top--;
|
@@ -7673,14 +7875,14 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
|
|
7673
7875
|
}
|
7674
7876
|
mc->mc_flags ^= C_SPLITTING;
|
7675
7877
|
if (rc != MDB_SUCCESS) {
|
7676
|
-
|
7878
|
+
goto done;
|
7677
7879
|
}
|
7678
7880
|
if (nflags & MDB_APPEND) {
|
7679
7881
|
mc->mc_pg[mc->mc_top] = rp;
|
7680
7882
|
mc->mc_ki[mc->mc_top] = 0;
|
7681
7883
|
rc = mdb_node_add(mc, 0, newkey, newdata, newpgno, nflags);
|
7682
7884
|
if (rc)
|
7683
|
-
|
7885
|
+
goto done;
|
7684
7886
|
for (i=0; i<mc->mc_top; i++)
|
7685
7887
|
mc->mc_ki[i] = mn.mc_ki[i];
|
7686
7888
|
} else if (!IS_LEAF2(mp)) {
|
@@ -7718,11 +7920,8 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
|
|
7718
7920
|
}
|
7719
7921
|
|
7720
7922
|
rc = mdb_node_add(mc, j, &rkey, rdata, pgno, flags);
|
7721
|
-
if (rc)
|
7722
|
-
|
7723
|
-
mdb_page_free(env, copy);
|
7724
|
-
return rc;
|
7725
|
-
}
|
7923
|
+
if (rc)
|
7924
|
+
goto done;
|
7726
7925
|
if (i == nkeys) {
|
7727
7926
|
i = 0;
|
7728
7927
|
j = 0;
|
@@ -7756,16 +7955,12 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
|
|
7756
7955
|
*/
|
7757
7956
|
if (mn.mc_pg[ptop] != mc->mc_pg[ptop] &&
|
7758
7957
|
mc->mc_ki[ptop] >= NUMKEYS(mc->mc_pg[ptop])) {
|
7759
|
-
for (i=0; i
|
7958
|
+
for (i=0; i<=ptop; i++) {
|
7760
7959
|
mc->mc_pg[i] = mn.mc_pg[i];
|
7761
7960
|
mc->mc_ki[i] = mn.mc_ki[i];
|
7762
7961
|
}
|
7763
|
-
mc->mc_pg[ptop] = mn.mc_pg[ptop];
|
7764
|
-
mc->mc_ki[ptop] = mn.mc_ki[ptop] - 1;
|
7765
7962
|
}
|
7766
7963
|
}
|
7767
|
-
/* return tmp page to freelist */
|
7768
|
-
mdb_page_free(env, copy);
|
7769
7964
|
}
|
7770
7965
|
|
7771
7966
|
{
|
@@ -7816,6 +8011,12 @@ mdb_page_split(MDB_cursor *mc, MDB_val *newkey, MDB_val *newdata, pgno_t newpgno
|
|
7816
8011
|
}
|
7817
8012
|
}
|
7818
8013
|
DPRINTF(("mp left: %d, rp left: %d", SIZELEFT(mp), SIZELEFT(rp)));
|
8014
|
+
|
8015
|
+
done:
|
8016
|
+
if (copy) /* tmp page */
|
8017
|
+
mdb_page_free(env, copy);
|
8018
|
+
if (rc)
|
8019
|
+
mc->mc_txn->mt_flags |= MDB_TXN_ERROR;
|
7819
8020
|
return rc;
|
7820
8021
|
}
|
7821
8022
|
|
@@ -7826,10 +8027,7 @@ mdb_put(MDB_txn *txn, MDB_dbi dbi,
|
|
7826
8027
|
MDB_cursor mc;
|
7827
8028
|
MDB_xcursor mx;
|
7828
8029
|
|
7829
|
-
|
7830
|
-
assert(data != NULL);
|
7831
|
-
|
7832
|
-
if (txn == NULL || !dbi || dbi >= txn->mt_numdbs || !(txn->mt_dbflags[dbi] & DB_VALID))
|
8030
|
+
if (!key || !data || dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
|
7833
8031
|
return EINVAL;
|
7834
8032
|
|
7835
8033
|
if ((flags & (MDB_NOOVERWRITE|MDB_NODUPDATA|MDB_RESERVE|MDB_APPEND|MDB_APPENDDUP)) != flags)
|
@@ -7861,6 +8059,32 @@ mdb_env_get_flags(MDB_env *env, unsigned int *arg)
|
|
7861
8059
|
return MDB_SUCCESS;
|
7862
8060
|
}
|
7863
8061
|
|
8062
|
+
int
|
8063
|
+
mdb_env_set_userctx(MDB_env *env, void *ctx)
|
8064
|
+
{
|
8065
|
+
if (!env)
|
8066
|
+
return EINVAL;
|
8067
|
+
env->me_userctx = ctx;
|
8068
|
+
return MDB_SUCCESS;
|
8069
|
+
}
|
8070
|
+
|
8071
|
+
void *
|
8072
|
+
mdb_env_get_userctx(MDB_env *env)
|
8073
|
+
{
|
8074
|
+
return env ? env->me_userctx : NULL;
|
8075
|
+
}
|
8076
|
+
|
8077
|
+
int
|
8078
|
+
mdb_env_set_assert(MDB_env *env, MDB_assert_func *func)
|
8079
|
+
{
|
8080
|
+
if (!env)
|
8081
|
+
return EINVAL;
|
8082
|
+
#ifndef NDEBUG
|
8083
|
+
env->me_assert_func = func;
|
8084
|
+
#endif
|
8085
|
+
return MDB_SUCCESS;
|
8086
|
+
}
|
8087
|
+
|
7864
8088
|
int
|
7865
8089
|
mdb_env_get_path(MDB_env *env, const char **arg)
|
7866
8090
|
{
|
@@ -8062,9 +8286,12 @@ int mdb_dbi_open(MDB_txn *txn, const char *name, unsigned int flags, MDB_dbi *db
|
|
8062
8286
|
|
8063
8287
|
int mdb_stat(MDB_txn *txn, MDB_dbi dbi, MDB_stat *arg)
|
8064
8288
|
{
|
8065
|
-
if (
|
8289
|
+
if (!arg || !TXN_DBI_EXIST(txn, dbi))
|
8066
8290
|
return EINVAL;
|
8067
8291
|
|
8292
|
+
if (txn->mt_flags & MDB_TXN_ERROR)
|
8293
|
+
return MDB_BAD_TXN;
|
8294
|
+
|
8068
8295
|
if (txn->mt_dbflags[dbi] & DB_STALE) {
|
8069
8296
|
MDB_cursor mc;
|
8070
8297
|
MDB_xcursor mx;
|
@@ -8089,7 +8316,7 @@ void mdb_dbi_close(MDB_env *env, MDB_dbi dbi)
|
|
8089
8316
|
int mdb_dbi_flags(MDB_txn *txn, MDB_dbi dbi, unsigned int *flags)
|
8090
8317
|
{
|
8091
8318
|
/* We could return the flags for the FREE_DBI too but what's the point? */
|
8092
|
-
if (
|
8319
|
+
if (dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
|
8093
8320
|
return EINVAL;
|
8094
8321
|
*flags = txn->mt_dbs[dbi].md_flags & PERSISTENT_FLAGS;
|
8095
8322
|
return MDB_SUCCESS;
|
@@ -8129,22 +8356,22 @@ mdb_drop0(MDB_cursor *mc, int subs)
|
|
8129
8356
|
memcpy(&pg, NODEDATA(ni), sizeof(pg));
|
8130
8357
|
rc = mdb_page_get(txn, pg, &omp, NULL);
|
8131
8358
|
if (rc != 0)
|
8132
|
-
|
8133
|
-
|
8359
|
+
goto done;
|
8360
|
+
mdb_cassert(mc, IS_OVERFLOW(omp));
|
8134
8361
|
rc = mdb_midl_append_range(&txn->mt_free_pgs,
|
8135
8362
|
pg, omp->mp_pages);
|
8136
8363
|
if (rc)
|
8137
|
-
|
8364
|
+
goto done;
|
8138
8365
|
} else if (subs && (ni->mn_flags & F_SUBDATA)) {
|
8139
8366
|
mdb_xcursor_init1(mc, ni);
|
8140
8367
|
rc = mdb_drop0(&mc->mc_xcursor->mx_cursor, 0);
|
8141
8368
|
if (rc)
|
8142
|
-
|
8369
|
+
goto done;
|
8143
8370
|
}
|
8144
8371
|
}
|
8145
8372
|
} else {
|
8146
8373
|
if ((rc = mdb_midl_need(&txn->mt_free_pgs, n)) != 0)
|
8147
|
-
|
8374
|
+
goto done;
|
8148
8375
|
for (i=0; i<n; i++) {
|
8149
8376
|
pgno_t pg;
|
8150
8377
|
ni = NODEPTR(mp, i);
|
@@ -8158,6 +8385,8 @@ mdb_drop0(MDB_cursor *mc, int subs)
|
|
8158
8385
|
mc->mc_ki[mc->mc_top] = i;
|
8159
8386
|
rc = mdb_cursor_sibling(mc, 1);
|
8160
8387
|
if (rc) {
|
8388
|
+
if (rc != MDB_NOTFOUND)
|
8389
|
+
goto done;
|
8161
8390
|
/* no more siblings, go back to beginning
|
8162
8391
|
* of previous level.
|
8163
8392
|
*/
|
@@ -8171,6 +8400,9 @@ mdb_drop0(MDB_cursor *mc, int subs)
|
|
8171
8400
|
}
|
8172
8401
|
/* free it */
|
8173
8402
|
rc = mdb_midl_append(&txn->mt_free_pgs, mc->mc_db->md_root);
|
8403
|
+
done:
|
8404
|
+
if (rc)
|
8405
|
+
txn->mt_flags |= MDB_TXN_ERROR;
|
8174
8406
|
} else if (rc == MDB_NOTFOUND) {
|
8175
8407
|
rc = MDB_SUCCESS;
|
8176
8408
|
}
|
@@ -8182,7 +8414,7 @@ int mdb_drop(MDB_txn *txn, MDB_dbi dbi, int del)
|
|
8182
8414
|
MDB_cursor *mc, *m2;
|
8183
8415
|
int rc;
|
8184
8416
|
|
8185
|
-
if (
|
8417
|
+
if ((unsigned)del > 1 || dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
|
8186
8418
|
return EINVAL;
|
8187
8419
|
|
8188
8420
|
if (F_ISSET(txn->mt_flags, MDB_TXN_RDONLY))
|
@@ -8201,10 +8433,12 @@ int mdb_drop(MDB_txn *txn, MDB_dbi dbi, int del)
|
|
8201
8433
|
|
8202
8434
|
/* Can't delete the main DB */
|
8203
8435
|
if (del && dbi > MAIN_DBI) {
|
8204
|
-
rc =
|
8436
|
+
rc = mdb_del0(txn, MAIN_DBI, &mc->mc_dbx->md_name, NULL, 0);
|
8205
8437
|
if (!rc) {
|
8206
8438
|
txn->mt_dbflags[dbi] = DB_STALE;
|
8207
8439
|
mdb_dbi_close(txn->mt_env, dbi);
|
8440
|
+
} else {
|
8441
|
+
txn->mt_flags |= MDB_TXN_ERROR;
|
8208
8442
|
}
|
8209
8443
|
} else {
|
8210
8444
|
/* reset the DB record, mark it dirty */
|
@@ -8225,7 +8459,7 @@ leave:
|
|
8225
8459
|
|
8226
8460
|
int mdb_set_compare(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp)
|
8227
8461
|
{
|
8228
|
-
if (
|
8462
|
+
if (dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
|
8229
8463
|
return EINVAL;
|
8230
8464
|
|
8231
8465
|
txn->mt_dbxs[dbi].md_cmp = cmp;
|
@@ -8234,7 +8468,7 @@ int mdb_set_compare(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp)
|
|
8234
8468
|
|
8235
8469
|
int mdb_set_dupsort(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp)
|
8236
8470
|
{
|
8237
|
-
if (
|
8471
|
+
if (dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
|
8238
8472
|
return EINVAL;
|
8239
8473
|
|
8240
8474
|
txn->mt_dbxs[dbi].md_dcmp = cmp;
|
@@ -8243,7 +8477,7 @@ int mdb_set_dupsort(MDB_txn *txn, MDB_dbi dbi, MDB_cmp_func *cmp)
|
|
8243
8477
|
|
8244
8478
|
int mdb_set_relfunc(MDB_txn *txn, MDB_dbi dbi, MDB_rel_func *rel)
|
8245
8479
|
{
|
8246
|
-
if (
|
8480
|
+
if (dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
|
8247
8481
|
return EINVAL;
|
8248
8482
|
|
8249
8483
|
txn->mt_dbxs[dbi].md_rel = rel;
|
@@ -8252,7 +8486,7 @@ int mdb_set_relfunc(MDB_txn *txn, MDB_dbi dbi, MDB_rel_func *rel)
|
|
8252
8486
|
|
8253
8487
|
int mdb_set_relctx(MDB_txn *txn, MDB_dbi dbi, void *ctx)
|
8254
8488
|
{
|
8255
|
-
if (
|
8489
|
+
if (dbi == FREE_DBI || !TXN_DBI_EXIST(txn, dbi))
|
8256
8490
|
return EINVAL;
|
8257
8491
|
|
8258
8492
|
txn->mt_dbxs[dbi].md_relctx = ctx;
|
@@ -8261,7 +8495,7 @@ int mdb_set_relctx(MDB_txn *txn, MDB_dbi dbi, void *ctx)
|
|
8261
8495
|
|
8262
8496
|
int mdb_env_get_maxkeysize(MDB_env *env)
|
8263
8497
|
{
|
8264
|
-
return
|
8498
|
+
return ENV_MAXKEY(env);
|
8265
8499
|
}
|
8266
8500
|
|
8267
8501
|
int mdb_reader_list(MDB_env *env, MDB_msg_func *func, void *ctx)
|
@@ -8269,7 +8503,7 @@ int mdb_reader_list(MDB_env *env, MDB_msg_func *func, void *ctx)
|
|
8269
8503
|
unsigned int i, rdrs;
|
8270
8504
|
MDB_reader *mr;
|
8271
8505
|
char buf[64];
|
8272
|
-
int first = 1;
|
8506
|
+
int rc = 0, first = 1;
|
8273
8507
|
|
8274
8508
|
if (!env || !func)
|
8275
8509
|
return -1;
|
@@ -8280,27 +8514,25 @@ int mdb_reader_list(MDB_env *env, MDB_msg_func *func, void *ctx)
|
|
8280
8514
|
mr = env->me_txns->mti_readers;
|
8281
8515
|
for (i=0; i<rdrs; i++) {
|
8282
8516
|
if (mr[i].mr_pid) {
|
8283
|
-
|
8284
|
-
|
8285
|
-
|
8286
|
-
|
8287
|
-
sprintf(buf, "%10d %"Z"x -\n", mr[i].mr_pid, tid);
|
8288
|
-
} else {
|
8289
|
-
sprintf(buf, "%10d %"Z"x %"Z"u\n", mr[i].mr_pid, tid, mr[i].mr_txnid);
|
8290
|
-
}
|
8517
|
+
txnid_t txnid = mr[i].mr_txnid;
|
8518
|
+
sprintf(buf, txnid == (txnid_t)-1 ?
|
8519
|
+
"%10d %"Z"x -\n" : "%10d %"Z"x %"Z"u\n",
|
8520
|
+
(int)mr[i].mr_pid, (size_t)mr[i].mr_tid, txnid);
|
8291
8521
|
if (first) {
|
8292
8522
|
first = 0;
|
8293
|
-
func(" pid thread txnid\n", ctx);
|
8523
|
+
rc = func(" pid thread txnid\n", ctx);
|
8524
|
+
if (rc < 0)
|
8525
|
+
break;
|
8294
8526
|
}
|
8295
8527
|
rc = func(buf, ctx);
|
8296
8528
|
if (rc < 0)
|
8297
|
-
|
8529
|
+
break;
|
8298
8530
|
}
|
8299
8531
|
}
|
8300
8532
|
if (first) {
|
8301
|
-
func("(no active readers)\n", ctx);
|
8533
|
+
rc = func("(no active readers)\n", ctx);
|
8302
8534
|
}
|
8303
|
-
return
|
8535
|
+
return rc;
|
8304
8536
|
}
|
8305
8537
|
|
8306
8538
|
/** Insert pid into list if not already present.
|
@@ -8361,7 +8593,6 @@ int mdb_reader_check(MDB_env *env, int *dead)
|
|
8361
8593
|
return ENOMEM;
|
8362
8594
|
pids[0] = 0;
|
8363
8595
|
mr = env->me_txns->mti_readers;
|
8364
|
-
j = 0;
|
8365
8596
|
for (i=0; i<rdrs; i++) {
|
8366
8597
|
if (mr[i].mr_pid && mr[i].mr_pid != env->me_pid) {
|
8367
8598
|
pid = mr[i].mr_pid;
|