Commit 816415fc authored by Leif Walsh's avatar Leif Walsh Committed by Yoni Fogel

refs #5206 remove indentation caused by namespace


git-svn-id: file:///svn/toku/tokudb@45942 c7de825b-a66e-492c-adef-691d508d4ae1
parent c010c1e5
...@@ -23,988 +23,988 @@ ...@@ -23,988 +23,988 @@
namespace toku { namespace toku {
template<typename omtdata_t, template<typename omtdata_t,
typename omtdataout_t=omtdata_t> typename omtdataout_t=omtdata_t>
struct omt { struct omt {
/** /**
* *
*/ */
void create(void) void create(void)
{ {
this->create_internal(2); this->create_internal(2);
} }
/** /**
* *
*/ */
void create_no_array(void) void create_no_array(void)
{ {
this->create_internal_no_array(0); this->create_internal_no_array(0);
} }
/** /**
* *
*/ */
void create_from_sorted_array(const omtdata_t *values, const uint32_t numvalues) void create_from_sorted_array(const omtdata_t *values, const uint32_t numvalues)
{ {
this->create_internal(numvalues); this->create_internal(numvalues);
memcpy(this->d.a.values, values, numvalues * (sizeof values[0])); memcpy(this->d.a.values, values, numvalues * (sizeof values[0]));
this->d.a.num_values = numvalues; this->d.a.num_values = numvalues;
} }
/** /**
* *
*/ */
__attribute__((nonnull(2))) __attribute__((nonnull(2)))
void create_steal_sorted_array(omtdata_t **const values, const uint32_t numvalues, const uint32_t capacity_) void create_steal_sorted_array(omtdata_t **const values, const uint32_t numvalues, const uint32_t capacity_)
{ {
invariant_notnull(values); invariant_notnull(values);
this->create_internal_no_array(capacity_); this->create_internal_no_array(capacity_);
this->d.a.num_values = numvalues; this->d.a.num_values = numvalues;
this->d.a.values = *values; this->d.a.values = *values;
*values = nullptr; *values = nullptr;
} }
/** /**
* *
*/ */
__attribute__((nonnull(2))) __attribute__((nonnull(2)))
void split_at(omt *const newomt, const uint32_t idx) { void split_at(omt *const newomt, const uint32_t idx) {
invariant_notnull(newomt); invariant_notnull(newomt);
if (idx > this->size()) { return EINVAL; } if (idx > this->size()) { return EINVAL; }
this->convert_to_array(); this->convert_to_array();
const uint32_t newsize = this->size() - idx; const uint32_t newsize = this->size() - idx;
newomt->create_from_sorted_array(&this->d.a.values[this->d.a.start_idx + idx], newsize); newomt->create_from_sorted_array(&this->d.a.values[this->d.a.start_idx + idx], newsize);
this->d.a.num_values = idx; this->d.a.num_values = idx;
this->maybe_resize_array(); this->maybe_resize_array();
} }
/** /**
* *
*/ */
__attribute__((nonnull(2,3))) __attribute__((nonnull(2,3)))
void merge(omt *const leftomt, omt *const rightomt) { void merge(omt *const leftomt, omt *const rightomt) {
invariant_notnull(leftomt); invariant_notnull(leftomt);
invariant_notnull(rightomt); invariant_notnull(rightomt);
const uint32_t leftsize = leftomt->size(); const uint32_t leftsize = leftomt->size();
const uint32_t rightsize = rightomt->size(); const uint32_t rightsize = rightomt->size();
const uint32_t newsize = leftsize + rightsize; const uint32_t newsize = leftsize + rightsize;
if (leftomt->is_array) { if (leftomt->is_array) {
if (leftomt->capacity - (leftomt->d.a.start_idx + leftomt->d.a.num_values) >= rightsize) { if (leftomt->capacity - (leftomt->d.a.start_idx + leftomt->d.a.num_values) >= rightsize) {
this->create_steal_sorted_array(leftomt->d.a.values, leftomt->d.a.num_values, leftomt->capacity); this->create_steal_sorted_array(leftomt->d.a.values, leftomt->d.a.num_values, leftomt->capacity);
this->d.a.start_idx = leftomt->d.a.start_idx; this->d.a.start_idx = leftomt->d.a.start_idx;
} else {
this->create_internal(newsize);
memcpy(&this->d.a.values[0],
&leftomt->d.a.values[leftomt->d.a.start_idx],
leftomt->d.a.num_values * (sizeof this->d.a.values[0]));
}
} else { } else {
this->create_internal(newsize); this->create_internal(newsize);
leftomt->fill_array_with_subtree_values(&this->d.a.values[0], leftomt->d.t.root); memcpy(&this->d.a.values[0],
} &leftomt->d.a.values[leftomt->d.a.start_idx],
leftomt->destroy(); leftomt->d.a.num_values * (sizeof this->d.a.values[0]));
this->d.a.num_values = leftsize; }
} else {
if (rightomt->is_array) { this->create_internal(newsize);
memcpy(&this->d.a.values[this->d.a.start_idx + this->d.a.num_values], leftomt->fill_array_with_subtree_values(&this->d.a.values[0], leftomt->d.t.root);
&rightomt->d.a.values[rightomt->d.a.start_idx], }
rightomt->d.a.num_values * (sizeof this->d.a.values[0])); leftomt->destroy();
} else { this->d.a.num_values = leftsize;
rightomt->fill_array_with_subtree_values(&this->d.a.values[this->d.a.start_idx + this->d.a.num_values],
rightomt->d.t.root); if (rightomt->is_array) {
} memcpy(&this->d.a.values[this->d.a.start_idx + this->d.a.num_values],
rightomt->destroy(); &rightomt->d.a.values[rightomt->d.a.start_idx],
this->d.a.num_values += rightsize; rightomt->d.a.num_values * (sizeof this->d.a.values[0]));
invariant(this->size() == newsize); } else {
} rightomt->fill_array_with_subtree_values(&this->d.a.values[this->d.a.start_idx + this->d.a.num_values],
rightomt->d.t.root);
/** }
* rightomt->destroy();
*/ this->d.a.num_values += rightsize;
void clone(const omt &src) invariant(this->size() == newsize);
{ }
this->create_internal(src.size());
if (src.is_array) { /**
memcpy(&this->d.a.values[0], &src.d.a.values[src.d.a.start_idx], src.d.a.num_values * (sizeof this->d.a.values[0])); *
} else { */
src.fill_array_with_subtree_values(&this->d.a.values[0], src.d.t.root); void clone(const omt &src)
} {
this->d.a.num_values = src.size(); this->create_internal(src.size());
} if (src.is_array) {
memcpy(&this->d.a.values[0], &src.d.a.values[src.d.a.start_idx], src.d.a.num_values * (sizeof this->d.a.values[0]));
/** } else {
* src.fill_array_with_subtree_values(&this->d.a.values[0], src.d.t.root);
*/ }
void deep_clone(const omt &src) this->d.a.num_values = src.size();
{ }
this->create_internal(src.size());
int r = src.iterate<omt, deep_clone_iter>(this); /**
lazy_assert_zero(r); *
this->d.a.num_values = src.size(); */
} void deep_clone(const omt &src)
{
/** this->create_internal(src.size());
* int r = src.iterate<omt, deep_clone_iter>(this);
*/ lazy_assert_zero(r);
void clear(void) this->d.a.num_values = src.size();
{ }
if (this->is_array) {
this->d.a.start_idx = 0; /**
this->d.a.num_values = 0; *
} else { */
this->d.t.root = NODE_NULL; void clear(void)
this->d.t.free_idx = 0; {
} if (this->is_array) {
} this->d.a.start_idx = 0;
this->d.a.num_values = 0;
/** } else {
* this->d.t.root = NODE_NULL;
*/ this->d.t.free_idx = 0;
void destroy(void) }
{ }
this->clear();
this->capacity = 0; /**
if (this->is_array) { *
if (this->d.a.values != nullptr) { */
toku_free(this->d.a.values); void destroy(void)
} {
this->d.a.values = nullptr; this->clear();
} else { this->capacity = 0;
if (this->d.t.nodes != nullptr) { if (this->is_array) {
toku_free(this->d.t.nodes); if (this->d.a.values != nullptr) {
} toku_free(this->d.a.values);
this->d.t.nodes = nullptr;
} }
} this->d.a.values = nullptr;
} else {
/** if (this->d.t.nodes != nullptr) {
* toku_free(this->d.t.nodes);
*/
inline uint32_t size(void) const
{
if (this->is_array) {
return this->d.a.num_values;
} else {
return this->nweight(this->d.t.root);
} }
this->d.t.nodes = nullptr;
}
}
/**
*
*/
inline uint32_t size(void) const
{
if (this->is_array) {
return this->d.a.num_values;
} else {
return this->nweight(this->d.t.root);
}
}
/**
*
*/
template<typename omtcmp_t,
int (*h)(const omtdata_t &, const omtcmp_t &)>
int insert(const omtdata_t &value, const omtcmp_t &v, uint32_t *idx)
{
int r;
uint32_t insert_idx;
r = this->find_zero<omtcmp_t, h>(v, nullptr, &insert_idx);
if (r==0) {
if (idx) *idx = insert_idx;
return DB_KEYEXIST;
} }
if (r != DB_NOTFOUND) return r;
/** if ((r = this->insert_at(value, insert_idx))) return r;
* if (idx) *idx = insert_idx;
*/
template<typename omtcmp_t,
int (*h)(const omtdata_t &, const omtcmp_t &)>
int insert(const omtdata_t &value, const omtcmp_t &v, uint32_t *idx)
{
int r;
uint32_t insert_idx;
r = this->find_zero<omtcmp_t, h>(v, nullptr, &insert_idx);
if (r==0) {
if (idx) *idx = insert_idx;
return DB_KEYEXIST;
}
if (r != DB_NOTFOUND) return r;
if ((r = this->insert_at(value, insert_idx))) return r; return 0;
if (idx) *idx = insert_idx; }
return 0; /**
*
*/
int insert_at(const omtdata_t &value, const uint32_t idx)
{
if (idx > this->size()) { return EINVAL; }
this->maybe_resize_or_convert(this->size() + 1);
if (this->is_array && idx != this->d.a.num_values &&
(idx != 0 || this->d.a.start_idx == 0)) {
this->convert_to_tree();
} }
if (this->is_array) {
/** if (idx == this->d.a.num_values) {
* this->d.a.values[this->d.a.start_idx + this->d.a.num_values] = value;
*/
int insert_at(const omtdata_t &value, const uint32_t idx)
{
if (idx > this->size()) { return EINVAL; }
this->maybe_resize_or_convert(this->size() + 1);
if (this->is_array && idx != this->d.a.num_values &&
(idx != 0 || this->d.a.start_idx == 0)) {
this->convert_to_tree();
}
if (this->is_array) {
if (idx == this->d.a.num_values) {
this->d.a.values[this->d.a.start_idx + this->d.a.num_values] = value;
}
else {
this->d.a.values[--this->d.a.start_idx] = value;
}
this->d.a.num_values++;
} }
else { else {
node_idx *rebalance_idx = nullptr; this->d.a.values[--this->d.a.start_idx] = value;
this->insert_internal(&this->d.t.root, value, idx, &rebalance_idx); }
if (rebalance_idx != nullptr) { this->d.a.num_values++;
this->rebalance(rebalance_idx); }
} else {
} node_idx *rebalance_idx = nullptr;
return 0; this->insert_internal(&this->d.t.root, value, idx, &rebalance_idx);
} if (rebalance_idx != nullptr) {
this->rebalance(rebalance_idx);
/** }
* }
*/ return 0;
int set_at(const omtdata_t &value, const uint32_t idx) }
{
if (idx >= this->size()) { return EINVAL; } /**
*
*/
int set_at(const omtdata_t &value, const uint32_t idx)
{
if (idx >= this->size()) { return EINVAL; }
if (this->is_array) {
this->set_at_internal_array(value, idx);
} else {
this->set_at_internal(this->d.t.root, value, idx);
}
return 0;
}
/**
*
*/
int delete_at(const uint32_t idx)
{
if (idx >= this->size()) { return EINVAL; }
this->maybe_resize_or_convert(this->size() - 1);
if (this->is_array && idx != 0 && idx != this->d.a.num_values - 1) {
this->convert_to_tree();
}
if (this->is_array) {
//Testing for 0 does not rule out it being the last entry.
//Test explicitly for num_values-1
if (idx != this->d.a.num_values - 1) {
this->d.a.start_idx++;
}
this->d.a.num_values--;
} else {
node_idx *rebalance_idx = nullptr;
this->delete_internal(&this->d.t.root, idx, nullptr, &rebalance_idx);
if (rebalance_idx != nullptr) {
this->rebalance(rebalance_idx);
}
}
return 0;
}
/**
*
*/
template<typename iterate_extra_t,
int (*f)(const omtdata_t &, const uint32_t, iterate_extra_t *const)>
int iterate(iterate_extra_t *const iterate_extra) const {
return this->iterate_on_range<iterate_extra_t, f>(0, this->size(), iterate_extra);
}
/**
*
*/
template<typename iterate_extra_t,
int (*f)(const omtdata_t &, const uint32_t, iterate_extra_t *const)>
int iterate_on_range(const uint32_t left, const uint32_t right, iterate_extra_t *const iterate_extra) const {
if (right > this->size()) { return EINVAL; }
if (this->is_array) {
return this->iterate_internal_array<iterate_extra_t, f>(left, right, iterate_extra);
}
return this->iterate_internal<iterate_extra_t, f>(left, right, this->d.t.root, 0, iterate_extra);
}
/**
*
*/
template<typename iterate_extra_t,
int (*f)(omtdata_t *, const uint32_t, iterate_extra_t *const)>
void iterate_ptr(iterate_extra_t *const iterate_extra) {
if (this->is_array) {
this->iterate_ptr_internal_array<iterate_extra_t, f>(0, this->size(), iterate_extra);
} else {
this->iterate_ptr_internal<iterate_extra_t, f>(0, this->size(), this->d.t.root, 0, iterate_extra);
}
}
void free_items(void) {
this->iterate_ptr<void, free_items_iter>(nullptr);
}
/**
*
*/
int fetch(const uint32_t idx, omtdataout_t *value) const
{
if (idx >= this->size()) { return EINVAL; }
if (this->is_array) {
this->fetch_internal_array(idx, value);
} else {
this->fetch_internal(this->d.t.root, idx, value);
}
return 0;
}
/**
*
*/
template<typename omtcmp_t,
int (*h)(const omtdata_t &, const omtcmp_t &)>
int find_zero(const omtcmp_t &extra, omtdataout_t *value, uint32_t *const idxp) const
{
uint32_t tmp_index;
uint32_t *const child_idxp = (idxp != nullptr) ? idxp : &tmp_index;
int r;
if (this->is_array) {
r = this->find_internal_zero_array<omtcmp_t, h>(extra, value, child_idxp);
}
else {
r = this->find_internal_zero<omtcmp_t, h>(this->d.t.root, extra, value, child_idxp);
}
return r;
}
/**
*
*/
template<typename omtcmp_t,
int (*h)(const omtdata_t &, const omtcmp_t &)>
int find(const omtcmp_t &extra, int direction, omtdataout_t *const value, uint32_t *const idxp) const
{
uint32_t tmp_index;
uint32_t *const child_idxp = (idxp != nullptr) ? idxp : &tmp_index;
if (direction == 0) {
abort();
} else if (direction < 0) {
if (this->is_array) { if (this->is_array) {
this->set_at_internal_array(value, idx); return this->find_internal_minus_array<omtcmp_t, h>(extra, value, child_idxp);
} else { } else {
this->set_at_internal(this->d.t.root, value, idx); return this->find_internal_minus<omtcmp_t, h>(this->d.t.root, extra, value, child_idxp);
}
return 0;
}
/**
*
*/
int delete_at(const uint32_t idx)
{
if (idx >= this->size()) { return EINVAL; }
this->maybe_resize_or_convert(this->size() - 1);
if (this->is_array && idx != 0 && idx != this->d.a.num_values - 1) {
this->convert_to_tree();
} }
} else {
if (this->is_array) { if (this->is_array) {
//Testing for 0 does not rule out it being the last entry. return this->find_internal_plus_array<omtcmp_t, h>(extra, value, child_idxp);
//Test explicitly for num_values-1
if (idx != this->d.a.num_values - 1) {
this->d.a.start_idx++;
}
this->d.a.num_values--;
} else { } else {
node_idx *rebalance_idx = nullptr; return this->find_internal_plus<omtcmp_t, h>(this->d.t.root, extra, value, child_idxp);
this->delete_internal(&this->d.t.root, idx, nullptr, &rebalance_idx);
if (rebalance_idx != nullptr) {
this->rebalance(rebalance_idx);
}
} }
return 0;
} }
}
/** /**
* *
*/ */
template<typename iterate_extra_t, size_t memory_size(void) {
int (*f)(const omtdata_t &, const uint32_t, iterate_extra_t *const)> if (this->is_array) {
int iterate(iterate_extra_t *const iterate_extra) const { return (sizeof *this) + this->capacity * (sizeof this->d.a.values[0]);
return this->iterate_on_range<iterate_extra_t, f>(0, this->size(), iterate_extra);
} }
return (sizeof *this) + this->capacity * (sizeof this->d.t.nodes[0]);
}
/** private:
* typedef uint32_t node_idx;
*/ enum {
template<typename iterate_extra_t, NODE_NULL = UINT32_MAX
int (*f)(const omtdata_t &, const uint32_t, iterate_extra_t *const)> };
int iterate_on_range(const uint32_t left, const uint32_t right, iterate_extra_t *const iterate_extra) const {
if (right > this->size()) { return EINVAL; }
if (this->is_array) {
return this->iterate_internal_array<iterate_extra_t, f>(left, right, iterate_extra);
}
return this->iterate_internal<iterate_extra_t, f>(left, right, this->d.t.root, 0, iterate_extra);
}
/** struct omt_node {
* uint32_t weight;
*/ node_idx left;
template<typename iterate_extra_t, node_idx right;
int (*f)(omtdata_t *, const uint32_t, iterate_extra_t *const)> omtdata_t value;
void iterate_ptr(iterate_extra_t *const iterate_extra) { } __attribute__((__packed__));
if (this->is_array) {
this->iterate_ptr_internal_array<iterate_extra_t, f>(0, this->size(), iterate_extra); struct omt_array {
} else { uint32_t start_idx;
this->iterate_ptr_internal<iterate_extra_t, f>(0, this->size(), this->d.t.root, 0, iterate_extra); uint32_t num_values;
} omtdata_t *values;
} };
void free_items(void) { struct omt_tree {
this->iterate_ptr<void, free_items_iter>(nullptr); node_idx root;
} node_idx free_idx;
struct omt_node *nodes;
};
/** bool is_array;
* uint32_t capacity;
*/ union {
int fetch(const uint32_t idx, omtdataout_t *value) const struct omt_array a;
{ struct omt_tree t;
if (idx >= this->size()) { return EINVAL; } } d;
if (this->is_array) {
this->fetch_internal_array(idx, value);
} else { void create_internal_no_array(const uint32_t capacity_) {
this->fetch_internal(this->d.t.root, idx, value); this->is_array = true;
} this->capacity = capacity_;
this->d.a.start_idx = 0;
this->d.a.num_values = 0;
this->d.a.values = nullptr;
}
void create_internal(const uint32_t capacity_) {
this->create_internal_no_array(capacity_);
XMALLOC_N(this->capacity, this->d.a.values);
}
inline uint32_t nweight(const node_idx idx) const {
if (idx == NODE_NULL) {
return 0; return 0;
} else {
return this->d.t.nodes[idx].weight;
} }
}
/** inline node_idx node_malloc(void) {
* invariant(this->d.t.free_idx < this->capacity);
*/ return this->d.t.free_idx++;
template<typename omtcmp_t, }
int (*h)(const omtdata_t &, const omtcmp_t &)>
int find_zero(const omtcmp_t &extra, omtdataout_t *value, uint32_t *const idxp) const
{
uint32_t tmp_index;
uint32_t *const child_idxp = (idxp != nullptr) ? idxp : &tmp_index;
int r;
if (this->is_array) {
r = this->find_internal_zero_array<omtcmp_t, h>(extra, value, child_idxp);
}
else {
r = this->find_internal_zero<omtcmp_t, h>(this->d.t.root, extra, value, child_idxp);
}
return r;
}
/** inline void node_free(const node_idx idx) {
* invariant(idx < this->capacity);
*/ }
template<typename omtcmp_t,
int (*h)(const omtdata_t &, const omtcmp_t &)>
int find(const omtcmp_t &extra, int direction, omtdataout_t *const value, uint32_t *const idxp) const
{
uint32_t tmp_index;
uint32_t *const child_idxp = (idxp != nullptr) ? idxp : &tmp_index;
if (direction == 0) {
abort();
} else if (direction < 0) {
if (this->is_array) {
return this->find_internal_minus_array<omtcmp_t, h>(extra, value, child_idxp);
} else {
return this->find_internal_minus<omtcmp_t, h>(this->d.t.root, extra, value, child_idxp);
}
} else {
if (this->is_array) {
return this->find_internal_plus_array<omtcmp_t, h>(extra, value, child_idxp);
} else {
return this->find_internal_plus<omtcmp_t, h>(this->d.t.root, extra, value, child_idxp);
}
}
}
/**
*
*/
size_t memory_size(void) {
if (this->is_array) {
return (sizeof *this) + this->capacity * (sizeof this->d.a.values[0]);
}
return (sizeof *this) + this->capacity * (sizeof this->d.t.nodes[0]);
}
private:
typedef uint32_t node_idx;
enum {
NODE_NULL = UINT32_MAX
};
struct omt_node {
uint32_t weight;
node_idx left;
node_idx right;
omtdata_t value;
} __attribute__((__packed__));
struct omt_array {
uint32_t start_idx;
uint32_t num_values;
omtdata_t *values;
};
struct omt_tree {
node_idx root;
node_idx free_idx;
struct omt_node *nodes;
};
bool is_array;
uint32_t capacity;
union {
struct omt_array a;
struct omt_tree t;
} d;
void create_internal_no_array(const uint32_t capacity_) {
this->is_array = true;
this->capacity = capacity_;
this->d.a.start_idx = 0;
this->d.a.num_values = 0;
this->d.a.values = nullptr;
}
void create_internal(const uint32_t capacity_) { inline void maybe_resize_array(const uint32_t n) {
this->create_internal_no_array(capacity_); const uint32_t new_size = n<=2 ? 4 : 2*n;
XMALLOC_N(this->capacity, this->d.a.values); const uint32_t room = this->capacity - this->d.a.start_idx;
}
inline uint32_t nweight(const node_idx idx) const { if (room < n || this->capacity / 2 >= new_size) {
if (idx == NODE_NULL) { omtdata_t *XMALLOC_N(new_size, tmp_values);
return 0; memcpy(tmp_values, &this->d.a.values[this->d.a.start_idx],
} else { this->d.a.num_values * (sizeof tmp_values[0]));
return this->d.t.nodes[idx].weight; this->d.a.start_idx = 0;
} this->capacity = new_size;
} toku_free(this->d.a.values);
this->d.a.values = tmp_values;
inline node_idx node_malloc(void) { }
invariant(this->d.t.free_idx < this->capacity); }
return this->d.t.free_idx++;
} __attribute__((nonnull(2)))
inline void fill_array_with_subtree_values(omtdata_t *const array, const node_idx tree_idx) const {
inline void node_free(const node_idx idx) { if (tree_idx==NODE_NULL) return;
invariant(idx < this->capacity); const omt_node &tree = this->d.t.nodes[tree_idx];
} this->fill_array_with_subtree_values(&array[0], tree.left);
array[this->nweight(tree.left)] = tree.value;
inline void maybe_resize_array(const uint32_t n) { this->fill_array_with_subtree_values(&array[this->nweight(tree.left) + 1], tree.right);
}
inline void convert_to_array(void) {
if (!this->is_array) {
const uint32_t num_values = this->size();
uint32_t new_size = 2*num_values;
new_size = new_size < 4 ? 4 : new_size;
omtdata_t *XMALLOC_N(new_size, tmp_values);
this->fill_array_with_subtree_values(tmp_values, this->d.t.root);
toku_free(this->d.t.nodes);
this->is_array = true;
this->capacity = new_size;
this->d.a.num_values = num_values;
this->d.a.values = tmp_values;
this->d.a.start_idx = 0;
}
}
__attribute__((nonnull(2,3)))
inline void rebuild_from_sorted_array(node_idx *const n_idxp, const omtdata_t *const values, const uint32_t numvalues) {
if (numvalues==0) {
*n_idxp = NODE_NULL;
} else {
const uint32_t halfway = numvalues/2;
const node_idx newidx = this->node_malloc();
omt_node *const newnode = &this->d.t.nodes[newidx];
newnode->weight = numvalues;
newnode->value = values[halfway];
*n_idxp = newidx; // update everything before the recursive calls so the second call can be a tail call.
this->rebuild_from_sorted_array(&newnode->left, &values[0], halfway);
this->rebuild_from_sorted_array(&newnode->right, &values[halfway+1], numvalues - (halfway+1));
}
}
inline void convert_to_tree(void) {
if (this->is_array) {
const uint32_t num_nodes = this->size();
uint32_t new_size = num_nodes*2;
new_size = new_size < 4 ? 4 : new_size;
omt_node *XMALLOC_N(new_size, new_nodes);
omtdata_t *const values = this->d.a.values;
omtdata_t *const tmp_values = &values[this->d.a.start_idx];
this->is_array = false;
this->d.t.nodes = new_nodes;
this->capacity = new_size;
this->d.t.free_idx = 0;
this->d.t.root = NODE_NULL;
this->rebuild_from_sorted_array(&this->d.t.root, tmp_values, num_nodes);
toku_free(values);
}
}
inline void maybe_resize_or_convert(const uint32_t n) {
if (this->is_array) {
this->maybe_resize_array(n);
} else {
const uint32_t new_size = n<=2 ? 4 : 2*n; const uint32_t new_size = n<=2 ? 4 : 2*n;
const uint32_t room = this->capacity - this->d.a.start_idx; const uint32_t num_nodes = this->nweight(this->d.t.root);
if ((this->capacity/2 >= new_size) ||
if (room < n || this->capacity / 2 >= new_size) { (this->d.t.free_idx >= this->capacity && num_nodes < n) ||
omtdata_t *XMALLOC_N(new_size, tmp_values); (this->capacity<n)) {
memcpy(tmp_values, &this->d.a.values[this->d.a.start_idx], this->convert_to_array();
this->d.a.num_values * (sizeof tmp_values[0]));
this->d.a.start_idx = 0;
this->capacity = new_size;
toku_free(this->d.a.values);
this->d.a.values = tmp_values;
}
}
__attribute__((nonnull(2)))
inline void fill_array_with_subtree_values(omtdata_t *const array, const node_idx tree_idx) const {
if (tree_idx==NODE_NULL) return;
const omt_node &tree = this->d.t.nodes[tree_idx];
this->fill_array_with_subtree_values(&array[0], tree.left);
array[this->nweight(tree.left)] = tree.value;
this->fill_array_with_subtree_values(&array[this->nweight(tree.left) + 1], tree.right);
}
inline void convert_to_array(void) {
if (!this->is_array) {
const uint32_t num_values = this->size();
uint32_t new_size = 2*num_values;
new_size = new_size < 4 ? 4 : new_size;
omtdata_t *XMALLOC_N(new_size, tmp_values);
this->fill_array_with_subtree_values(tmp_values, this->d.t.root);
toku_free(this->d.t.nodes);
this->is_array = true;
this->capacity = new_size;
this->d.a.num_values = num_values;
this->d.a.values = tmp_values;
this->d.a.start_idx = 0;
}
}
__attribute__((nonnull(2,3)))
inline void rebuild_from_sorted_array(node_idx *const n_idxp, const omtdata_t *const values, const uint32_t numvalues) {
if (numvalues==0) {
*n_idxp = NODE_NULL;
} else {
const uint32_t halfway = numvalues/2;
const node_idx newidx = this->node_malloc();
omt_node *const newnode = &this->d.t.nodes[newidx];
newnode->weight = numvalues;
newnode->value = values[halfway];
*n_idxp = newidx; // update everything before the recursive calls so the second call can be a tail call.
this->rebuild_from_sorted_array(&newnode->left, &values[0], halfway);
this->rebuild_from_sorted_array(&newnode->right, &values[halfway+1], numvalues - (halfway+1));
}
}
inline void convert_to_tree(void) {
if (this->is_array) {
const uint32_t num_nodes = this->size();
uint32_t new_size = num_nodes*2;
new_size = new_size < 4 ? 4 : new_size;
omt_node *XMALLOC_N(new_size, new_nodes);
omtdata_t *const values = this->d.a.values;
omtdata_t *const tmp_values = &values[this->d.a.start_idx];
this->is_array = false;
this->d.t.nodes = new_nodes;
this->capacity = new_size;
this->d.t.free_idx = 0;
this->d.t.root = NODE_NULL;
this->rebuild_from_sorted_array(&this->d.t.root, tmp_values, num_nodes);
toku_free(values);
}
}
inline void maybe_resize_or_convert(const uint32_t n) {
if (this->is_array) {
this->maybe_resize_array(n);
} else {
const uint32_t new_size = n<=2 ? 4 : 2*n;
const uint32_t num_nodes = this->nweight(this->d.t.root);
if ((this->capacity/2 >= new_size) ||
(this->d.t.free_idx >= this->capacity && num_nodes < n) ||
(this->capacity<n)) {
this->convert_to_array();
}
} }
} }
}
inline bool will_need_rebalance(const node_idx n_idx, const int leftmod, const int rightmod) const {
if (n_idx==NODE_NULL) { return false; } inline bool will_need_rebalance(const node_idx n_idx, const int leftmod, const int rightmod) const {
const omt_node &n = this->d.t.nodes[n_idx]; if (n_idx==NODE_NULL) { return false; }
// one of the 1's is for the root. const omt_node &n = this->d.t.nodes[n_idx];
// the other is to take ceil(n/2) // one of the 1's is for the root.
const uint32_t weight_left = this->nweight(n.left) + leftmod; // the other is to take ceil(n/2)
const uint32_t weight_right = this->nweight(n.right) + rightmod; const uint32_t weight_left = this->nweight(n.left) + leftmod;
return ((1+weight_left < (1+1+weight_right)/2) const uint32_t weight_right = this->nweight(n.right) + rightmod;
|| return ((1+weight_left < (1+1+weight_right)/2)
(1+weight_right < (1+1+weight_left)/2)); ||
} (1+weight_right < (1+1+weight_left)/2));
}
__attribute__((nonnull(5)))
inline void insert_internal(node_idx *n_idxp, const omtdata_t &value, const uint32_t idx, node_idx **const rebalance_idx) { __attribute__((nonnull(5)))
if (*n_idxp == NODE_NULL) { inline void insert_internal(node_idx *n_idxp, const omtdata_t &value, const uint32_t idx, node_idx **const rebalance_idx) {
invariant_zero(idx); if (*n_idxp == NODE_NULL) {
const node_idx newidx = this->node_malloc(); invariant_zero(idx);
omt_node *const newnode = &this->d.t.nodes[newidx]; const node_idx newidx = this->node_malloc();
newnode->weight = 1; omt_node *const newnode = &this->d.t.nodes[newidx];
newnode->left = NODE_NULL; newnode->weight = 1;
newnode->right = NODE_NULL; newnode->left = NODE_NULL;
newnode->value = value; newnode->right = NODE_NULL;
*n_idxp = newidx; newnode->value = value;
} else { *n_idxp = newidx;
const node_idx thisidx = *n_idxp; } else {
omt_node *const n = &this->d.t.nodes[thisidx]; const node_idx thisidx = *n_idxp;
n->weight++; omt_node *const n = &this->d.t.nodes[thisidx];
if (idx <= this->nweight(n->left)) { n->weight++;
if (*rebalance_idx == nullptr && this->will_need_rebalance(thisidx, 1, 0)) { if (idx <= this->nweight(n->left)) {
*rebalance_idx = n_idxp; if (*rebalance_idx == nullptr && this->will_need_rebalance(thisidx, 1, 0)) {
} *rebalance_idx = n_idxp;
this->insert_internal(&n->left, value, idx, rebalance_idx);
} else {
if (*rebalance_idx == nullptr && this->will_need_rebalance(thisidx, 0, 1)) {
*rebalance_idx = n_idxp;
}
const uint32_t sub_index = idx - this->nweight(n->left) - 1;
this->insert_internal(&n->right, value, sub_index, rebalance_idx);
} }
} this->insert_internal(&n->left, value, idx, rebalance_idx);
}
inline void set_at_internal_array(const omtdata_t &value, const uint32_t idx) {
this->d.a.values[this->d.a.start_idx + idx] = value;
}
inline void set_at_internal(const node_idx n_idx, const omtdata_t &value, const uint32_t idx) {
invariant(n_idx != NODE_NULL);
omt_node *const n = &this->d.t.nodes[n_idx];
const uint32_t leftweight = this->nweight(n->left);
if (idx < leftweight) {
this->set_at_internal(n->left, value, idx);
} else if (idx == leftweight) {
n->value = value;
} else { } else {
this->set_at_internal(n->right, value, idx - leftweight - 1); if (*rebalance_idx == nullptr && this->will_need_rebalance(thisidx, 0, 1)) {
}
}
__attribute__((nonnull(2,5)))
inline void delete_internal(node_idx *const n_idxp, const uint32_t idx, omt_node *const copyn, node_idx **const rebalance_idx) {
invariant(*n_idxp != NODE_NULL);
omt_node *const n = &this->d.t.nodes[*n_idxp];
const uint32_t leftweight = this->nweight(n->left);
if (idx < leftweight) {
n->weight--;
if (*rebalance_idx == nullptr && this->will_need_rebalance(*n_idxp, -1, 0)) {
*rebalance_idx = n_idxp; *rebalance_idx = n_idxp;
} }
this->delete_internal(&n->left, idx, copyn, rebalance_idx); const uint32_t sub_index = idx - this->nweight(n->left) - 1;
} else if (idx == leftweight) { this->insert_internal(&n->right, value, sub_index, rebalance_idx);
if (n->left == NODE_NULL) { }
const uint32_t oldidx = *n_idxp; }
*n_idxp = n->right; }
if (copyn != nullptr) {
copyn->value = n->value; inline void set_at_internal_array(const omtdata_t &value, const uint32_t idx) {
} this->d.a.values[this->d.a.start_idx + idx] = value;
this->node_free(oldidx); }
} else if (n->right == NODE_NULL) {
const uint32_t oldidx = *n_idxp; inline void set_at_internal(const node_idx n_idx, const omtdata_t &value, const uint32_t idx) {
*n_idxp = n->left; invariant(n_idx != NODE_NULL);
if (copyn != nullptr) { omt_node *const n = &this->d.t.nodes[n_idx];
copyn->value = n->value; const uint32_t leftweight = this->nweight(n->left);
} if (idx < leftweight) {
this->node_free(oldidx); this->set_at_internal(n->left, value, idx);
} else { } else if (idx == leftweight) {
if (*rebalance_idx == nullptr && this->will_need_rebalance(*n_idxp, 0, -1)) { n->value = value;
*rebalance_idx = n_idxp; } else {
} this->set_at_internal(n->right, value, idx - leftweight - 1);
// don't need to copy up value, it's only used by this }
// next call, and when that gets to the bottom there }
// won't be any more recursion
n->weight--; __attribute__((nonnull(2,5)))
this->delete_internal(&n->right, 0, n, rebalance_idx); inline void delete_internal(node_idx *const n_idxp, const uint32_t idx, omt_node *const copyn, node_idx **const rebalance_idx) {
} invariant(*n_idxp != NODE_NULL);
omt_node *const n = &this->d.t.nodes[*n_idxp];
const uint32_t leftweight = this->nweight(n->left);
if (idx < leftweight) {
n->weight--;
if (*rebalance_idx == nullptr && this->will_need_rebalance(*n_idxp, -1, 0)) {
*rebalance_idx = n_idxp;
}
this->delete_internal(&n->left, idx, copyn, rebalance_idx);
} else if (idx == leftweight) {
if (n->left == NODE_NULL) {
const uint32_t oldidx = *n_idxp;
*n_idxp = n->right;
if (copyn != nullptr) {
copyn->value = n->value;
}
this->node_free(oldidx);
} else if (n->right == NODE_NULL) {
const uint32_t oldidx = *n_idxp;
*n_idxp = n->left;
if (copyn != nullptr) {
copyn->value = n->value;
}
this->node_free(oldidx);
} else { } else {
n->weight--;
if (*rebalance_idx == nullptr && this->will_need_rebalance(*n_idxp, 0, -1)) { if (*rebalance_idx == nullptr && this->will_need_rebalance(*n_idxp, 0, -1)) {
*rebalance_idx = n_idxp; *rebalance_idx = n_idxp;
} }
this->delete_internal(&n->right, idx - leftweight - 1, copyn, rebalance_idx); // don't need to copy up value, it's only used by this
} // next call, and when that gets to the bottom there
} // won't be any more recursion
n->weight--;
template<typename iterate_extra_t, this->delete_internal(&n->right, 0, n, rebalance_idx);
int (*f)(const omtdata_t &, const uint32_t, iterate_extra_t *const)>
inline int iterate_internal_array(const uint32_t left, const uint32_t right,
iterate_extra_t *const iterate_extra) const {
int r;
for (uint32_t i = left; i < right; ++i) {
r = f(this->d.a.values[this->d.a.start_idx + i], i, iterate_extra);
if (r != 0) {
return r;
}
} }
return 0; } else {
} n->weight--;
if (*rebalance_idx == nullptr && this->will_need_rebalance(*n_idxp, 0, -1)) {
template<typename iterate_extra_t, *rebalance_idx = n_idxp;
int (*f)(omtdata_t *, const uint32_t, iterate_extra_t *const)>
inline void iterate_ptr_internal(const uint32_t left, const uint32_t right,
const node_idx n_idx, const uint32_t idx,
iterate_extra_t *const iterate_extra) {
if (n_idx != NODE_NULL) {
omt_node *const n = this->d.t.nodes[n_idx];
const uint32_t idx_root = idx + this->nweight(n->left);
if (left < idx_root) {
this->iterate_ptr_internal<iterate_extra_t, f>(left, right, n->left, idx, iterate_extra);
}
if (left <= idx_root && idx_root < right) {
int r = f(&n->value, idx_root, iterate_extra);
lazy_assert_zero(r);
}
if (idx_root + 1 < right) {
this->iterate_ptr_internal<iterate_extra_t, f>(left, right, n->right, idx_root + 1, iterate_extra);
}
} }
this->delete_internal(&n->right, idx - leftweight - 1, copyn, rebalance_idx);
} }
}
template<typename iterate_extra_t, template<typename iterate_extra_t,
int (*f)(omtdata_t *, const uint32_t, iterate_extra_t *const)> int (*f)(const omtdata_t &, const uint32_t, iterate_extra_t *const)>
inline void iterate_ptr_internal_array(const uint32_t left, const uint32_t right, inline int iterate_internal_array(const uint32_t left, const uint32_t right,
iterate_extra_t *const iterate_extra) { iterate_extra_t *const iterate_extra) const {
for (uint32_t i = left; i < right; ++i) { int r;
int r = f(&this->d.a.values[this->d.a.start_idx + i], i, iterate_extra); for (uint32_t i = left; i < right; ++i) {
lazy_assert_zero(r); r = f(this->d.a.values[this->d.a.start_idx + i], i, iterate_extra);
if (r != 0) {
return r;
} }
} }
return 0;
}
template<typename iterate_extra_t, template<typename iterate_extra_t,
int (*f)(const omtdata_t &, const uint32_t, iterate_extra_t *const)> int (*f)(omtdata_t *, const uint32_t, iterate_extra_t *const)>
inline int iterate_internal(const uint32_t left, const uint32_t right, inline void iterate_ptr_internal(const uint32_t left, const uint32_t right,
const node_idx n_idx, const uint32_t idx, const node_idx n_idx, const uint32_t idx,
iterate_extra_t *const iterate_extra) const { iterate_extra_t *const iterate_extra) {
if (n_idx == NODE_NULL) { return 0; } if (n_idx != NODE_NULL) {
int r; omt_node *const n = this->d.t.nodes[n_idx];
const omt_node &n = this->d.t.nodes[n_idx]; const uint32_t idx_root = idx + this->nweight(n->left);
const uint32_t idx_root = idx + this->nweight(n.left);
if (left < idx_root) { if (left < idx_root) {
r = this->iterate_internal<iterate_extra_t, f>(left, right, n.left, idx, iterate_extra); this->iterate_ptr_internal<iterate_extra_t, f>(left, right, n->left, idx, iterate_extra);
if (r != 0) { return r; }
} }
if (left <= idx_root && idx_root < right) { if (left <= idx_root && idx_root < right) {
r = f(n.value, idx_root, iterate_extra); int r = f(&n->value, idx_root, iterate_extra);
if (r != 0) { return r; } lazy_assert_zero(r);
} }
if (idx_root + 1 < right) { if (idx_root + 1 < right) {
return this->iterate_internal<iterate_extra_t, f>(left, right, n.right, idx_root + 1, iterate_extra); this->iterate_ptr_internal<iterate_extra_t, f>(left, right, n->right, idx_root + 1, iterate_extra);
} }
return 0;
} }
}
inline void fetch_internal_array(const uint32_t i, omtdataout_t *value) const { template<typename iterate_extra_t,
int (*f)(omtdata_t *, const uint32_t, iterate_extra_t *const)>
inline void iterate_ptr_internal_array(const uint32_t left, const uint32_t right,
iterate_extra_t *const iterate_extra) {
for (uint32_t i = left; i < right; ++i) {
int r = f(&this->d.a.values[this->d.a.start_idx + i], i, iterate_extra);
lazy_assert_zero(r);
}
}
template<typename iterate_extra_t,
int (*f)(const omtdata_t &, const uint32_t, iterate_extra_t *const)>
inline int iterate_internal(const uint32_t left, const uint32_t right,
const node_idx n_idx, const uint32_t idx,
iterate_extra_t *const iterate_extra) const {
if (n_idx == NODE_NULL) { return 0; }
int r;
const omt_node &n = this->d.t.nodes[n_idx];
const uint32_t idx_root = idx + this->nweight(n.left);
if (left < idx_root) {
r = this->iterate_internal<iterate_extra_t, f>(left, right, n.left, idx, iterate_extra);
if (r != 0) { return r; }
}
if (left <= idx_root && idx_root < right) {
r = f(n.value, idx_root, iterate_extra);
if (r != 0) { return r; }
}
if (idx_root + 1 < right) {
return this->iterate_internal<iterate_extra_t, f>(left, right, n.right, idx_root + 1, iterate_extra);
}
return 0;
}
inline void fetch_internal_array(const uint32_t i, omtdataout_t *value) const {
if (value != nullptr) {
copyout(value, &this->d.a.values[this->d.a.start_idx + i]);
}
}
inline void fetch_internal(const node_idx idx, const uint32_t i, omtdataout_t *value) const {
omt_node *const n = &this->d.t.nodes[idx];
const uint32_t leftweight = this->nweight(n->left);
if (i < leftweight) {
this->fetch_internal(n->left, i, value);
} else if (i == leftweight) {
if (value != nullptr) { if (value != nullptr) {
copyout(value, &this->d.a.values[this->d.a.start_idx + i]); copyout(value, n);
} }
} else {
this->fetch_internal(n->right, i - leftweight - 1, value);
} }
}
inline void fetch_internal(const node_idx idx, const uint32_t i, omtdataout_t *value) const { __attribute__((nonnull(2)))
omt_node *const n = &this->d.t.nodes[idx]; inline void fill_array_with_subtree_idxs(node_idx *const array, const node_idx tree_idx) const {
const uint32_t leftweight = this->nweight(n->left); if (tree_idx != NODE_NULL) {
if (i < leftweight) { const omt_node &tree = this->d.t.nodes[tree_idx];
this->fetch_internal(n->left, i, value); this->fill_array_with_subtree_idxs(&array[0], tree.left);
} else if (i == leftweight) { array[this->nweight(tree.left)] = tree_idx;
if (value != nullptr) { this->fill_array_with_subtree_idxs(&array[this->nweight(tree.left) + 1], tree.right);
copyout(value, n); }
} }
} else {
this->fetch_internal(n->right, i - leftweight - 1, value); __attribute__((nonnull(2,3)))
inline void rebuild_subtree_from_idxs(node_idx *const n_idxp, const node_idx *const idxs, const uint32_t numvalues) {
if (numvalues==0) {
*n_idxp = NODE_NULL;
} else {
uint32_t halfway = numvalues/2;
*n_idxp = idxs[halfway];
//node_idx newidx = idxs[halfway];
omt_node *const newnode = &this->d.t.nodes[*n_idxp];
newnode->weight = numvalues;
// value is already in there.
this->rebuild_subtree_from_idxs(&newnode->left, &idxs[0], halfway);
this->rebuild_subtree_from_idxs(&newnode->right, &idxs[halfway+1], numvalues-(halfway+1));
//n_idx = newidx;
}
}
__attribute__((nonnull(2)))
inline void rebalance(node_idx *const n_idxp) {
node_idx idx = *n_idxp;
if (idx==this->d.t.root) {
//Try to convert to an array.
//If this fails, (malloc) nothing will have changed.
//In the failure case we continue on to the standard rebalance
//algorithm.
this->convert_to_array();
} else {
const omt_node &n = this->d.t.nodes[idx];
node_idx *tmp_array;
size_t mem_needed = n.weight * (sizeof tmp_array[0]);
size_t mem_free = (this->capacity - this->d.t.free_idx) * (sizeof this->d.t.nodes[0]);
bool malloced;
if (mem_needed<=mem_free) {
//There is sufficient free space at the end of the nodes array
//to hold enough node indexes to rebalance.
malloced = false;
tmp_array = reinterpret_cast<node_idx *>(&this->d.t.nodes[this->d.t.free_idx]);
} }
} else {
malloced = true;
__attribute__((nonnull(2))) XMALLOC_N(n.weight, tmp_array);
inline void fill_array_with_subtree_idxs(node_idx *const array, const node_idx tree_idx) const { }
if (tree_idx != NODE_NULL) { this->fill_array_with_subtree_idxs(tmp_array, idx);
const omt_node &tree = this->d.t.nodes[tree_idx]; this->rebuild_subtree_from_idxs(n_idxp, tmp_array, n.weight);
this->fill_array_with_subtree_idxs(&array[0], tree.left); if (malloced) toku_free(tmp_array);
array[this->nweight(tree.left)] = tree_idx; }
this->fill_array_with_subtree_idxs(&array[this->nweight(tree.left) + 1], tree.right); }
__attribute__((nonnull(1)))
static inline void copyout(omtdata_t *const out, const omt_node *const n) {
*out = n->value;
}
__attribute__((nonnull(1,2)))
static inline void copyout(omtdata_t **const out, omt_node *const n) {
*out = &n->value;
}
__attribute__((nonnull(1)))
static inline void copyout(omtdata_t *const out, const omtdata_t *const stored_value_ptr) {
*out = *stored_value_ptr;
}
__attribute__((nonnull(1,2)))
static inline void copyout(omtdata_t **const out, omtdata_t *const stored_value_ptr) {
*out = stored_value_ptr;
}
template<typename omtcmp_t,
int (*h)(const omtdata_t &, const omtcmp_t &)>
__attribute__((nonnull(4)))
inline int find_internal_zero_array(const omtcmp_t &extra, omtdataout_t *value, uint32_t *const idxp) const {
uint32_t min = this->d.a.start_idx;
uint32_t limit = this->d.a.start_idx + this->d.a.num_values;
uint32_t best_pos = NODE_NULL;
uint32_t best_zero = NODE_NULL;
while (min!=limit) {
uint32_t mid = (min + limit) / 2;
int hv = h(this->d.a.values[mid], extra);
if (hv<0) {
min = mid+1;
} }
} else if (hv>0) {
best_pos = mid;
__attribute__((nonnull(2,3))) limit = mid;
inline void rebuild_subtree_from_idxs(node_idx *const n_idxp, const node_idx *const idxs, const uint32_t numvalues) {
if (numvalues==0) {
*n_idxp = NODE_NULL;
} else {
uint32_t halfway = numvalues/2;
*n_idxp = idxs[halfway];
//node_idx newidx = idxs[halfway];
omt_node *const newnode = &this->d.t.nodes[*n_idxp];
newnode->weight = numvalues;
// value is already in there.
this->rebuild_subtree_from_idxs(&newnode->left, &idxs[0], halfway);
this->rebuild_subtree_from_idxs(&newnode->right, &idxs[halfway+1], numvalues-(halfway+1));
//n_idx = newidx;
}
}
__attribute__((nonnull(2)))
inline void rebalance(node_idx *const n_idxp) {
node_idx idx = *n_idxp;
if (idx==this->d.t.root) {
//Try to convert to an array.
//If this fails, (malloc) nothing will have changed.
//In the failure case we continue on to the standard rebalance
//algorithm.
this->convert_to_array();
} else {
const omt_node &n = this->d.t.nodes[idx];
node_idx *tmp_array;
size_t mem_needed = n.weight * (sizeof tmp_array[0]);
size_t mem_free = (this->capacity - this->d.t.free_idx) * (sizeof this->d.t.nodes[0]);
bool malloced;
if (mem_needed<=mem_free) {
//There is sufficient free space at the end of the nodes array
//to hold enough node indexes to rebalance.
malloced = false;
tmp_array = reinterpret_cast<node_idx *>(&this->d.t.nodes[this->d.t.free_idx]);
}
else {
malloced = true;
XMALLOC_N(n.weight, tmp_array);
}
this->fill_array_with_subtree_idxs(tmp_array, idx);
this->rebuild_subtree_from_idxs(n_idxp, tmp_array, n.weight);
if (malloced) toku_free(tmp_array);
} }
} else {
best_zero = mid;
__attribute__((nonnull(1))) limit = mid;
static inline void copyout(omtdata_t *const out, const omt_node *const n) {
*out = n->value;
}
__attribute__((nonnull(1,2)))
static inline void copyout(omtdata_t **const out, omt_node *const n) {
*out = &n->value;
}
__attribute__((nonnull(1)))
static inline void copyout(omtdata_t *const out, const omtdata_t *const stored_value_ptr) {
*out = *stored_value_ptr;
}
__attribute__((nonnull(1,2)))
static inline void copyout(omtdata_t **const out, omtdata_t *const stored_value_ptr) {
*out = stored_value_ptr;
}
template<typename omtcmp_t,
int (*h)(const omtdata_t &, const omtcmp_t &)>
__attribute__((nonnull(4)))
inline int find_internal_zero_array(const omtcmp_t &extra, omtdataout_t *value, uint32_t *const idxp) const {
uint32_t min = this->d.a.start_idx;
uint32_t limit = this->d.a.start_idx + this->d.a.num_values;
uint32_t best_pos = NODE_NULL;
uint32_t best_zero = NODE_NULL;
while (min!=limit) {
uint32_t mid = (min + limit) / 2;
int hv = h(this->d.a.values[mid], extra);
if (hv<0) {
min = mid+1;
}
else if (hv>0) {
best_pos = mid;
limit = mid;
}
else {
best_zero = mid;
limit = mid;
}
} }
if (best_zero!=NODE_NULL) { }
//Found a zero if (best_zero!=NODE_NULL) {
if (value != nullptr) { //Found a zero
copyout(value, &this->d.a.values[best_zero]); if (value != nullptr) {
} copyout(value, &this->d.a.values[best_zero]);
*idxp = best_zero - this->d.a.start_idx;
return 0;
} }
if (best_pos!=NODE_NULL) *idxp = best_pos - this->d.a.start_idx; *idxp = best_zero - this->d.a.start_idx;
else *idxp = this->d.a.num_values; return 0;
}
if (best_pos!=NODE_NULL) *idxp = best_pos - this->d.a.start_idx;
else *idxp = this->d.a.num_values;
return DB_NOTFOUND;
}
template<typename omtcmp_t,
int (*h)(const omtdata_t &, const omtcmp_t &)>
__attribute__((nonnull(5)))
inline int find_internal_zero(const node_idx n_idx, const omtcmp_t &extra, omtdataout_t *value, uint32_t *const idxp) const {
if (n_idx==NODE_NULL) {
*idxp = 0;
return DB_NOTFOUND; return DB_NOTFOUND;
} }
omt_node *const n = &this->d.t.nodes[n_idx];
template<typename omtcmp_t, int hv = h(n->value, extra);
int (*h)(const omtdata_t &, const omtcmp_t &)> if (hv<0) {
__attribute__((nonnull(5))) int r = this->find_internal_zero<omtcmp_t, h>(n->right, extra, value, idxp);
inline int find_internal_zero(const node_idx n_idx, const omtcmp_t &extra, omtdataout_t *value, uint32_t *const idxp) const { *idxp += this->nweight(n->left)+1;
if (n_idx==NODE_NULL) { return r;
*idxp = 0; } else if (hv>0) {
return DB_NOTFOUND; return this->find_internal_zero<omtcmp_t, h>(n->left, extra, value, idxp);
} } else {
omt_node *const n = &this->d.t.nodes[n_idx]; int r = this->find_internal_zero<omtcmp_t, h>(n->left, extra, value, idxp);
int hv = h(n->value, extra); if (r==DB_NOTFOUND) {
if (hv<0) { *idxp = this->nweight(n->left);
int r = this->find_internal_zero<omtcmp_t, h>(n->right, extra, value, idxp); if (value != nullptr) {
*idxp += this->nweight(n->left)+1; copyout(value, n);
return r;
} else if (hv>0) {
return this->find_internal_zero<omtcmp_t, h>(n->left, extra, value, idxp);
} else {
int r = this->find_internal_zero<omtcmp_t, h>(n->left, extra, value, idxp);
if (r==DB_NOTFOUND) {
*idxp = this->nweight(n->left);
if (value != nullptr) {
copyout(value, n);
}
r = 0;
} }
return r; r = 0;
} }
return r;
} }
}
template<typename omtcmp_t, template<typename omtcmp_t,
int (*h)(const omtdata_t &, const omtcmp_t &)> int (*h)(const omtdata_t &, const omtcmp_t &)>
__attribute__((nonnull(4))) __attribute__((nonnull(4)))
inline int find_internal_plus_array(const omtcmp_t &extra, omtdataout_t *value, uint32_t *const idxp) const { inline int find_internal_plus_array(const omtcmp_t &extra, omtdataout_t *value, uint32_t *const idxp) const {
uint32_t min = this->d.a.start_idx; uint32_t min = this->d.a.start_idx;
uint32_t limit = this->d.a.start_idx + this->d.a.num_values; uint32_t limit = this->d.a.start_idx + this->d.a.num_values;
uint32_t best = NODE_NULL; uint32_t best = NODE_NULL;
while (min != limit) { while (min != limit) {
const uint32_t mid = (min + limit) / 2; const uint32_t mid = (min + limit) / 2;
const int hv = h(this->d.a.values[mid], extra); const int hv = h(this->d.a.values[mid], extra);
if (hv > 0) {
best = mid;
limit = mid;
} else {
min = mid + 1;
}
}
if (best == NODE_NULL) { return DB_NOTFOUND; }
if (value != nullptr) {
copyout(value, &this->d.a.values[best]);
}
*idxp = best - this->d.a.start_idx;
return 0;
}
template<typename omtcmp_t,
int (*h)(const omtdata_t &, const omtcmp_t &)>
__attribute__((nonnull(5)))
inline int find_internal_plus(const node_idx n_idx, const omtcmp_t &extra, omtdataout_t *value, uint32_t *const idxp) const {
if (n_idx==NODE_NULL) {
return DB_NOTFOUND;
}
omt_node *const n = &this->d.t.nodes[n_idx];
int hv = h(n->value, extra);
int r;
if (hv > 0) { if (hv > 0) {
r = this->find_internal_plus<omtcmp_t, h>(n->left, extra, value, idxp); best = mid;
if (r == DB_NOTFOUND) { limit = mid;
*idxp = this->nweight(n->left);
if (value != nullptr) {
copyout(value, n);
}
r = 0;
}
} else { } else {
r = this->find_internal_plus<omtcmp_t, h>(n->right, extra, value, idxp); min = mid + 1;
if (r == 0) {
*idxp += this->nweight(n->left) + 1;
}
} }
return r;
} }
if (best == NODE_NULL) { return DB_NOTFOUND; }
if (value != nullptr) {
copyout(value, &this->d.a.values[best]);
}
*idxp = best - this->d.a.start_idx;
return 0;
}
template<typename omtcmp_t, template<typename omtcmp_t,
int (*h)(const omtdata_t &, const omtcmp_t &)> int (*h)(const omtdata_t &, const omtcmp_t &)>
__attribute__((nonnull(4))) __attribute__((nonnull(5)))
inline int find_internal_minus_array(const omtcmp_t &extra, omtdataout_t *value, uint32_t *const idxp) const { inline int find_internal_plus(const node_idx n_idx, const omtcmp_t &extra, omtdataout_t *value, uint32_t *const idxp) const {
uint32_t min = this->d.a.start_idx; if (n_idx==NODE_NULL) {
uint32_t limit = this->d.a.start_idx + this->d.a.num_values; return DB_NOTFOUND;
uint32_t best = NODE_NULL; }
omt_node *const n = &this->d.t.nodes[n_idx];
while (min != limit) { int hv = h(n->value, extra);
const uint32_t mid = (min + limit) / 2; int r;
const int hv = h(this->d.a.values[mid], extra); if (hv > 0) {
if (hv < 0) { r = this->find_internal_plus<omtcmp_t, h>(n->left, extra, value, idxp);
best = mid; if (r == DB_NOTFOUND) {
min = mid + 1; *idxp = this->nweight(n->left);
} else { if (value != nullptr) {
limit = mid; copyout(value, n);
} }
r = 0;
} }
if (best == NODE_NULL) { return DB_NOTFOUND; } } else {
if (value != nullptr) { r = this->find_internal_plus<omtcmp_t, h>(n->right, extra, value, idxp);
copyout(value, &this->d.a.values[best]); if (r == 0) {
*idxp += this->nweight(n->left) + 1;
} }
*idxp = best - this->d.a.start_idx;
return 0;
} }
return r;
}
template<typename omtcmp_t, template<typename omtcmp_t,
int (*h)(const omtdata_t &, const omtcmp_t &)> int (*h)(const omtdata_t &, const omtcmp_t &)>
__attribute__((nonnull(5))) __attribute__((nonnull(4)))
inline int find_internal_minus(const node_idx n_idx, const omtcmp_t &extra, omtdataout_t *value, uint32_t *const idxp) const { inline int find_internal_minus_array(const omtcmp_t &extra, omtdataout_t *value, uint32_t *const idxp) const {
if (n_idx==NODE_NULL) { uint32_t min = this->d.a.start_idx;
return DB_NOTFOUND; uint32_t limit = this->d.a.start_idx + this->d.a.num_values;
} uint32_t best = NODE_NULL;
omt_node *const n = &this->d.t.nodes[n_idx];
int hv = h(n->value, extra); while (min != limit) {
const uint32_t mid = (min + limit) / 2;
const int hv = h(this->d.a.values[mid], extra);
if (hv < 0) { if (hv < 0) {
int r = this->find_internal_minus<omtcmp_t, h>(n->right, extra, value, idxp); best = mid;
if (r == 0) { min = mid + 1;
*idxp += this->nweight(n->left) + 1;
} else if (r == DB_NOTFOUND) {
*idxp = this->nweight(n->left);
if (value != nullptr) {
copyout(value, n);
}
r = 0;
}
return r;
} else { } else {
return this->find_internal_minus<omtcmp_t, h>(n->left, extra, value, idxp); limit = mid;
} }
} }
if (best == NODE_NULL) { return DB_NOTFOUND; }
__attribute__((nonnull(3))) if (value != nullptr) {
static inline int deep_clone_iter(const omtdata_t &value, const uint32_t idx, omt *const dest) { copyout(value, &this->d.a.values[best]);
static_assert(std::is_pointer<omtdata_t>::value, "omtdata_t isn't a pointer, can't do deep clone");
invariant_nonnull(dest);
invariant(idx == dest->d.a.num_values);
invariant(idx < dest->capacity);
XMEMDUP(dest->d.a.values[dest->d.a.num_values++], value);
return 0;
} }
*idxp = best - this->d.a.start_idx;
return 0;
}
static inline int free_items_iter(omtdata_t *value, const uint32_t UU(idx), void *const UU(unused)) { template<typename omtcmp_t,
static_assert(std::is_pointer<omtdata_t>::value, "omtdata_t isn't a pointer, can't do free items"); int (*h)(const omtdata_t &, const omtcmp_t &)>
invariant_notnull(*value); __attribute__((nonnull(5)))
toku_free(*value); inline int find_internal_minus(const node_idx n_idx, const omtcmp_t &extra, omtdataout_t *value, uint32_t *const idxp) const {
return 0; if (n_idx==NODE_NULL) {
return DB_NOTFOUND;
} }
}; omt_node *const n = &this->d.t.nodes[n_idx];
int hv = h(n->value, extra);
if (hv < 0) {
int r = this->find_internal_minus<omtcmp_t, h>(n->right, extra, value, idxp);
if (r == 0) {
*idxp += this->nweight(n->left) + 1;
} else if (r == DB_NOTFOUND) {
*idxp = this->nweight(n->left);
if (value != nullptr) {
copyout(value, n);
}
r = 0;
}
return r;
} else {
return this->find_internal_minus<omtcmp_t, h>(n->left, extra, value, idxp);
}
}
__attribute__((nonnull(3)))
static inline int deep_clone_iter(const omtdata_t &value, const uint32_t idx, omt *const dest) {
static_assert(std::is_pointer<omtdata_t>::value, "omtdata_t isn't a pointer, can't do deep clone");
invariant_nonnull(dest);
invariant(idx == dest->d.a.num_values);
invariant(idx < dest->capacity);
XMEMDUP(dest->d.a.values[dest->d.a.num_values++], value);
return 0;
}
static inline int free_items_iter(omtdata_t *value, const uint32_t UU(idx), void *const UU(unused)) {
static_assert(std::is_pointer<omtdata_t>::value, "omtdata_t isn't a pointer, can't do free items");
invariant_notnull(*value);
toku_free(*value);
return 0;
}
};
}; };
......
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