/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
#ident "$Id$"
#ident "Copyright (c) 2007-2012 Tokutek Inc.  All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
#if !defined(TOKU_LOCKTREE_INTERNAL_H)
#define TOKU_LOCKTREE_INTERNAL_H

#include <range_tree/rangetree.h>
#include <lth.h>
#include <rth.h>
#include <idlth.h>
#include <ft/omt.h>

#define TOKU_LT_USE_BORDERWRITE 1

struct __toku_ltm {
    /** The maximum number of locks allowed for the environment. */
    uint64_t          locks_limit;
    /** The current number of locks for the environment. */
    uint64_t          curr_locks;
    /** The maximum amount of memory for locks allowed for the environment. */
    uint64_t          lock_memory_limit;
    /** The current amount of memory for locks for the environment. */
    uint64_t          curr_lock_memory;
    /** Status / accountability information */
    LTM_STATUS_S       status;
    /** The list of lock trees it manages. */
    toku_lth*          lth;
    /** List of lock-tree DB mappings. Upon a request for a lock tree given
        a DB, if an object for that DB exists in this list, then the lock tree
        is retrieved from this list, otherwise, a new lock tree is created
        and the new mapping of DB and Lock tree is stored here */
    toku_idlth*        idlth;
    /** The panic function */
    int               (*panic)(DB*, int);

    toku_mutex_t mutex;

    struct timeval lock_wait_time;
};

/** \brief The lock tree structure */
struct __toku_lock_tree {
    /** Lock tree manager */
    toku_ltm* mgr;
    // for comparisons
    struct __toku_db fake_db; // dummy db used for comparisons
    DESCRIPTOR_S desc_s;
#if TOKU_LT_USE_BORDERWRITE
    toku_range_tree*    borderwrite; /**< See design document */
#endif
    toku_rth*           rth;         /**< Stores local(read|write)set tables */
    /** Whether lock escalation is allowed. */
    bool                lock_escalation_allowed;
    /** Function to retrieve the key compare function from the database. */
    toku_dbt_cmp compare_fun;
    /** The number of references held by DB instances and transactions to this lock tree*/
    uint32_t          ref_count;
    /** DICTIONARY_ID associated with the lock tree */
    DICTIONARY_ID      dict_id;
    OMT                lock_requests;

    toku_mutex_t mutex;

    /** A temporary area where we store the results of various find on 
        the range trees that this lock tree owns 
    Memory ownership: 
     - tree->buf is an array of toku_range's, which the lt owns
       The contents of tree->buf are volatile (this is a buffer space
       that we pass around to various functions, and every time we
       invoke a new function, its previous contents may become 
       meaningless)
     - tree->buf[i].left, .right are toku_points (ultimately a struct), 
       also owned by lt. We gave a pointer only to this memory to the 
       range tree earlier when we inserted a range, but the range tree
       does not own it!
     - tree->buf[i].{left,right}.key_payload is owned by
       the lt, we made copies from the DB at some point
    */
    toku_range*         buf;      
    uint32_t            buflen;      /**< The length of buf */
    toku_range*         bw_buf;
    uint32_t            bw_buflen;
    toku_range*         verify_buf;
    uint32_t            verify_buflen;

    // reserved for the lock tree user's data
    void *userdata;
    // first thing called when toku_lt_close() happens
    toku_lt_on_close_cb on_close_callback;
};

toku_range_tree* toku_lt_ifexist_selfread(toku_lock_tree* tree, TXNID txn);

toku_range_tree* toku_lt_ifexist_selfwrite(toku_lock_tree* tree, TXNID txn);

#include "txnid_set.h"

// internal function that finds all transactions that conflict with a given lock request
// for read lock requests
//     conflicts = all transactions in the BWT that conflict with the lock request
// for write lock requests
//     conflicts = all transactions in the GRT that conflict with the lock request UNION
//                 all transactions in the BWT that conflict with the lock request
// adds all of the conflicting transactions to the conflicts transaction set
// returns an error code (0 == success)
int toku_lt_get_lock_request_conflicts(toku_lock_tree *tree, toku_lock_request *lock_request, txnid_set *conflicts);

// returns the lock request state
toku_lock_request_state toku_lock_request_get_state(toku_lock_request *lock_request);

/**

   \brief A 2D BDB-inspired point.

   Observe the toku_point, and marvel! 
   It makes the pair (key, data) into a 1-dimensional point,
   on which a total order is defined by toku_lt_point_cmp.
   Additionally, we have points at +infty and -infty as
   key_payload = (void*) toku_lt_infinity or 
   key_payload = (void*) toku_lt_neg infinity 
 */
struct __toku_point {
    toku_lock_tree* lt;           /**< The lock tree, where toku_lt_point_cmp 
                                       is defined */
    void*           key_payload;  /**< The key ... */
    uint32_t        key_len;      /**< and its length */
};
#if !defined(__TOKU_POINT)
#define __TOKU_POINT
typedef struct __toku_point toku_point;
#endif

int toku_lt_point_cmp(const toku_point* x, const toku_point* y);

#endif