/****************************************************************************
* rtentry.h :
* header file for Rtree Entry class.
*
* Change Log :
* 09-17-1997 Initial version, Liujian Qian
*
* $Id: rtentry.h,v 1.4 1998/12/02 04:03:45 qian Exp $
***************************************************************************/
#ifndef _RTENTRY_H_
#define _RTENTRY_H_
#include "memory.h"
#include "gadt_rect.h"
#include "rtbasic.h"
class RNode; //forward declaration
/**
*
the pointer part of an RTree entry.
THe RPtr of a RTree entry can either be a child node (page
id) if a non-leaf node owns the entry; or it can be a tuple
id in the case of leaf node. A tuple id is a long integer
identifying a spatial tuple stored somewhere in a spatial
database.
When the RTree is distributed, the ptr may also distinct between
pointing to a local node or a remote node.
*/
class RPtr
{
char is_remote; //true if pointing to a remote node
char is_leaf; //used only during search
short host_id; //-1 means local
long the_id; //either the page id or tuple id (in leaf node)
public:
///
RPtr()
: is_remote(0), is_leaf(0), host_id(-1), the_id(0) {};
///
RPtr(long _id, int hid=-1)
:is_leaf(0), host_id(hid), the_id(_id) { is_remote = (host_id<0)?0:1; };
///
virtual ~RPtr() {};
///
virtual RPtr& operator= (const RPtr& a);
///
virtual bool operator==(const RPtr& a)const;
///
void init() {is_leaf=is_remote = 0, host_id = -1, the_id = 0;}
//GROUP: handy operations
///
virtual int hostId() const {return host_id; }
///
virtual int isRemote() const{return is_remote; }
///
virtual long id() const {return the_id; }
///
virtual void setHostId(int hid) {host_id = hid; }
///
virtual void setId (long _id) {the_id = _id; }
///
virtual void setRemote() {is_remote = 1; }
///
bool isLeaf() {return is_leaf; }
///
void setLeaf (char lf=1) { is_leaf=lf;}
//GROUP: pack/unpack stuff
///
// pack data into the pipe
virtual Result pack(DataPipe& p)
{
p<<is_remote<<is_leaf<<host_id<<the_id;
return GOk;
}
///
// unpack data from the pipe
virtual Result unpack(DataPipe& p)
{
//p.seek(0);
if(p.eop())
msgFail("already at end of pipe");
p>>is_remote>>is_leaf>>host_id>>the_id;
return GOk;
}
///
// return packed (persistent) size of a RTree pointer
virtual int getPSize() const
{
return sizeof(int)*2 + sizeof(long);
}
friend ostream& operator<<(ostream& os, const RPtr& p);
};
class REntryPool;
/**
Class for RTree entries.
Each RTree entry (or index record as in Guttman '84) consists of
two parts, one is the Key, the other a pointer. The Key is a
rectangle (using GRect) and is of type RTKey; the pointer is
defined by the RPtr class, which may contain a child node (page) id
or a real tuple id if the entry is in a leaf node.
The main methods for the REntry class includes those that compares
keys and such. Most of Key related methods has already been
implemented in our GRect class so no reinventing the wheel here.
Note that this class is the in-memory representation of an RTree
entry; before the entry goes to a disk, it has to be pack()'ed.
Similarly the unpack() function should be used when a node page
just loaded into memory.
*/
class REntry
{
friend class REntryPool;
//core stuff
RKey _key; //the key part
RPtr ptr; //the pointer part
//in-memory stuff
int _level; //level of the rtree where this entry resides
REntry *next; //for preallocated entry pool stuff
public:
///
NOP REntry() : _level(-1),next(0) {};
///
NOP REntry( RKey k, RPtr p, int l)
: _key(k), ptr(p), _level(l){};
///
virtual NOP ~REntry();
///
virtual REntry& operator= (const REntry& a) ;
///
virtual void init() ;
///
void * operator new(size_t);
///
void operator delete(void* ep, size_t);
///
friend ostream& operator<<(ostream& os, const REntry& e);
//====================================================
//====
// GROUP: predicates relatd emethods
//====
//====================================================
///
// general comparison method
//
virtual int cmp (const REntry& other) const;
///
// compare two entries based on their (key's) hilbert order
//
virtual int hCmp (const REntry& other) const;
///
// check whether this key satisfies the predicate.
//
virtual bool consistent (const RPred& pred);
virtual int equal (const REntry& other) const;
///
// check whether the two keys are the same
//
virtual bool operator== (const REntry& other);
///
// check whether this key overlaps/intersects the "other" entry
//
virtual bool overlaps (const REntry& other) const ;
///
// check whether this entry contains/covers the "other" entry
//
virtual bool contains (const REntry& other) const;
///
// check whether this entry is inside the "other" entry
//
virtual bool isInside (const REntry& other) const;
///
// calculate the penalty of inserting a new entry
//
virtual RPenalty penalty (const REntry& other) const;
//====================================================
//====
// GROUP: pack/unpack methods
//====
//====================================================
///
// pack the data member into a pipe (which
// can be stored onto disk pages)
//
virtual Result pack (DataPipe& p);
///
// unpack/restore the data member out of a pipe
//
virtual Result unpack (DataPipe& p);
///
// return the persistent (packed) size of an entry
// this should be a fixed size for current implementation
//
virtual int getPSize();
//====================================================
//====
// GROUP: other handy methods
//====
//====================================================
///
// return the hilbert order of the entry
//
long hOrder () const { return 0; /*bogus*/ }
///
// return the key (the bounding box)
//
const RKey& key () const {return _key; }
///
void setKey (const GRect& r) {_key=r; }
///
void setKey (Coord xl, Coord yl,
Coord xh, Coord yh) {
_key.set(xl, yl, xh, yh);}
///
RPtr& pointer () const { return (RPtr&) ptr; };
///
void setPointer (const RPtr& p) {ptr = p; }
///
int level () const {return _level; }
///
void setLevel (int l) {_level = l; ptr.setLeaf(l==0?1:0); }
///
void setLeaf (bool t) {ptr.setLeaf(t); };
};
// below is a dirty hack for two types of stacks;
// they really ought to be two instances of same stack template.
// will modify to use <STL> soon...
/**
* @internal
* the stack class for RTree pointers; for keeping the path
*/
class RPtrStk
{
public:
enum { MAX_STK_SZ = 16 }; // 16 ought be enough
private:
RPtr _stk[MAX_STK_SZ];
short _top;
public:
NOP RPtrStk() :_top(0) {};
NOP ~RPtrStk() {};
inline RPtrStk& operator=(const RPtrStk& t);
inline void push(const RPtr& p);
inline RPtr& pop();
inline RPtr& top();
inline RPtr& second();
inline RPtr& bottom();
inline void updateTop(const RPtr& p);
inline short size() {return _top; }
inline bool isFull() { return _top >= MAX_STK_SZ; }
inline bool isEmpty(){ return _top == 0; }
inline void reset() { _top = 0; }
friend ostream& operator<<(ostream& os, const RPtrStk& t);
};
inline void RPtrStk::push(const RPtr& ptr)
{
if(isFull()) {
msgWarn("RTree Stack overflow!");
abort();
}
_stk[_top++] = ptr;
}
inline RPtr& RPtrStk::pop()
{
GAssert(!isEmpty());
return _stk[--_top];
}
inline RPtr& RPtrStk::top()
{
GAssert(!isEmpty()) ;
return _stk[_top-1];
}
inline RPtr& RPtrStk::second()
{
GAssert(_top > 1);
return _stk[_top-2];
}
inline RPtr& RPtrStk::bottom()
{
GAssert(! isEmpty());
return _stk[0];
}
inline void RPtrStk::updateTop(const RPtr& p)
{
GAssert(! isEmpty());
_stk[_top-1] = p;
}
inline RPtrStk& RPtrStk::operator=(const RPtrStk& t)
{
_top = t._top;
memcpy((char*)_stk, (char*)&t._stk, sizeof(RPtr)*MAX_STK_SZ);
return *this;
}
////////////////
// the stack class for RTree entries; used during search
//
/**
* @internal
*/
class REntryStk
{
public:
enum { MAX_STK_SZ = 1024 }; // an arbitrary limit
private:
REntry _stk[MAX_STK_SZ];
short _top;
public:
NOP REntryStk() :_top(0) {};
NOP ~REntryStk() {};
inline REntryStk& operator=(const REntryStk& t);
inline void push(const REntry& p);
inline REntry& pop();
inline REntry& top();
inline REntry& second();
inline REntry& bottom();
inline void updateTop(const REntry& p);
inline short size() {return _top; }
inline bool isFull() { return _top >= MAX_STK_SZ; }
inline bool isEmpty(){ return _top == 0; }
inline void reset() { _top = 0; }
friend ostream& operator<<(ostream& os, const REntryStk& t);
};
inline void REntryStk::push(const REntry& ptr)
{
if(isFull()) {
msgWarn("RTree Stack overflow!");
abort();
}
_stk[_top++] = ptr;
}
inline REntry& REntryStk::pop()
{
GAssert(!isEmpty());
return _stk[--_top];
}
inline REntry& REntryStk::top()
{
GAssert(!isEmpty()) ;
return _stk[_top-1];
}
inline REntry& REntryStk::second()
{
GAssert(_top > 1);
return _stk[_top-2];
}
inline REntry& REntryStk::bottom()
{
GAssert(! isEmpty());
return _stk[0];
}
inline void REntryStk::updateTop(const REntry& p)
{
GAssert(! isEmpty());
_stk[_top-1] = p;
}
inline REntryStk& REntryStk::operator=(const REntryStk& t)
{
_top = t._top;
memcpy((char*)_stk, (char*)&t._stk, sizeof(REntry)*MAX_STK_SZ);
return *this;
}
/**
@internal
REntryPool --
DESCRIPTION
THis class manages a pool of RTree entries. This is meant to speed up
the allocation/freeing of individual entries. The pool is
extended with POOL_DELTA of entries each time.
It is a globaly shared pool. *No mutex has been placed to protect it.*
*/
class REntryPool
{
enum {POOL_DELTA = 400};
static int n_total;
static int n_free;
static REntry* pool;
public:
///
// allocate an entry record from the pool
static REntry* allocEntry();
///
// free an entry record and put it back to the pool
static void freeEntry(REntry* ep);
///
// extend the capacity of the pool w/ 'incr' of new episodes
static Result extendPool(int incr=POOL_DELTA);
///
// free all entry; vacate the pool
static void freeAll();
static void stats (){
cout<<"total rtree entries allocated: "
<<n_total<<", free rtree entries: "
<<n_free<<endl;
}
};
#endif
Documentation generated by lqian@lqian-sun on Wed Jul 14 09:36:10 EDT 1999