mirror of
https://github.com/MariaDB/server.git
synced 2025-02-02 12:01:42 +01:00
Updated description of lock tree
git-svn-id: file:///svn/tokudb@1652 c7de825b-a66e-492c-adef-691d508d4ae1
This commit is contained in:
parent
907df64d8b
commit
4629d955af
1 changed files with 837 additions and 0 deletions
|
@ -31,4 +31,841 @@ struct __toku_db_internal {
|
||||||
int(*associate_callback)(DB*, const DBT*, const DBT*, DBT*); // For secondary, the callback function for associate. NULL if not secondary
|
int(*associate_callback)(DB*, const DBT*, const DBT*, DBT*); // For secondary, the callback function for associate. NULL if not secondary
|
||||||
int associate_is_immutable; // If this DB is a secondary then this field indicates that the index never changes due to updates.
|
int associate_is_immutable; // If this DB is a secondary then this field indicates that the index never changes due to updates.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct __toku_lock_tree {
|
||||||
|
DB* db;
|
||||||
|
//Some Red Black tree
|
||||||
|
} toku_lock_tree;
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a lock tree
|
||||||
|
* If it is a nodup database, it uses just the regular compare,
|
||||||
|
* else it uses both regular and dup compare.
|
||||||
|
*/
|
||||||
|
int toku_lock_tree_create(toku_lock_tree** tree, DB* db);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Closes/Frees a lock tree.
|
||||||
|
*/
|
||||||
|
int toku_lock_tree_close(toku_lock_tree* tree);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Obtains a read lock on a single key (or key/value)
|
||||||
|
* Returns 0 on success
|
||||||
|
* Error: DB_LOCK_NOTGRANTED if cannot get the read lock.
|
||||||
|
* This occurs if someone (else) has a write lock on it or
|
||||||
|
* a region that encompasses it.
|
||||||
|
*/
|
||||||
|
int toku_lock_tree_get_read_lock(toku_lock_tree* tree, DB_TXN* txn,
|
||||||
|
DBT* key, DBT* value);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Obtains a read lock on a key (or key/value) range.
|
||||||
|
* Returns 0 on success
|
||||||
|
* Error: DB_LOCK_NOTGRANTED if cannot get the read lock.
|
||||||
|
* This occurs if someone (else) has a write or read lock in the range
|
||||||
|
* or in an overlapping range.
|
||||||
|
*/
|
||||||
|
int toku_lock_tree_get_read_range_lock(toku_lock_tree* tree, DB_TXN* txn,
|
||||||
|
DBT* key_from, DBT* key_to,
|
||||||
|
DBT* value_from, DBT* value_to);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Obtains a write lock on a single key (or key/value)
|
||||||
|
* Returns 0 on success
|
||||||
|
* Error: DB_LOCK_NOTGRANTED if cannot get the read lock.
|
||||||
|
* This occurs if someone (else) has a read or write lock on it or
|
||||||
|
* a region that encompasses it.
|
||||||
|
*/
|
||||||
|
int toku_lock_tree_get_write_lock(toku_lock_tree* tree, DB_TXN* txn,
|
||||||
|
DBT* key, DBT* value);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Obtains a write lock on a key (or key/value) range.
|
||||||
|
* Returns 0 on success
|
||||||
|
* Error: DB_LOCK_NOTGRANTED if cannot get the read lock.
|
||||||
|
* This occurs if someone (else) has a read or write lock in the range
|
||||||
|
* or in an overlapping range.
|
||||||
|
*/
|
||||||
|
int toku_lock_tree_get_write_range_lock(toku_lock_tree* tree, DB_TXN* txn,
|
||||||
|
DBT* key_from, DBT* key_to,
|
||||||
|
DBT* value_from, DBT* value_to);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Releases all the locks owned by a transaction.
|
||||||
|
* Used when the transaction commits or rolls back.
|
||||||
|
*/
|
||||||
|
int toku_lock_tree_free_locks(toku_lock_tree* tree, DB_TXN* txn);
|
||||||
|
|
||||||
|
//These are special symbols for top/bottom.
|
||||||
|
//They can be used both for keys and values.
|
||||||
|
extern const DBT* toku_dbt_positive_infinity;
|
||||||
|
extern const DBT* toku_dbt_negative_infinity;
|
||||||
|
/*
|
||||||
|
This will be defined in the lock table .c file.
|
||||||
|
static const DBT toku_dbt_top_placeholder;
|
||||||
|
const DBT* toku_dbt_top = &toku_dbt_top_placeholder;
|
||||||
|
static const DBT toku_dbt_bottom_placeholder;
|
||||||
|
const DBT* toku_dbt_bottom = &toku_dbt_bottom_placeholder;
|
||||||
|
*/
|
||||||
|
//Need some way to represent TOP and BOTTOM, and (key,top) and (key,bottom), so therefore it should be easier
|
||||||
|
//for the lock tree to understand what keys and values are instead of just a single item.
|
||||||
|
|
||||||
|
/*
|
||||||
|
Whenever a lock fails rollback (just current op) and quit
|
||||||
|
NODUP in DB
|
||||||
|
get
|
||||||
|
DEFAULT (in key)
|
||||||
|
lock key
|
||||||
|
run
|
||||||
|
DB_GET_BOTH (in key)
|
||||||
|
lock key
|
||||||
|
run
|
||||||
|
c_get
|
||||||
|
DB_CURRENT (in void)
|
||||||
|
No Lock (Must already be locked by virtue of cursor pointing to it.)
|
||||||
|
run
|
||||||
|
DB_FIRST
|
||||||
|
run (out key)
|
||||||
|
if found lock bottom<->key
|
||||||
|
else lock bottom<->top
|
||||||
|
DB_LAST
|
||||||
|
run (out key)
|
||||||
|
if found lock key<->top
|
||||||
|
else lock bottom<->top
|
||||||
|
DB_GET_BOTH (in key)
|
||||||
|
lock key
|
||||||
|
run
|
||||||
|
DB_GET_BOTH_RANGE (in key)
|
||||||
|
******** I guess we don't care what the behavior is! Assuming it acts as DB_GET_BOTH and not DB_SET
|
||||||
|
lock key
|
||||||
|
run
|
||||||
|
DB_NEXT
|
||||||
|
if (!initialized) call DB_FIRST, return
|
||||||
|
API_getoldcurrent (out o_key)
|
||||||
|
run (out key)
|
||||||
|
if found lock o_key<->key
|
||||||
|
else lock o_key<->top
|
||||||
|
DB_PREV
|
||||||
|
if (!initialized) call DB_LAST, return
|
||||||
|
API_getoldcurrent (out o_key)
|
||||||
|
run (out key)
|
||||||
|
if found lock key<->o_key
|
||||||
|
else lock bottom<->o_key
|
||||||
|
DB_SET (in key)
|
||||||
|
lock key
|
||||||
|
run
|
||||||
|
DB_SET_RANGE (in i_key)
|
||||||
|
run (out key)
|
||||||
|
if found
|
||||||
|
if (i_key != key) lock i_key<->key
|
||||||
|
else lock i_key
|
||||||
|
else
|
||||||
|
lock i_key<->top
|
||||||
|
DB_NEXT_NODUP *** Does this return EINVAL?
|
||||||
|
call DB_NEXT, return
|
||||||
|
DB_NEXT_DUP
|
||||||
|
EINVAL? or just return notfound (or if not init, EINVAL)?
|
||||||
|
DB_PREV_NODUP
|
||||||
|
call DB_PREV, return
|
||||||
|
Put
|
||||||
|
Default/0 (in key)
|
||||||
|
writelock key
|
||||||
|
run
|
||||||
|
NoOverwrite
|
||||||
|
writelock key
|
||||||
|
run
|
||||||
|
|
||||||
|
optimization alternative
|
||||||
|
get
|
||||||
|
if found done
|
||||||
|
else call YesOverwrite
|
||||||
|
YesOverwrite
|
||||||
|
writelock key
|
||||||
|
run
|
||||||
|
Del
|
||||||
|
Default/0 (in key)
|
||||||
|
writelock key
|
||||||
|
run
|
||||||
|
|
||||||
|
optimization alternative
|
||||||
|
get
|
||||||
|
if !found done
|
||||||
|
else call DeleteAny
|
||||||
|
DeleteAny
|
||||||
|
writelock key
|
||||||
|
run
|
||||||
|
c_del
|
||||||
|
API_getoldcurrent (out key)
|
||||||
|
writelock key
|
||||||
|
run
|
||||||
|
DUPSORT db
|
||||||
|
get
|
||||||
|
DEFAULT (in key)
|
||||||
|
run (out key, out value)
|
||||||
|
if found lock (key,bottom)<->(key, value)
|
||||||
|
else lock (key,bottom)<->(key, top)
|
||||||
|
DB_GET_BOTH (in key, in value)
|
||||||
|
lock (key,value)
|
||||||
|
run
|
||||||
|
c_get
|
||||||
|
DB_CURRENT (in void)
|
||||||
|
No Lock (Must already be locked by virtue of cursor pointing to it.)
|
||||||
|
run
|
||||||
|
DB_FIRST
|
||||||
|
run (out key, out value)
|
||||||
|
if found lock (bottom,bottom)<->(key,value)
|
||||||
|
else lock (bottom,bottom)<->(top,top)
|
||||||
|
DB_LAST
|
||||||
|
run (out key, out value)
|
||||||
|
if found lock (key,value)<->(top,top)
|
||||||
|
else lock (bottom,bottom)<->(top,top)
|
||||||
|
DB_GET_BOTH (in key, in value)
|
||||||
|
lock (key,value)
|
||||||
|
run
|
||||||
|
DB_GET_BOTH_RANGE (in key, in i_value)
|
||||||
|
*** verify it doesn't leave the key
|
||||||
|
run (out value)
|
||||||
|
if found
|
||||||
|
if (value != i_value) lock (key,i_value)<->(key,value)
|
||||||
|
else lock (key,value)
|
||||||
|
else lock (key,i_value)<->(key,top)
|
||||||
|
DB_NEXT
|
||||||
|
if (!initialized) call DB_FIRST, return
|
||||||
|
API_getoldcurrent (out o_key,out o_value)
|
||||||
|
run (out key, out value)
|
||||||
|
if found lock (o_key,o_value)<->(key,value)
|
||||||
|
else lock (o_key,o_value)<->(top,top)
|
||||||
|
DB_PREV
|
||||||
|
if (!initialized) call DB_LAST, return
|
||||||
|
API_getoldcurrent (out o_key, out o_value)
|
||||||
|
run (out key, out value)
|
||||||
|
if found lock (key,value)<->(o_key,o_value)
|
||||||
|
else lock (bottom,bottom)<->(o_key,o_value)
|
||||||
|
DB_SET (in key)
|
||||||
|
run (out value)
|
||||||
|
if found lock (key,value)
|
||||||
|
else lock (key,bottom)<->(key,top)
|
||||||
|
DB_SET_RANGE (in i_key)
|
||||||
|
run (out key, out value)
|
||||||
|
if found lock (i_key, bottom)<->(key,value)
|
||||||
|
else lock (i_key, bottom)<->(top,top)
|
||||||
|
DB_NEXT_NODUP *** Does this return EINVAL?
|
||||||
|
***Alg that overblocks
|
||||||
|
if (!initialized) call DB_FIRST, return
|
||||||
|
API_getoldcurrent (out o_key,out o_value)
|
||||||
|
run (out key, out value)
|
||||||
|
if found lock (o_key,o_value)<->(key,value)
|
||||||
|
else lock (o_key,o_value)<->(top,top)
|
||||||
|
|
||||||
|
***'Optimization to not overblock'.. may require a 'supertop' instead of top however.
|
||||||
|
if (!initialized) call DB_FIRST, return
|
||||||
|
API_getoldcurrent (out o_key,out o_value)
|
||||||
|
run (out key, out value)
|
||||||
|
if found lock (o_key,top)<->(key,value) ********** Can I just use regular top? I think so! Won't hurt reads.. check writes
|
||||||
|
else lock (o_key,top)<->(top,top) ********** Can I just use regular top? I think so! Won't hurt reads.. check wirtes
|
||||||
|
DB_NEXT_DUP
|
||||||
|
API_getoldcurrent (out o_value)
|
||||||
|
run (out key, out value) //key == o_key so no need for it.
|
||||||
|
if found lock (key,o_value)<->(key,value)
|
||||||
|
else lock (key,o_value)<->(key,top)
|
||||||
|
DB_PREV_NODUP
|
||||||
|
***Alg that overblocks
|
||||||
|
if (!initialized) call DB_LAST, return
|
||||||
|
API_getoldcurrent (out o_key,out o_value)
|
||||||
|
run (out key, out value)
|
||||||
|
if found lock (key,value)<->(o_key,o_value)
|
||||||
|
else lock (bottom,bottom)<->(o_key,o_value)
|
||||||
|
|
||||||
|
***'Optimization to not overblock'.. may require a 'superbottom' instead of bottom however.
|
||||||
|
if (!initialized) call DB_FIRST, return
|
||||||
|
API_getoldcurrent (out o_key,out o_value)
|
||||||
|
run (out key, out value)
|
||||||
|
if found lock (key,value)<->(o_key,bottom) ********** Can I just use regular bottom? I think so! Won't hurt reads.. check writes
|
||||||
|
else lock (bottom,bottom)<->(o_key,bottom) ********** Can I just use regular bottom? I think so! Won't hurt reads.. check wirtes
|
||||||
|
Put
|
||||||
|
Default/0
|
||||||
|
EINVAL (EASY)
|
||||||
|
NoOverwrite (in key, in value)
|
||||||
|
writelock (key,value)
|
||||||
|
run
|
||||||
|
|
||||||
|
optimization alternative
|
||||||
|
get DB_GET_BOTH (key,value)
|
||||||
|
if found done
|
||||||
|
else call YesOverwrite(key,value)
|
||||||
|
YesOverwrite
|
||||||
|
writelock (key,value)
|
||||||
|
run
|
||||||
|
Del
|
||||||
|
Default/0 (in key)
|
||||||
|
writelock (key,bottom)<->(key,top) //Technically conflicts with NEXT_NODUP and PREV_NODUP, but ONLY with the same txn,
|
||||||
|
//so no problem, since anyone holding top/bottom has a read lock inside that key as well.
|
||||||
|
run
|
||||||
|
|
||||||
|
optimization alternative
|
||||||
|
get
|
||||||
|
if !found done
|
||||||
|
else call DeleteAny
|
||||||
|
DeleteAny
|
||||||
|
writelock (key,bottom)<->(key,top) //Technically conflicts with NEXT_NODUP and PREV_NODUP, but ONLY with the same txn,
|
||||||
|
//so no problem, since anyone holding top/bottom has a read lock inside that key as well.
|
||||||
|
run
|
||||||
|
c_del
|
||||||
|
API_getoldcurrent (out key, out value)
|
||||||
|
writelock (key,value)
|
||||||
|
run
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Whenever a lock fails rollback (just current op) and quit
|
||||||
|
|
||||||
|
Several forms of locks.
|
||||||
|
Write Locks
|
||||||
|
Exact key (exists in db)
|
||||||
|
Exact key (May or may not exist in db)
|
||||||
|
open range between two entries (two sides will be exact and exist or not)
|
||||||
|
Read Locks
|
||||||
|
Exact key (exists in db)
|
||||||
|
Exact key (May or may not exist in db)
|
||||||
|
open range between two entries (two sides will be exact and exist or not)
|
||||||
|
|
||||||
|
Locking an exact key inside an open range requires you to split the range.
|
||||||
|
i.e.
|
||||||
|
Things 'underlined' with '-'s are read locks.
|
||||||
|
Things 'underlined' with '+'s are write locks
|
||||||
|
Our standard database is All letters of the alphabet. (Values are equal to the keys.
|
||||||
|
We may show a subset of that if it is not necessary for the example.
|
||||||
|
|
||||||
|
A B C
|
||||||
|
-(-)
|
||||||
|
|
||||||
|
Add lock on B1 changes the lock tree to:
|
||||||
|
|
||||||
|
A B B1 C
|
||||||
|
-(-)--(-)
|
||||||
|
A
|
||||||
|
|
||||||
|
|
||||||
|
NODUP in DB
|
||||||
|
get
|
||||||
|
DEFAULT (in key)
|
||||||
|
Input: key. Returns key and value if (key,vale) is in the db. Else returns DB_NOTFOUND.
|
||||||
|
Procedure
|
||||||
|
run the regular 'get' call.
|
||||||
|
If found, acquire exact read lock on key.
|
||||||
|
else, acquire open range at key.
|
||||||
|
Ex
|
||||||
|
get (B) transforms
|
||||||
|
A B C
|
||||||
|
to
|
||||||
|
A B C
|
||||||
|
-
|
||||||
|
|
||||||
|
get (B1) transforms
|
||||||
|
A B C
|
||||||
|
to
|
||||||
|
A B C
|
||||||
|
(-)
|
||||||
|
DB_GET_BOTH (in key)
|
||||||
|
Input: (key,value). Retrieves key from db. If it exists, and tests value found for equality with input value,
|
||||||
|
Procedure
|
||||||
|
Run the regular 'get' call.
|
||||||
|
If found lock exact key
|
||||||
|
else lock open range for key
|
||||||
|
test for equality/return
|
||||||
|
Ex
|
||||||
|
getDB_GET_BOTH (B,B) transforms
|
||||||
|
(A,A) (B,B) (C,C)
|
||||||
|
to
|
||||||
|
(A,A) (B,B) (C,C)
|
||||||
|
-----
|
||||||
|
getDB_GET_BOTH (B,V) transforms
|
||||||
|
(A,A) (B,B) (C,C)
|
||||||
|
to
|
||||||
|
(A,A) (B,B) (C,C)
|
||||||
|
-----
|
||||||
|
getDB_GET_BOTH (B1,V) transforms
|
||||||
|
(A,A) (B,B) (C,C)
|
||||||
|
to
|
||||||
|
(A,A) (B,B) (C,C)
|
||||||
|
(-)
|
||||||
|
c_get
|
||||||
|
DB_CURRENT (in void)
|
||||||
|
Returns what the cursor is already pointing to.
|
||||||
|
Note that a single cursor is binded to a single transaction.
|
||||||
|
Whatever the cursor points to must already be locked since we managed
|
||||||
|
to get a cursor to point to it.
|
||||||
|
|
||||||
|
Nothing needs to be done to get this to work.
|
||||||
|
DB_FIRST
|
||||||
|
Retrieves the minimum element in the db.
|
||||||
|
Procedure
|
||||||
|
Run c_getDB_FIRST (retrieves key,value)
|
||||||
|
if found lock key
|
||||||
|
else lock entire db (open range from bottom to top)
|
||||||
|
Ex
|
||||||
|
cgetDB_FIRST transforms
|
||||||
|
A B C
|
||||||
|
to
|
||||||
|
A B C
|
||||||
|
-
|
||||||
|
cgetDB_FIRST transforms
|
||||||
|
(empty db)
|
||||||
|
to
|
||||||
|
(empty db)
|
||||||
|
(--------)
|
||||||
|
DB_LAST
|
||||||
|
Retrieves the maximum element in the db.
|
||||||
|
Procedure
|
||||||
|
Run c_getDB_LAST (retrieves key,value)
|
||||||
|
if found lock key
|
||||||
|
else lock entire db (open range from bottom to top)
|
||||||
|
Ex
|
||||||
|
cgetDB_LAST transforms
|
||||||
|
A B C ..... X Y Z
|
||||||
|
to
|
||||||
|
A B C ..... X Y Z
|
||||||
|
-
|
||||||
|
cgetDB_LAST transforms
|
||||||
|
(empty db)
|
||||||
|
to
|
||||||
|
(empty db)
|
||||||
|
(--------)
|
||||||
|
DB_GET_BOTH (in key)
|
||||||
|
Runs getDB_GET_BOTH, and if it is found and value matches, returns a cursor to it.
|
||||||
|
See getDB_GET_BOTH.
|
||||||
|
DB_GET_BOTH_RANGE (in key)
|
||||||
|
For non-dupsort databases, this is the same as c_getDB_GET_BOTH
|
||||||
|
DB_NEXT
|
||||||
|
On an initialized cursor, does a successor query on the current element.
|
||||||
|
On an uninitialized cursor, it calls c_getDB_FIRST
|
||||||
|
Note that what the cursor originally points to is locked prior to this call.
|
||||||
|
Procedure
|
||||||
|
if (!initialized) call DB_FIRST, return
|
||||||
|
run cgetDB_NEXT (retrieves key,value)
|
||||||
|
if found lock key, locks open range before key
|
||||||
|
else lock open range at end of db
|
||||||
|
Ex
|
||||||
|
cgetDB_NEXT transforms
|
||||||
|
A (B) C
|
||||||
|
---
|
||||||
|
to
|
||||||
|
A B (C)
|
||||||
|
-(-)---
|
||||||
|
cgetDB_NEXT transforms
|
||||||
|
A B (C)
|
||||||
|
-(-)---
|
||||||
|
to
|
||||||
|
A B C
|
||||||
|
-(-)-(-)
|
||||||
|
DB_PREV
|
||||||
|
Opposite of cgetDB_NEXT (runs DB_LAST if uninitialized, runs pred query otherwise)
|
||||||
|
Note that what the cursor originally points to is locked prior to this call.
|
||||||
|
Procedure
|
||||||
|
if (!initialized) call DB_LAST, return
|
||||||
|
run cgetDB_PREV (retrieves key,value)
|
||||||
|
if found lock key, locks open range after key
|
||||||
|
else lock open range at start of db
|
||||||
|
Ex
|
||||||
|
cgetDB_PREV transforms
|
||||||
|
A (B) C
|
||||||
|
---
|
||||||
|
to
|
||||||
|
(A) B C
|
||||||
|
---(-)-
|
||||||
|
cgetDB_PREV transforms
|
||||||
|
(A) B C
|
||||||
|
---(-)-
|
||||||
|
to
|
||||||
|
A B C
|
||||||
|
(-)-(-)-
|
||||||
|
DB_SET (in key)
|
||||||
|
Runs get, and if it is found, returns a cursor to it.
|
||||||
|
See get.
|
||||||
|
DB_SET_RANGE (in i_key)
|
||||||
|
Retrieves the least upper bound of input (key) as a cursor.
|
||||||
|
Procedure
|
||||||
|
run cgetDB_SET_RANGE(i_key), retrieves key or returns DB_NOTFOUND
|
||||||
|
if found
|
||||||
|
if (i_key != key) lock key, lock open range before key
|
||||||
|
else lock key
|
||||||
|
else lock open range at i_key
|
||||||
|
Ex
|
||||||
|
cgetDB_SET_RANGE(B) transforms
|
||||||
|
A B C
|
||||||
|
to
|
||||||
|
A (B) C
|
||||||
|
---
|
||||||
|
cgetDB_SET_RANGE(B1) transforms
|
||||||
|
A B C
|
||||||
|
to
|
||||||
|
A B (C)
|
||||||
|
(-)---
|
||||||
|
cgetDB_SET_RANGE(Z1) transforms
|
||||||
|
A ... X Y Z
|
||||||
|
to
|
||||||
|
A ... X Y Z
|
||||||
|
(-)
|
||||||
|
DB_NEXT_NODUP
|
||||||
|
Same as cgetDB_NEXT (for non dupsort dbs)
|
||||||
|
call DB_NEXT, return
|
||||||
|
DB_NEXT_DUP
|
||||||
|
returns EINVAL for non dupsort dbs
|
||||||
|
DB_PREV_NODUP
|
||||||
|
Same as cgetDB_PREV (for non dupsort dbs)
|
||||||
|
Put
|
||||||
|
Default/0 (in key)
|
||||||
|
Identical to putDB_YESOVERWRITE for non dupsort dbs.
|
||||||
|
DB_NODUPDATA
|
||||||
|
(Currently not implemented)
|
||||||
|
Invalid for non dupsort dbs.
|
||||||
|
DB_NOOVERWRITE
|
||||||
|
Inserts (key,value) into the db if the key does not exist in the db. Returns error otherwise.
|
||||||
|
Procedure
|
||||||
|
call get (key) (This may create read locks)
|
||||||
|
If found, return DB_KEYEXISTS
|
||||||
|
else call putDB_YESOVERWRITE
|
||||||
|
Ex
|
||||||
|
putDB_NOOVERWRITE (A) transforms
|
||||||
|
A B C
|
||||||
|
to
|
||||||
|
A B C
|
||||||
|
-
|
||||||
|
and returns DB_KEYEXIST
|
||||||
|
|
||||||
|
putDB_NOOVERWRITE (A1) transforms
|
||||||
|
A B C
|
||||||
|
to
|
||||||
|
A A1 B C
|
||||||
|
--
|
||||||
|
++
|
||||||
|
DB_YESOVERWRITE
|
||||||
|
Inserts (key,value) into the db. If it already exists, it will overwrite it.
|
||||||
|
Procedure
|
||||||
|
writelock key
|
||||||
|
Run putDB_YESOVERWRITE
|
||||||
|
Ex
|
||||||
|
putDB_YESOVERWRITE (A) transforms
|
||||||
|
A B C
|
||||||
|
to
|
||||||
|
A B C
|
||||||
|
+
|
||||||
|
putDB_YESOVERWRITE (A1) transforms
|
||||||
|
A B C
|
||||||
|
to
|
||||||
|
A A1 B C
|
||||||
|
++
|
||||||
|
Del
|
||||||
|
Default/0 (in key)
|
||||||
|
Delete key, but report whether it was there in the first place.
|
||||||
|
Procedure
|
||||||
|
call get (key) (This may create read locks)
|
||||||
|
if !found, return DB_NOTFOUND
|
||||||
|
else call delDB_DELETE_ANY
|
||||||
|
Ex
|
||||||
|
del(A) transforms
|
||||||
|
A B C
|
||||||
|
to
|
||||||
|
[A] B C [] in this case means it is not in the db.
|
||||||
|
---
|
||||||
|
+++
|
||||||
|
|
||||||
|
del(A1) transforms
|
||||||
|
A B C
|
||||||
|
to
|
||||||
|
A B C
|
||||||
|
(-)
|
||||||
|
DB_DELETE_ANY
|
||||||
|
Delete key from db. Do not report (thus saving a search).
|
||||||
|
Procedure
|
||||||
|
writelock key
|
||||||
|
run the actual delete
|
||||||
|
delDB_DELETE_ANY (A) transforms
|
||||||
|
A B C
|
||||||
|
to
|
||||||
|
[A] B C
|
||||||
|
+++
|
||||||
|
delDB_DELETE_ANY (A1) transforms
|
||||||
|
A B C
|
||||||
|
to
|
||||||
|
A [A1] B C
|
||||||
|
++++
|
||||||
|
c_del
|
||||||
|
Deletes what a cursor is pointing to from the db.
|
||||||
|
Procedure
|
||||||
|
API_getoldcurrent (out key) (gets the old value of the key)
|
||||||
|
writelock key
|
||||||
|
delete it.
|
||||||
|
Ex
|
||||||
|
c_del transforms
|
||||||
|
A (B) C
|
||||||
|
---
|
||||||
|
to
|
||||||
|
A ([B]) C
|
||||||
|
+++++
|
||||||
|
DUPSORT db
|
||||||
|
get
|
||||||
|
DEFAULT (in key)
|
||||||
|
Searches for the lowest value for the given key. (Returns key,value if found) else returns DB_NOTFOUND.
|
||||||
|
Procedure
|
||||||
|
run the regular 'get' call.
|
||||||
|
If found, acquire exact read lock on (key,value) and open range before
|
||||||
|
else, acquire open range at (key,value).
|
||||||
|
|
||||||
|
NOTE: Since it finds the first one.. do we also need to lock the open range between (key,bottom) and (key,value)???
|
||||||
|
Ex
|
||||||
|
get (B) transforms
|
||||||
|
A,V B,V C,V
|
||||||
|
to
|
||||||
|
A,V B,V C,V
|
||||||
|
(-)---
|
||||||
|
|
||||||
|
get (B1) transforms
|
||||||
|
A B C
|
||||||
|
to
|
||||||
|
A B C
|
||||||
|
(-)
|
||||||
|
DB_GET_BOTH (in key)
|
||||||
|
Input: (key,value). Retrieves key from db. If it exists, and tests value found for equality with input value,
|
||||||
|
Procedure
|
||||||
|
Run the regular 'get' call.
|
||||||
|
If found lock exact key
|
||||||
|
else lock open range for key
|
||||||
|
test for equality/return
|
||||||
|
Ex
|
||||||
|
getDB_GET_BOTH (B,B) transforms
|
||||||
|
(A,A) (B,B) (C,C)
|
||||||
|
to
|
||||||
|
(A,A) (B,B) (C,C)
|
||||||
|
-----
|
||||||
|
getDB_GET_BOTH (B,V) transforms
|
||||||
|
(A,A) (B,B) (C,C)
|
||||||
|
to
|
||||||
|
(A,A) (B,B) (C,C)
|
||||||
|
-----
|
||||||
|
getDB_GET_BOTH (B1,V) transforms
|
||||||
|
(A,A) (B,B) (C,C)
|
||||||
|
to
|
||||||
|
(A,A) (B,B) (C,C)
|
||||||
|
(-)
|
||||||
|
c_get
|
||||||
|
DB_CURRENT (in void)
|
||||||
|
Returns what the cursor is already pointing to.
|
||||||
|
Note that a single cursor is binded to a single transaction.
|
||||||
|
Whatever the cursor points to must already be locked since we managed
|
||||||
|
to get a cursor to point to it.
|
||||||
|
|
||||||
|
Nothing needs to be done to get this to work.
|
||||||
|
DB_FIRST
|
||||||
|
Retrieves the minimum element in the db.
|
||||||
|
Procedure
|
||||||
|
Run c_getDB_FIRST (retrieves key,value)
|
||||||
|
if found lock key
|
||||||
|
else lock entire db (open range from bottom to top)
|
||||||
|
Ex
|
||||||
|
cgetDB_FIRST transforms
|
||||||
|
A B C
|
||||||
|
to
|
||||||
|
A B C
|
||||||
|
-
|
||||||
|
cgetDB_FIRST transforms
|
||||||
|
(empty db)
|
||||||
|
to
|
||||||
|
(empty db)
|
||||||
|
(--------)
|
||||||
|
DB_LAST
|
||||||
|
Retrieves the maximum element in the db.
|
||||||
|
Procedure
|
||||||
|
Run c_getDB_LAST (retrieves key,value)
|
||||||
|
if found lock key
|
||||||
|
else lock entire db (open range from bottom to top)
|
||||||
|
Ex
|
||||||
|
cgetDB_LAST transforms
|
||||||
|
A B C ..... X Y Z
|
||||||
|
to
|
||||||
|
A B C ..... X Y Z
|
||||||
|
-
|
||||||
|
cgetDB_LAST transforms
|
||||||
|
(empty db)
|
||||||
|
to
|
||||||
|
(empty db)
|
||||||
|
(--------)
|
||||||
|
DB_GET_BOTH (in key)
|
||||||
|
Runs getDB_GET_BOTH, and if it is found and value matches, returns a cursor to it.
|
||||||
|
See getDB_GET_BOTH.
|
||||||
|
DB_GET_BOTH_RANGE (in key) ************************* 3 cases.. did not find ->read open interval, found exact->lock exact, found different ->lock exact and open before
|
||||||
|
For non-dupsort databases, this is the same as c_getDB_GET_BOTH
|
||||||
|
DB_NEXT
|
||||||
|
On an initialized cursor, does a successor query on the current element.
|
||||||
|
On an uninitialized cursor, it calls c_getDB_FIRST
|
||||||
|
Note that what the cursor originally points to is locked prior to this call.
|
||||||
|
Procedure
|
||||||
|
if (!initialized) call DB_FIRST, return
|
||||||
|
run cgetDB_NEXT (retrieves key,value)
|
||||||
|
if found lock key, locks open range before key
|
||||||
|
else lock open range at end of db
|
||||||
|
Ex
|
||||||
|
cgetDB_NEXT transforms
|
||||||
|
A (B) C
|
||||||
|
---
|
||||||
|
to
|
||||||
|
A B (C)
|
||||||
|
-(-)---
|
||||||
|
cgetDB_NEXT transforms
|
||||||
|
A B (C)
|
||||||
|
-(-)---
|
||||||
|
to
|
||||||
|
A B C
|
||||||
|
-(-)-(-)
|
||||||
|
DB_PREV
|
||||||
|
Opposite of cgetDB_NEXT (runs DB_LAST if uninitialized, runs pred query otherwise)
|
||||||
|
Note that what the cursor originally points to is locked prior to this call.
|
||||||
|
Procedure
|
||||||
|
if (!initialized) call DB_LAST, return
|
||||||
|
run cgetDB_PREV (retrieves key,value)
|
||||||
|
if found lock key, locks open range after key
|
||||||
|
else lock open range at start of db
|
||||||
|
Ex
|
||||||
|
cgetDB_PREV transforms
|
||||||
|
A (B) C
|
||||||
|
---
|
||||||
|
to
|
||||||
|
(A) B C
|
||||||
|
---(-)-
|
||||||
|
cgetDB_PREV transforms
|
||||||
|
(A) B C
|
||||||
|
---(-)-
|
||||||
|
to
|
||||||
|
A B C
|
||||||
|
(-)-(-)-
|
||||||
|
DB_SET (in key)
|
||||||
|
Runs get, and if it is found, returns a cursor to it.
|
||||||
|
See get.
|
||||||
|
DB_SET_RANGE (in i_key) **************ALWAYS key AND open range
|
||||||
|
Retrieves the least upper bound of input (key) as a cursor.
|
||||||
|
Procedure
|
||||||
|
run cgetDB_SET_RANGE(i_key), retrieves key or returns DB_NOTFOUND
|
||||||
|
if found
|
||||||
|
if (i_key != key) lock key, lock open range before key
|
||||||
|
else lock key
|
||||||
|
else lock open range at i_key
|
||||||
|
Ex
|
||||||
|
cgetDB_SET_RANGE(B) transforms
|
||||||
|
A B C
|
||||||
|
to
|
||||||
|
A (B) C
|
||||||
|
---
|
||||||
|
cgetDB_SET_RANGE(B1) transforms
|
||||||
|
A B C
|
||||||
|
to
|
||||||
|
A B (C)
|
||||||
|
(-)---
|
||||||
|
cgetDB_SET_RANGE(Z1) transforms
|
||||||
|
A ... X Y Z
|
||||||
|
to
|
||||||
|
A ... X Y Z
|
||||||
|
(-)
|
||||||
|
DB_NEXT_NODUP ***** lock the exact, and open range from new till prev(new).
|
||||||
|
Same as cgetDB_NEXT (for non dupsort dbs)
|
||||||
|
call DB_NEXT, return
|
||||||
|
DB_NEXT_DUP ***** same as DB_NEXT (for nodups) except if key of successor is different, lock open range.
|
||||||
|
returns EINVAL for non dupsort dbs
|
||||||
|
DB_PREV_NODUP *** trivially create from DB_NEXT_NODUP
|
||||||
|
Same as cgetDB_PREV (for non dupsort dbs)
|
||||||
|
Put
|
||||||
|
Default/0 (in key) *** EINVAL
|
||||||
|
Identical to putDB_YESOVERWRITE for non dupsort dbs.
|
||||||
|
DB_NODUPDATA **** delete cursor put NO_DUPDATA
|
||||||
|
(Currently not implemented)
|
||||||
|
Invalid for non dupsort dbs.
|
||||||
|
DB_NOOVERWRITE *** if exists, lock ANY (probably first) and return.
|
||||||
|
Inserts (key,value) into the db if the key does not exist in the db. Returns error otherwise.
|
||||||
|
Procedure
|
||||||
|
call get (key) (This may create read locks)
|
||||||
|
If found, return DB_KEYEXISTS
|
||||||
|
else call putDB_YESOVERWRITE
|
||||||
|
Ex
|
||||||
|
putDB_NOOVERWRITE (A) transforms
|
||||||
|
A B C
|
||||||
|
to
|
||||||
|
A B C
|
||||||
|
-
|
||||||
|
and returns DB_KEYEXIST
|
||||||
|
|
||||||
|
putDB_NOOVERWRITE (A1) transforms
|
||||||
|
A B C
|
||||||
|
to
|
||||||
|
A A1 B C
|
||||||
|
--
|
||||||
|
++
|
||||||
|
DB_YESOVERWRITE *** 'same' as nodups
|
||||||
|
Inserts (key,value) into the db. If it already exists, it will overwrite it.
|
||||||
|
Procedure
|
||||||
|
writelock key
|
||||||
|
Run putDB_YESOVERWRITE
|
||||||
|
Ex
|
||||||
|
putDB_YESOVERWRITE (A) transforms
|
||||||
|
A B C
|
||||||
|
to
|
||||||
|
A B C
|
||||||
|
+
|
||||||
|
putDB_YESOVERWRITE (A1) transforms
|
||||||
|
A B C
|
||||||
|
to
|
||||||
|
A A1 B C
|
||||||
|
++
|
||||||
|
Del
|
||||||
|
Default/0 (in key) *** find first 'b', then do pred, and then do nextnodup (don't use infinities yet)
|
||||||
|
Delete key, but report whether it was there in the first place.
|
||||||
|
Procedure
|
||||||
|
call get (key) (This may create read locks)
|
||||||
|
if !found, return DB_NOTFOUND
|
||||||
|
else call delDB_DELETE_ANY
|
||||||
|
Ex
|
||||||
|
del(A) transforms
|
||||||
|
A B C
|
||||||
|
to
|
||||||
|
[A] B C [] in this case means it is not in the db.
|
||||||
|
---
|
||||||
|
+++
|
||||||
|
|
||||||
|
del(A1) transforms
|
||||||
|
A B C
|
||||||
|
to
|
||||||
|
A B C
|
||||||
|
(-)
|
||||||
|
DB_DELETE_ANY **** need infinities. lock infinities
|
||||||
|
Delete key from db. Do not report (thus saving a search).
|
||||||
|
Procedure
|
||||||
|
writelock key
|
||||||
|
run the actual delete
|
||||||
|
delDB_DELETE_ANY (A) transforms
|
||||||
|
A B C
|
||||||
|
to
|
||||||
|
[A] B C
|
||||||
|
+++
|
||||||
|
delDB_DELETE_ANY (A1) transforms
|
||||||
|
A B C
|
||||||
|
to
|
||||||
|
A [A1] B C
|
||||||
|
++++
|
||||||
|
c_del *** same as nodups
|
||||||
|
Deletes what a cursor is pointing to from the db.
|
||||||
|
Procedure
|
||||||
|
API_getoldcurrent (out key) (gets the old value of the key)
|
||||||
|
writelock key
|
||||||
|
delete it.
|
||||||
|
Ex
|
||||||
|
c_del transforms
|
||||||
|
A (B) C
|
||||||
|
---
|
||||||
|
to
|
||||||
|
A ([B]) C
|
||||||
|
+++++
|
||||||
|
*/
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue