/**************************************************************************
 * Source Id :
 *
 * $Id: bucket.h,v 1.1 2001/04/03 20:10:25 aleksandras Exp $
 *-------------------------------------------------------------------------
 * Project Notes :
 *
 *  Diamond Base
 *  ============
 *      A solid database implementation, spurred on by the continuing
 *  Metal (Lead) Base saga.
 *
 *  Project Team :
 *        A. Davison
 *        K. Lentin
 *        D. Platt
 *
 *	Project Commenced : 05-02-1993
 *
 *-------------------------------------------------------------------------
 *  Module Notes :
 *
 *  Include file for bucket.cc. Created far too late in the piece!
 *
 *
 *  Original Author : Kev
 *
 **************************************************************************/

#ifndef __DB_BUCKET_H__
#define __DB_BUCKET_H__

#include <diamond/defs.h>
#include <diamond/dberr.h>

//enum e_leaf {INNER, LEAF};

class DIA_EXPORT DIA_object;
class bucket;

// Data stored at the head of each bucket's data area.

struct headerData
{
	// This is a bit ugly - we really want an enumated e_leaf type here,
	// but we have to ensure binary compatibility, so we make it a 32 bit number.
	// e_leaf		leaf;
	uint32		leaf;
	bucketId	parentId;
	bucketId	nextBucket;
	bucketId	prevBucket;
	int32		activeKeys;
};

// Class definition for the bucket.

class bucket
{
	int32*		data; // This is long* so that the headerData is aligned right
	bucketId	id;
	size_t		keyLength;
	uint32		numKeys;
	uint32		size;
	uint32		keyNum;
	size_t		myTupleSize;

public:
//-----
	bucket(const bucketId newId, const size_t newKeyLength, const int32 newSize, const e_leaf newLeaf, const bucketId newParentId, const bucketId newNextBucket, const bucketId newPrevBucket, const int32 NewkeyNum=0);
//	bucket(int32 newKeyNum=0 ) {};
	~bucket();
	inline bucketId	getId(void) const
		{
			return id;
		}
	void	info(void) const;
	inline	size_t headerSize(void) const
		{
			return sizeof(headerData);
		}

	inline	size_t tupleSize(void) const
		{
			return myTupleSize;
		}

	inline	headerData* header(void) const
		{
		// Return a correctly typed pointer to the header data.
		// This gives access to private data and should probably be
		// replaced with access methods for all header data individually.

			return (headerData*)data;
		}

	inline	char* firstTuple(void) const
		{
		// The keys and links in the bucket are numbered as follows:
		//    +-+-+-+-+-+-+-+
		//    |L|K|L|K|L|K|L|  L = Link,  K = Key
		//    +-+-+-+-+-+-+-+
		//     0 1 1 2 2 3 3
		//

		// Return the address of the
		// start of the Tuple space (i.e.
		// the address of Link 0).

			return (char*)data + headerSize();
		}

	inline	pKeyType getKeyAddr(const size_t pos) const
		{
		// Return a pointer to the pos'th
		// Key in the Tuple space.
		// Note we explicitly use int32 values for the database
		// storage.
			pKeyType key = (pKeyType)(firstTuple() + (pos-1) * tupleSize() +sizeof(int32));
			return key;
		}

	inline	char* getLinkAddr(const size_t pos) const
		{
		// Return a pointer to the pos'th link
		// in the Tuple space.
		// char * so no unaligned int32 accesses with keys not a multiple
		// of 4 int32. This problem now removed with keys rounded up to
		// multiples of 4 long

			char* tempLink = (firstTuple()+pos*tupleSize());
			return tempLink;
		}

	bucketId	getLink(const size_t pos) const;
	void		setLink(const size_t pos, const bucketId link);
	bool 	searchForKey(const DIA_object& theObject, size_t& ptr) const;
	void	findIndex(size_t& ind, bool& found) const;
	void	insert(const DIA_object& theObject, const int32 link);
	dbError	del(const size_t pos);
	inline  bool	full(void) const
		{
			return (bool)(numKeys == (uint32)header()->activeKeys);
		}

	inline  bool	empty(void) const
		{
		// Leaf buckets are considered empty when 0 keys are present.
		// Inner buckets still contain a link at this point so we test for -1.
		// A slight adaptation to the delete mechanism, with appropriate care
		// for balancing might not require this strange treatment.

			return (bool)(header()->activeKeys == ((header()->leaf==LEAF)?0:-1));
		}

	inline  pKeyType allocTmpKey(void)
		{
		// The bucket is in charge of allocating temporary key areas but
		// the deleting is left to the caller.

			return (pKeyType)new char[keyLength];
		}

	void	sploosh(bucket* newBucket, pKeyType in, pKeyType out, const DIA_object& theObject, const int32 link);

	// A couple of access to functions to keep our data safe...

	inline	void setActiveKeys(const int32 keys)
		{
			header()->activeKeys = keys;
		}

	inline	bucketId getParent(void) const
		{
			return header()->parentId;
		}

	inline	void setParent(bucketId parent)
		{
			header()->parentId = parent;
		}

	void	dump(void) const;
	inline	void*	getData(void) const
		{
			return (void*)data;
		}
	 const char* verStr(void) const;

friend class bTree;

}; //---- class def for Buckets...

#endif

////////////////////////////////////////////////////////////////////////////
// Revision History:
//
// $Log: bucket.h,v $
// Revision 1.1  2001/04/03 20:10:25  aleksandras
// big one 3.1 (comments later)
//
// Revision 1.12  1996/03/05  22:04:29  dmb
// removed ^M.
//
// Revision 1.11  1996/03/05  21:42:35  dmb
// Preliminary modifications to get Dos/Windows 0.4 portability.
//
// Revision 1.10  1996/02/01  22:44:16  dmb
// long->int32.
//
// Revision 1.9  1995/10/04  02:08:23  davison
// Changed references to objects to DIA_objects to prevent namespace clashes.
//
// Revision 1.8  1995/09/11 08:10:27  darrenp
// Changed long* -> int32
//
// Revision 1.7  1994/05/15 05:01:32  kevinl
// Type fixups.
//
// Revision 1.6  1994/02/25  03:15:56  darrenp
// Changes for DOS binary compatibility.
//
// Revision 1.4  1994/02/03  05:50:31  kevinl
// Moved include files to diamond/ and fixed HAVE_MALLOC_H
//
// Revision 1.3  1993/12/23  22:58:48  kevinl
// dbErr uses dbString, autoconf stuff, moved logs, added const and size_t
//
// Revision 1.2  1993/11/18  02:54:20  kevinl
// Fixed variable shadowing
//
// Revision 1.1  1993/11/09  04:20:02  kevinl
// Initial revision
//
////////////////////////////////////////////////////////////////////////////
