Commit d6820390 authored by Yoni Fogel's avatar Yoni Fogel

Addresses #596

Preliminary .h file, with perhaps all functions needed

git-svn-id: file:///svn/tokudb@3517 c7de825b-a66e-492c-adef-691d508d4ae1
parent ce2f9354
...@@ -3,108 +3,204 @@ ...@@ -3,108 +3,204 @@
#ident "Copyright (c) 2007 Tokutek Inc. All rights reserved." #ident "Copyright (c) 2007 Tokutek Inc. All rights reserved."
/* Each of these C++ templated items can be wrapped with a simple header that uses pure C. */ /* I'm writing this in C to demonstrate how it is used. We can implement it
template <typename ITEM_TYPE, typename EXTRA_RENUMBER> later either using void*s
struct OMS { or templates under the hood. */
/* Stuff */
OMSITEM* foo; /* I've made the following assumptions which very well might be wrong.
};
1: We are storing key/value pairs, not just keys.
1a: We want to abstract a key/value pair to an OMITEM.
2: OMITEM will NOT support telling you the index number (for now).
2a: Indexs (for purposes of logging) will be retrieved by an output
parameter.
3: The CALLER of the OMS functions own the memory of the DBTs.
The OM structure will copy the OMITEM, but
key.data and value.data will be owned by the caller
responsibility for freeing/etc belongs to the caller.
Should not free anything till its been removed from teh OMS.
4: I don't know what to call it so I'm just calling it 'oms_blah'
5: We do not need to do multiple interleaving iterations.
5a: If we do, we need to change prototypes, perhaps pass a status object along.
6: For inserting (with search), it will not replace already existing items
it will just report that it was already inside.
*/
/* This is my guess of what an OMITEM should be. */
typedef struct {
DBT key;
DBT value;
} OMITEM;
/*
Create an empty OMS.
Possible Error codes
0
ENOMEM
Will assert ptree, db, cmp are NOT NULL.
*/
int oms_create(OMS** ptree,
DB* db, int (*cmp)(DB*, const OMITEM*, const OMITEM*));
/*
Create an OMS containing the elements in a presorted array.
Possible Error codes
0
ENOMEM
Will assert ptree, db, cmp, items are NOT NULL.
*/
int oms_create_from_presorted_array(OMS** ptree, DB* db,
int (*cmp)(DB*, const OMITEM*, const OMITEM*),
OMITEM* items, u_int32_t num_items);
/*
Create an OMS containing presorted elements accessed by an iterator.
Possible Error codes
0
ENOMEM
Will assert ptree is NOT NULL.
NOTE: I'm using void* here cause I don't know what the parameters should be.
In the actual implementation I will use the real data types.
We can also change the iterator type, i.e. make it return int
and we get next via an output parameter.
Note: May just be a wrapper for oms_create_presorted_array.
/* The actual header would be written entirely in C, using wrapper functions, this is just a starting example. */ Will assert ptree, db, cmp, items are NOT NULL.
*/
int oms_create_from_presorted_iterator(OMS** ptree, DB* db,
int (*cmp)(DB*, const OMITEM*, const OMITEM*),
OMITEM* (*get_next)(void* param));
/*
Close/free an OMS.
Note: This will not free key.data/value.data for entries inside.
Those should be freed immediately before or after calling oms_destroy.
Will assert tree is NOT NULL.
*/
void oms_destroy(OMS* tree);
/*
NOTE: USES THE COMPARISON FUNCTION
Initializes iteration over the tree.
if start is NULL, we start at the head, otherwise we search for it.
Searching requires a comparison function!
/* The templated functions are static and inline so the wrapper C functions don't add any overhead. */ Will assert tree is NOT NULL.
if not found, it will allow you to find
*/
void oms_init_iteration(OMS* tree, OMITEM* start);
/* /*
Questions/issues: Initializes iteration over the tree.
1- Do we really need to wrap items in an OMITEM<ITEM_TYPE> container? if start is NULL, we start at the head, otherwise we search for it.
I assume yes.. for example, the ITEM_TYPE could be a DBT, Searching requires a comparison function!
and the OMITEM<DBT*> would also hold the index (plus maybe additional stuff).
2- For a single OMS, do we need to support CHANGING the renumberf function? Will assert tree is NOT NULL.
i.e. won't it be the same function for every insert for a given OMS?
I'm assuming the renumberf function stays the same, so I provide it just Possible error codes
once in the constructor. 0
Actually, if the function is constant, and only the 'extra' can differ, ERANGE: If start_index >= the number of elements in the structure
it can be a template parameter and be even faster. */
3- Similarly to #2, will the 'extra info' to the renumberf function ever change? int oms_init_iteration_at(OMS* tree, u_int32_t start_index);
I'm assuming it stays the same for the duration of an OMS,
and am passing it to the constructor. /*
4- For 'insert_in_appropriate place', I know the comparison function is not always available Gets the next item in the tree.
So I'm giving it as a parameter to that function. When you go off the end, it returns NULL, as will subsequent calls.
5- Extra info to the comparison function. This can change (for the lock tree),
so its a parameter to the functoins that use comparisons. Use oms_init_iteration(_at) to reset the iterator.
6- Do we need some way of 'loading' an order maintenance structure? */
i.e. use these tags for the following items instead of 'inserting' over and over. OMITEM* oms_get_next(OMS* tree);
7- The tag might not be able to be just 64 bits, is it ok to use 2 64 bit ints?
/*
NOTE: USES THE COMPARISON FUNCTION
What we don't understand: Insert an item at the appropriate place.
* A separate order maintenance structure for each node, or for each leaf? (Emailed)
* >When we insert a key-value pair into a BRT leaf, we need to log enough information to rebuild the leaf after a crash. Will assert tree, item, and already_exists are NOT NULL.
>And at the time of recovery, we don't have a comparison function. already_exists is an out parameter.
What is involved in rebuilding a node? If the exact OMITEM is already there, it will NOT be replaced,
Our guess is that the only thing necessary is: but we will report that.
1-Recreate _which_ elements were stored in it. Reports the index it was found at.
2-Recreate the _order_ of the elements stored in it.
Is there anything else? Possible error codes:
If that's it, it explains why we don't need an OMS for each node (just for each leaf). 0
Nodes only require #1, and when the elements are recreated the order doesn't matter (and can even change). ENOMEM
Is our guess correct? DB_KEYEXIST: If it already exists in the structure.
* forwards backwards idea? */
* int oms_insert(OMS* tree, OMITEM* item, u_int32_t* index);
1- What does the PMA hold? Does it hold pointers to DBTs, or it actually holds /*
the DBTs and their data in-line? Insert an item at a given index.
2- What is being logged, and why is it being logged that way?
Do we just store old and new slots in the PMA? Will assert tree, item, and already_exists are NOT NULL.
If so, what does that actually give us? already_exists is an out parameter.
Do we just serialize to disk by storing things in order? If the exact OMITEM is already there, it will NOT be replaced,
3- Logging: Do we really need to log ALL changes to tags, but we will report that.
or only enough to 'reconstruct' the OMS such that we have a comparison function?
First case gives us O(log n), second makes O(1) possible. Possible error codes:
(First case may be possible with O(1) but we'd have to devise a new algorithm) 0
ENOMEM
*/ */
int oms_insert_at(OMS* tree, OMITEM* item, u_int32_t index);
template <typename ITEM_TYPE, typename EXTRA_RENUMBER, typename EXTRA_CMP>
static inline int toku_oms_create(OMS<ITEM_TYPE, EXTRA_RENUMBER, EXTRA_CMP>** poms, /*
void (*renumberf)(OMITEM<ITEM_TYPE>*, u_int64_t old_index, u_int64_t new_index, EXTRA_RENUMBER* extra_for_renumberf), NOTE: USES THE COMPARISON FUNCTION
/* Additional parameters to pass to the callback function. */ Deletes a given item.
EXTRA_RENUMBER* extra_for_renumberf);
Will assert tree, item, and found are NOT NULL.
template <typename ITEM_TYPE, typename EXTRA_RENUMBER, typename EXTRA_CMP> Reports the index it was found at.
static inline int toku_oms_close(OMS<ITEM_TYPE, EXTRA_RENUMBER, EXTRA_CMP>* oms); Possible error codes:
0
static inline int toku_oms_insert(OMS* oms, /* The order maintenance structure. */ DB_NOTFOUND
*/
template <typename ITEM_TYPE, typename EXTRA_RENUMBER, typename EXTRA_CMP> int oms_delete(OMS* tree, OMITEM* item, u_int32_t* index);
static inline int toku_oms_insert(OMS<ITEM_TYPE, EXTRA_RENUMBER, EXTRA_CMP>* oms, /* The order maintenance structure. */
OMITEM<ITEM_TYPE>* prev_omi, /* Pass in NULL if the new item is at the head, otherwise pass in the predecessor. */ /*
DATA_ITEM* item); /* The user-provided data item. */ Deletes the item at a given index.
Possible error codes:
template <typename ITEM_TYPE, typename EXTRA_RENUMBER, typename EXTRA_CMP> 0
static inline int toku_oms_delete(OMS<ITEM_TYPE, EXTRA_RENUMBER, EXTRA_CMP>* oms, /* The order maintenance structure. */ ERANGE: If index >= num elements in the structure
OMSITEM<ITEM_TYPE>* to_remove); /* The user-provided data item. */ */
int oms_delete_at(OMS* tree, u_int32_t index);
/* This will use the comparison function to find the appropriate location, /*
and then call toku_oms_insert with the appropriate predecessor. */ I don't know what kind of 'finds' we need here.
static inline int toku_oms_insert_appropriately(OMS<ITEM_TYPE, EXTRA_RENUMBER, EXTRA_CMP>* oms, /* The order maintenance structure. */ */
DATA_ITEM* item, int oms_find(OMS* tree, OMITEM* item, u_int32_t find_flags);
void (*cmp)(EXTRA_CMP* extra_for_cmp, ITEM_TYPE*, ITEM_TYPE*),
/* Additional parameters to pass to the comparison function. */ /*
EXTRA_CMP* extra_for_cmp); Creates 2 new trees caused by splitting the current one evently.
Reports the split index.
Does NOT free the old one.
/* Example wrapper */ */
extern "C" { int oms_split_evenly(OMS* tree, OMS** pleft_tree, OMS** pright_tree,
int toku_node_node_oms_insert(toku_node_oms* oms, u_int32_t* index);
toku_node_omsitem* prev_omi,
DBT* item) { /*
return toku_oms_insert<toku_node_omsitem, DBT, int, DB>(oms, prev_omi, item); Creates 2 new trees caused by splitting the current one at the
} given index. (0..index-1) are in left, (index..end) are in right.
} Does NOT free the old one.
*/
int oms_split_at(OMS* tree, OMS** pleft_tree, OMS** pright_tree,
u_int32_t index);
/*
Creates one tree from merging 2 of them.
Does not free the old one.
reports the 'split index' that you would use to undo the operation.
*/
int oms_merge(OMS** ptree, OMS* left_tree, OMS* right_tree, u_int32_t* index);
u_int32_t oms_get_num_elements(OMS* tree);
#endif /* #ifndef OM_H */ #endif /* #ifndef OM_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment