<commit_before>/* Masstree
 * <NAME>, <NAME>, <NAME>
 * Copyright (c) 2012-2013 President and Fellows of Harvard College
 * Copyright (c) 2012-2013 Massachusetts Institute of Technology
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, subject to the conditions
 * listed in the Masstree LICENSE file. These conditions include: you must
 * preserve this copyright notice, and you cannot mention the copyright
 * holders in advertising related to the Software without their permission.
 * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
 * notice is a summary of the Masstree LICENSE file; the license in that file
 * is legally binding.
 */
#ifndef MASSTREE_STRUCT_HH
#define MASSTREE_STRUCT_HH
#include "masstree.hh"
#include "nodeversion.hh"
#include "stringbag.hh"
#include "mtcounters.hh"
#include "timestamp.hh"

#include "../object.h"
namespace Masstree {

template <typename P>
struct make_nodeversion {
    typedef typename mass::conditional<P::concurrent,
				       nodeversion,
				       singlethreaded_nodeversion>::type type;
};

template <typename P>
struct make_prefetcher {
    typedef typename mass::conditional<P::prefetch,
				       value_prefetcher<typename P::value_type>,
				       do_nothing>::type type;
};

template <typename P>
class node_base : public make_nodeversion<P>::type {
  public:
    static constexpr bool concurrent = P::concurrent;
    static constexpr int nikey = 1;
    typedef leaf<P> leaf_type;
    typedef internode<P> internode_type;
    typedef node_base<P> base_type;
    typedef typename P::value_type value_type;
    typedef leafvalue<P> leafvalue_type;
    typedef typename P::ikey_type ikey_type;
    typedef key<ikey_type> key_type;
    typedef typename make_nodeversion<P>::type nodeversion_type;
    typedef typename P::threadinfo_type threadinfo;

	typedef basic_table<P> basic_table_type;
	basic_table_type* table_;
	oid_type oid;

	inline base_type* fetch_node( oid_type oid ) const
	{
		return table_->fetch_node( oid );
	}

    node_base(bool isleaf)
	: nodeversion_type(isleaf) {
    }

    int size() const {
	if (this->isleaf())
	    return static_cast<const leaf_type*>(this)->size();
	else
	    return static_cast<const internode_type*>(this)->size();
    }

    inline base_type* parent() const {
        // almost always an internode
	if (this->isleaf())
	{
		if (static_cast<const leaf_type*>(this)->parent_oid_) 
	    return this->fetch_node(static_cast<const leaf_type*>(this)->parent_oid_);
	}
	else
	{
		if (static_cast<const internode_type*>(this)->parent_oid_)
	    return this->fetch_node(static_cast<const internode_type*>(this)->parent_oid_);
	}

	return 0;
    }
    inline void set_parent(base_type* p) {
	if (this->isleaf())
	{
	    if ( parent_exists(p) )
			static_cast<leaf_type*>(this)->parent_oid_ = p->oid;
		else
			static_cast<leaf_type*>(this)->parent_oid_ = 0;

	}
	else
	{
	    if ( parent_exists(p) )
			static_cast<internode_type*>(this)->parent_oid_ = p->oid;
		else
			static_cast<internode_type*>(this)->parent_oid_ = 0;

	}
    }
    static inline bool parent_exists(base_type* p) {
        return p != 0;
    }
    inline bool has_parent() const {
        return parent_exists(parent());
    }
    inline internode_type* locked_parent(threadinfo& ti) const;
    inline base_type* unsplit_ancestor() const {
	base_type* x = const_cast<base_type*>(this), *p;
	while (x->has_split() && (p = x->parent()))
	    x = p;
	return x;
    }
    inline leaf_type* leftmost() const {
        base_type* x = unsplit_ancestor();
        while (!x->isleaf()) {
            internode_type* in = static_cast<internode_type*>(x);
			x = in->fetch_node(in->child_oid[0]);
        }
        return x;
    }

    inline leaf_type* reach_leaf(const key_type& k, nodeversion_type& version,
                                 threadinfo& ti) const;

    void prefetch_full() const {
	for (int i = 0; i < std::min(16 * std::min(P::leaf_width, P::internode_width) + 1, 4 * 64); i += 64)
	    ::prefetch((const char *) this + i);
    }

    void print(FILE* f, const char* prefix, int indent, int kdepth);
};

template <typename P>
class internode : public node_base<P> {
  public:
    static constexpr int width = P::internode_width;
    typedef typename node_base<P>::nodeversion_type nodeversion_type;
    typedef key<typename P::ikey_type> key_type;
    typedef typename P::ikey_type ikey_type;
    typedef typename key_bound<width, P::bound_method>::type bound_type;
    typedef typename P::threadinfo_type threadinfo;

    uint8_t nkeys_;
    ikey_type ikey0_[width];
    kvtimestamp_t created_at_[P::debug_level > 0];

	typedef basic_table<P> basic_table_type;
	typedef object_vector node_vector_type;
	oid_type child_oid_[width + 1];
	oid_type parent_oid_; 
    internode()
	: node_base<P>(false), nkeys_(0), parent_oid_() {
    }


	static internode<P>* make(threadinfo& ti, basic_table<P>* table) {

		// Allocate object
		object* obj = reinterpret_cast<object*>(RA::allocate(sizeof(object) + sizeof(internode<P>)));
		ALWAYS_ASSERT(obj);
		internode<P>* n = (internode<P>*)((char*)obj + sizeof(object));


		// Init object container and node
		obj = new (obj) object(sizeof(object)+sizeof(internode<P>));
		n = new(n) internode<P>;

		// get oid
		node_vector_type* node_vector = table->get_node_vector();
		oid_type oid = node_vector->alloc();

		// Node init
		n->table_ = table;
		n->oid = oid;
		memset( n->child_oid_, 0, sizeof(oid_type)*width+1 );

		// drop to oid array
		fat_ptr new_head = fat_ptr::make( obj, INVALID_SIZE_CODE );
		while(not node_vector->put( oid, new_head ));
		return n;<commit_msg>masstree: fix internode oid initialization.<commit_after>/* Masstree
 * <NAME>, <NAME>, <NAME>
 * Copyright (c) 2012-2013 President and Fellows of Harvard College
 * Copyright (c) 2012-2013 Massachusetts Institute of Technology
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, subject to the conditions
 * listed in the Masstree LICENSE file. These conditions include: you must
 * preserve this copyright notice, and you cannot mention the copyright
 * holders in advertising related to the Software without their permission.
 * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This
 * notice is a summary of the Masstree LICENSE file; the license in that file
 * is legally binding.
 */
#ifndef MASSTREE_STRUCT_HH
#define MASSTREE_STRUCT_HH
#include "masstree.hh"
#include "nodeversion.hh"
#include "stringbag.hh"
#include "mtcounters.hh"
#include "timestamp.hh"

#include "../object.h"
namespace Masstree {

template <typename P>
struct make_nodeversion {
    typedef typename mass::conditional<P::concurrent,
				       nodeversion,
				       singlethreaded_nodeversion>::type type;
};

template <typename P>
struct make_prefetcher {
    typedef typename mass::conditional<P::prefetch,
				       value_prefetcher<typename P::value_type>,
				       do_nothing>::type type;
};

template <typename P>
class node_base : public make_nodeversion<P>::type {
  public:
    static constexpr bool concurrent = P::concurrent;
    static constexpr int nikey = 1;
    typedef leaf<P> leaf_type;
    typedef internode<P> internode_type;
    typedef node_base<P> base_type;
    typedef typename P::value_type value_type;
    typedef leafvalue<P> leafvalue_type;
    typedef typename P::ikey_type ikey_type;
    typedef key<ikey_type> key_type;
    typedef typename make_nodeversion<P>::type nodeversion_type;
    typedef typename P::threadinfo_type threadinfo;

	typedef basic_table<P> basic_table_type;
	basic_table_type* table_;
	oid_type oid;

	inline base_type* fetch_node( oid_type oid ) const
	{
		return table_->fetch_node( oid );
	}

    node_base(bool isleaf)
	: nodeversion_type(isleaf) {
    }

    int size() const {
	if (this->isleaf())
	    return static_cast<const leaf_type*>(this)->size();
	else
	    return static_cast<const internode_type*>(this)->size();
    }

    inline base_type* parent() const {
        // almost always an internode
	if (this->isleaf())
	{
		if (static_cast<const leaf_type*>(this)->parent_oid_) 
	    return this->fetch_node(static_cast<const leaf_type*>(this)->parent_oid_);
	}
	else
	{
		if (static_cast<const internode_type*>(this)->parent_oid_)
	    return this->fetch_node(static_cast<const internode_type*>(this)->parent_oid_);
	}

	return 0;
    }
    inline void set_parent(base_type* p) {
	if (this->isleaf())
	{
	    if ( parent_exists(p) )
			static_cast<leaf_type*>(this)->parent_oid_ = p->oid;
		else
			static_cast<leaf_type*>(this)->parent_oid_ = 0;

	}
	else
	{
	    if ( parent_exists(p) )
			static_cast<internode_type*>(this)->parent_oid_ = p->oid;
		else
			static_cast<internode_type*>(this)->parent_oid_ = 0;

	}
    }
    static inline bool parent_exists(base_type* p) {
        return p != 0;
    }
    inline bool has_parent() const {
        return parent_exists(parent());
    }
    inline internode_type* locked_parent(threadinfo& ti) const;
    inline base_type* unsplit_ancestor() const {
	base_type* x = const_cast<base_type*>(this), *p;
	while (x->has_split() && (p = x->parent()))
	    x = p;
	return x;
    }
    inline leaf_type* leftmost() const {
        base_type* x = unsplit_ancestor();
        while (!x->isleaf()) {
            internode_type* in = static_cast<internode_type*>(x);
			x = in->fetch_node(in->child_oid[0]);
        }
        return x;
    }

    inline leaf_type* reach_leaf(const key_type& k, nodeversion_type& version,
                                 threadinfo& ti) const;

    void prefetch_full() const {
	for (int i = 0; i < std::min(16 * std::min(P::leaf_width, P::internode_width) + 1, 4 * 64); i += 64)
	    ::prefetch((const char *) this + i);
    }

    void print(FILE* f, const char* prefix, int indent, int kdepth);
};

template <typename P>
class internode : public node_base<P> {
  public:
    static constexpr int width = P::internode_width;
    typedef typename node_base<P>::nodeversion_type nodeversion_type;
    typedef key<typename P::ikey_type> key_type;
    typedef typename P::ikey_type ikey_type;
    typedef typename key_bound<width, P::bound_method>::type bound_type;
    typedef typename P::threadinfo_type threadinfo;

    uint8_t nkeys_;
    ikey_type ikey0_[width];
    kvtimestamp_t created_at_[P::debug_level > 0];

	typedef basic_table<P> basic_table_type;
	typedef object_vector node_vector_type;
	oid_type child_oid_[width + 1];
	oid_type parent_oid_; 
    internode()
	: node_base<P>(false), nkeys_(0), parent_oid_() {
    }


	static internode<P>* make(threadinfo& ti, basic_table<P>* table) {

		// Allocate object
		object* obj = reinterpret_cast<object*>(RA::allocate(sizeof(object) + sizeof(internode<P>)));
		ALWAYS_ASSERT(obj);
		internode<P>* n = (internode<P>*)((char*)obj + sizeof(object));


		// Init object container and node
		obj = new (obj) object(sizeof(object)+sizeof(internode<P>));
		n = new(n) internode<P>;

		// get oid
		node_vector_type* node_vector = table->get_node_vector();
		oid_type oid = node_vector->alloc();

		// Node init
		n->table_ = table;
		n->oid = oid;
        memset(n->child_oid_, 0, sizeof(oid_type)*(width+1));

		// drop to oid array
		fat_ptr new_head = fat_ptr::make( obj, INVALID_SIZE_CODE );
		while(not node_vector->put( oid, new_head ));
		return n;
{'fraction_non_alphanumeric': 0.11832786318880635, 'fraction_numerical': 0.0065641734323717395, 'mean_word_length': 3.969527896995708, 'pattern_counts': {'":': 0, '<': 93, '<?xml version=': 0, '>': 151, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3072869', 'n_tokens_mistral': 3993, 'n_tokens_neox': 3714, 'n_words': 982}