/* Copyright (C) 2006 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; version 2 of the License.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

// IndexPage.h: interface for the IndexPage class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_INDEXPAGE_H__5DD7F231_A406_11D2_AB5B_0000C01D2301__INCLUDED_)
#define AFX_INDEXPAGE_H__5DD7F231_A406_11D2_AB5B_0000C01D2301__INCLUDED_

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

#include "Page.h"
#include "Btn.h"
#include "IndexNode.h"

static const int SUPERNODES = 16;

class Dbb;
class Bdb;
class Bitmap;
class IndexKey;
class Index;

class IndexPage : public Page
{
public:
	AddNodeResult addNode (Dbb *dbb, IndexKey *key, int32 recordNumber);
	AddNodeResult addNode (Dbb *dbb, IndexKey *key, int32 recordNumber,IndexNode *node, IndexKey *priorKey, IndexKey *nextKey);
	Btn*		appendNode (IndexKey *indexKey, int32 recordNumber, int pageSize);
	int			deleteNode (Dbb *dbb, IndexKey *key, int32 recordNumber);
	Btn*		findNodeInBranch (IndexKey *indexKey, int32 recordNumber);
	Btn*		findNodeInLeaf (IndexKey *key, IndexKey *foundKey);
	Btn*		findInsertionPoint (IndexKey *indexKey, int32 recordNumber, IndexKey *expandedKey);
	Btn*		findInsertionPoint(int level, IndexKey* indexKey, int32 recordNumber, IndexKey* expandedKey, Btn* from, Btn* bucketEnd);
	Bdb*		splitPage (Dbb *dbb, Bdb *bdb, TransId transId);
	Bdb*		splitIndexPageEnd(Dbb *dbb, Bdb *bdb, TransId transId, IndexKey *insertKey, int recordNumber);
	Bdb*		splitIndexPageMiddle(Dbb *dbb, Bdb *bdb, IndexKey *splitKey, TransId transId);
	bool		isLastNode (Btn *node);

	void		analyze (int pageNumber);
	//void		validateInsertion (int keyLength, UCHAR * key, int32 recordNumber);
	void		validateNodes (Dbb *dbb, Validation *validation, Bitmap *children, int32 parentPageNumber);
	void		validate (Dbb *dbb, Validation *validation, Bitmap *pages, int32 parentPageNumber);
	void		validate(void *before);
	bool		checkAddSuperNode(int pageSize, IndexNode* node, IndexKey *indexKey, int recordNumber, int offset,  bool *makeNextSuper);
	void		moveMemory(void *dst,void *src);
	void		addSupernode(Btn *where);
	bool		deleteSupernode(Btn *where);
	Btn*		findSupernode(int level, UCHAR *key, size_t len, int32 recordNumber, Btn *after, bool *match);
	Btn*		findPriorNodeForSupernode(Btn *where,IndexKey *priorKey);
	Btn*		getEnd(void);
	static void	 initRootPage(Bdb *bdb);

	void		backup(EncodedDataStream* stream);
	void		restore(EncodedDataStream* stream);

	static int		computePrefix (IndexKey *key1, IndexKey *key2);
	static Bdb*		findLevel (Dbb *dbb, int32 indexId, Bdb *bdb, int level, IndexKey *indexKey, int32 recordNumber);
	static void		printPage (Bdb *bdb, bool inversion);
	static void		printPage (IndexPage *page, int32 pageNumber, bool inversion);
	static void		printPage (IndexPage *page, int32 pageNum, bool printDetail, bool inversion);
	static void		printNode(int i, IndexPage * page, int32 pageNumber, IndexNode & node, bool inversion = false);
	static void		printNode(IndexPage *page, int32 pageNumber, Btn *node, bool inversion = false);
	static int32	getRecordNumber(const UCHAR *ptr);
	static void		logIndexPage (Bdb *bdb, TransId transId, Index* index);

	int32	unused[2]; // used to be parent and prior pages
	int32	nextPage;
	//short	level;
	UCHAR	level;
	UCHAR	version;
	uint16	length;
	short	superNodes[SUPERNODES];
	Btn		nodes [1];
};

#endif // !defined(AFX_INDEXPAGE_H__5DD7F231_A406_11D2_AB5B_0000C01D2301__INCLUDED_)
