715 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			715 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
 | 
						|
#include "ccommon.h"
 | 
						|
#include "genconst.h"
 | 
						|
#include "ccustio.h"
 | 
						|
#include "cbpltree.h"
 | 
						|
#include "bplpriv.h"
 | 
						|
#include "btrread.h"
 | 
						|
#include "btrbase.h"
 | 
						|
#include "checks.h"
 | 
						|
#include        <memory.h>
 | 
						|
 | 
						|
 | 
						|
 void Move(byte ,int ,int ,int ,char *,char *);
 | 
						|
 | 
						|
/*
 | 
						|
@(SHF) Funzioni di base per il B+Tree
 | 
						|
@($) ZPage  B+TREE
 | 
						|
 | 
						|
@(ID)
 | 
						|
Azzera una pagina del B+TREE.
 | 
						|
@(FD)
 | 
						|
*/
 | 
						|
 | 
						|
	void                            ZPage(ActPage)
 | 
						|
	Page                            *ActPage; /* pagina attuale */
 | 
						|
 | 
						|
		{ 
 | 
						|
 | 
						|
			ActPage->PA.PageHeader.TPage = EmptyPage;
 | 
						|
			ActPage->PA.PageHeader.PathNumber = 0;
 | 
						|
			ActPage->PA.PageHeader.Flags = 0;
 | 
						|
			ActPage->PA.PageHeader.Father = NoLink;
 | 
						|
			ActPage->PA.PageHeader.Prev = NoLink;
 | 
						|
			ActPage->PA.PageHeader.Next = NoLink;
 | 
						|
			ActPage->PA.PageHeader.NKey = 0;
 | 
						|
			memset(ActPage->PA.AreaForKey, ' ', AreaLen);
 | 
						|
		}
 | 
						|
 | 
						|
/*
 | 
						|
@($) GetHeader  B+TREE
 | 
						|
 | 
						|
@(ID)
 | 
						|
Legge l'header di un indice.
 | 
						|
Restituisce il codice di errore.
 | 
						|
@(FD)
 | 
						|
 | 
						|
@(ISV)
 | 
						|
junk = variabile spazzatura per la chiamata della funzione "sleep".
 | 
						|
 | 
						|
w    = descrittore della finestra.
 | 
						|
 | 
						|
@(FSV)
 | 
						|
 | 
						|
*/
 | 
						|
 | 
						|
	int                                     GetHeader(FilCheck, HPage, LockMode, Err)
 | 
						|
	FilCtrl                 *FilCheck; /* identificatore indice             */
 | 
						|
	Page                            *HPage;    /* pagina dell' indice  */
 | 
						|
	int                                     LockMode;  /* lock sull'header                  */
 | 
						|
	int                                     *Err;      /* codice di errore                  */
 | 
						|
 | 
						|
	{
 | 
						|
	  do
 | 
						|
	  {
 | 
						|
	    CRead(&FilCheck->Fil, (char *) HPage, 1L, LockMode);
 | 
						|
	    if (TESTLOCK(FilCheck->Fil.IOR))
 | 
						|
	      message_box("Sono in attesa dell' indice");
 | 
						|
	  } while TESTLOCK(FilCheck->Fil.IOR);
 | 
						|
	  return((*Err = FilCheck->Fil.IOR));
 | 
						|
	}
 | 
						|
 | 
						|
/*
 | 
						|
@($) PutHeader  B+TREE
 | 
						|
 | 
						|
@(ID)
 | 
						|
Scrive l'header di un indice.
 | 
						|
Restituisce il codice di errore.
 | 
						|
@(FD)
 | 
						|
*/
 | 
						|
 | 
						|
	int                                     PutHeader(FilCheck, HPage, LockMode, Err)
 | 
						|
	FilCtrl                 *FilCheck; /* identificatore indice    */
 | 
						|
	Page                            *HPage;    /* pagina in cui scrivere l'header */
 | 
						|
	int                                     LockMode;  /* lock sull'header                */
 | 
						|
	int                                     *Err;      /* errore                          */
 | 
						|
 | 
						|
			{
 | 
						|
				CWrite(&FilCheck->Fil, (char *) HPage, 1L, LockMode);
 | 
						|
				return((*Err = FilCheck->Fil.IOR));
 | 
						|
			}
 | 
						|
 | 
						|
/*
 | 
						|
@($) GetAPage  B+TREE
 | 
						|
 | 
						|
@(ID)
 | 
						|
Legge una pagina generica dell'indice.
 | 
						|
Restituisce il codice di errore.
 | 
						|
@(FD)
 | 
						|
*/
 | 
						|
 | 
						|
	int                                     GetAPage(FilCheck, ActPage, Pg, Err)
 | 
						|
	FilCtrl                 *FilCheck; /* identificatore indice */
 | 
						|
	Page                            *ActPage;  /* pagina letta          */
 | 
						|
	RecNoType               Pg;        /* numero di pagina      */
 | 
						|
	int                                     *Err;      /* codice di errore      */
 | 
						|
 | 
						|
		{
 | 
						|
			CRead(&FilCheck->Fil, (char *) ActPage, Pg + FilCheck->FHead.CABlock + 1,
 | 
						|
						NoLock);
 | 
						|
			return((*Err = FilCheck->Fil.IOR)); 
 | 
						|
		}
 | 
						|
 | 
						|
/*
 | 
						|
@($) PutAPage  B+TREE
 | 
						|
 | 
						|
@(ID)
 | 
						|
Scrive una pagina generica dell'indice.
 | 
						|
Restituisce il codice di errore.
 | 
						|
@(FD)
 | 
						|
*/
 | 
						|
 | 
						|
	int                                     PutAPage(FilCheck, ActPage, Pg, Err)
 | 
						|
	FilCtrl                 *FilCheck; /* identificatore indice */
 | 
						|
	Page                            *ActPage;  /* pagina attiva         */
 | 
						|
	RecNoType               Pg;        /* numero della pagina   */
 | 
						|
	int                                     *Err;      /* codice errore         */
 | 
						|
 | 
						|
		{
 | 
						|
			CWrite(&FilCheck->Fil, (char *) ActPage, Pg + FilCheck->FHead.CABlock + 1,
 | 
						|
							NoLock);
 | 
						|
			return((*Err = FilCheck->Fil.IOR)); 
 | 
						|
		}
 | 
						|
 | 
						|
/*
 | 
						|
@($) GetAKey  B+TREE
 | 
						|
 | 
						|
@(ID)
 | 
						|
Estrae una chiave da una pagina.
 | 
						|
@(FD)
 | 
						|
 | 
						|
@(ISV)
 | 
						|
BgnItem = numero di byte precedenti alla chiave dall'inizio della pagina.
 | 
						|
@(FSV)
 | 
						|
*/
 | 
						|
 | 
						|
	void                            GetAKey(ActPage, KeyLen, Pstion, KKey, Index)
 | 
						|
	Page                            ActPage; /* pagina attiva                    */
 | 
						|
	int                                     KeyLen;  /* lunghezza della chiave           */
 | 
						|
	int                                     Pstion;  /* numero chiave nella pagina       */
 | 
						|
	TKey                            KKey;    /* Valore chiave (in output)        */
 | 
						|
	RecNoType               *Index;  /* indice associato a questa chiave */
 | 
						|
 | 
						|
		{
 | 
						|
			int                                BgnItem;
 | 
						|
 | 
						|
			BgnItem = (Pstion - 1) * (KeyLen + IndLen);
 | 
						|
			strcpy(KKey, (char *)(ActPage.PA.AreaForKey + BgnItem));
 | 
						|
			*Index = *((RecNoType *)(ActPage.PA.AreaForKey + BgnItem + KeyLen));
 | 
						|
		}
 | 
						|
 | 
						|
/*
 | 
						|
@($) PutAKey  B+TREE
 | 
						|
 | 
						|
@(ID)
 | 
						|
Mette una chiave in una pagina.
 | 
						|
@(FD)
 | 
						|
 | 
						|
@(ISV)
 | 
						|
BgnItem = numero di byte precedenti alla chiave dall'inizio della pagina.
 | 
						|
@(FSV)
 | 
						|
*/
 | 
						|
 | 
						|
	void                            PutAKey(KKey, Index, Pstion, KeyLen, ActPage)
 | 
						|
	TKey                            KKey;    /* valore della chiave             */
 | 
						|
	RecNoType               Index;   /* indice                          */
 | 
						|
	int                                     Pstion;  /* posizione nella quale scrivere la chiave */
 | 
						|
	int                                     KeyLen;  /* lunghezza della chiave          */
 | 
						|
	Page                            *ActPage;/* pagina attiva                   */
 | 
						|
 | 
						|
		{
 | 
						|
			register int                                    BgnItem;
 | 
						|
 | 
						|
			BgnItem = (Pstion - 1) * (KeyLen + IndLen);
 | 
						|
			strcpy((char *)(ActPage->PA.AreaForKey + BgnItem), KKey);
 | 
						|
			*((RecNoType *)(ActPage->PA.AreaForKey + BgnItem + KeyLen)) = Index;
 | 
						|
		}
 | 
						|
 | 
						|
/*
 | 
						|
@($) Repos  B+TREE
 | 
						|
 | 
						|
@(ID)
 | 
						|
Riposizione all'ultima chiave letta dall'ultima operazione.
 | 
						|
@(FD)
 | 
						|
 | 
						|
@(ISV)
 | 
						|
WKey, WKey1 = variabili di lavoro contenenti chiavi.
 | 
						|
 | 
						|
WPos        = variabile di lavoro contenente il numero di chiave nella pagina.
 | 
						|
 | 
						|
WPag        = variabile di lavoro contenente il numero di pagina attuale.
 | 
						|
 | 
						|
WInd,WInd1  = variabili di lavoro contenenti indici associati alle chavi Wkey.
 | 
						|
@(FSV)
 | 
						|
 | 
						|
@(IN)
 | 
						|
Serve solo in multiutenza (XENIX).
 | 
						|
@(FN)
 | 
						|
*/
 | 
						|
 | 
						|
	void                            Repos(FilCheck, BError)
 | 
						|
	FilCtrl                 *FilCheck;  /* identificatore indice     */
 | 
						|
	int                                     *BError;    /* codice errore (in output) */
 | 
						|
 | 
						|
	{
 | 
						|
		TKey                    WKey, WKey1;
 | 
						|
		int                             WPos = FilCheck->Pos, WError;
 | 
						|
		RecNoType       WPag = FilCheck->CurPag, WInd, WInd1;
 | 
						|
 | 
						|
		if (GetAPage(FilCheck, &PathPage, WPag, BError) != NoErr) return;
 | 
						|
		if (PathPage.PA.PageHeader.NKey < WPos) WPos = PathPage.PA.PageHeader.NKey ;
 | 
						|
		GetAKey(PathPage, FilCheck->Base[FilCheck->PN].KeyLen, WPos, WKey, &WInd);
 | 
						|
		if ((strcmp(WKey, FilCheck->Key) == 0) && (WInd == FilCheck->Ind)) return ;
 | 
						|
		strcpy(WKey1, FilCheck->Key) ;
 | 
						|
		WInd = FilCheck->Ind ;
 | 
						|
		BTrRead(FilCheck, FilCheck->Key, WKey, &WInd1, BError) ;
 | 
						|
		if (*BError == BTrEmptyTree) return ;
 | 
						|
		if (FilCheck->Base[FilCheck->PN].DupKeys == TRUE)
 | 
						|
		{
 | 
						|
			while ((strcmp(WKey, WKey1) == 0) && (WInd1 < WInd))
 | 
						|
			{
 | 
						|
				if (WPos < PathPage.PA.PageHeader.NKey) WPos++;
 | 
						|
				else
 | 
						|
					if (PathPage.PA.PageHeader.Next == NoLink) break;
 | 
						|
					else
 | 
						|
					{
 | 
						|
						WPag = PathPage.PA.PageHeader.Next;
 | 
						|
						if (GetAPage(FilCheck, &PathPage, WPag, BError) != NoErr) return;
 | 
						|
						WPos = 1;
 | 
						|
					}
 | 
						|
				GetAKey(PathPage, FilCheck->Base[FilCheck->PN].KeyLen, WPos, WKey, &WInd1);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		if (GetAPage(FilCheck, &PathPage, WPag, &WError) != NoErr) return;
 | 
						|
		if ((strcmp(WKey, WKey1) == 0) && (WInd == WInd1))
 | 
						|
		{
 | 
						|
			FilCheck->CurPag = WPag;
 | 
						|
			FilCheck->Pos = WPos;
 | 
						|
		}
 | 
						|
		else 
 | 
						|
		{
 | 
						|
			if (*BError != BTrEOF)
 | 
						|
			{
 | 
						|
				FilCheck->CurPag = WPag;
 | 
						|
				FilCheck->Pos = WPos;
 | 
						|
				strcpy(FilCheck->Key, WKey) ;
 | 
						|
				FilCheck->Ind = WInd1;
 | 
						|
				*BError = BTrKeyNotFound;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
/*
 | 
						|
@($) BTrNext  B+TREE
 | 
						|
 | 
						|
@(ID)
 | 
						|
Restituisce la chiave successiva all'ultima letta.
 | 
						|
@(FD)
 | 
						|
 | 
						|
@(ISV)
 | 
						|
WKey = variabile di lavoro contenente la chiave.
 | 
						|
 | 
						|
- Versione DOS e XENIX
 | 
						|
@(FSV)
 | 
						|
*/
 | 
						|
 | 
						|
	void                            BTrNext(FilCheck, KKey, IndSr, BError)
 | 
						|
	FilCtrl                 *FilCheck; /* identificatore indice   */
 | 
						|
	TKey                            KKey;      /* valore della chiave     */
 | 
						|
	RecNoType               *IndSr;    /* indice associato        */
 | 
						|
	int                                     *BError;   /* codice errore           */
 | 
						|
 | 
						|
		{
 | 
						|
			TKey                    WKey;
 | 
						|
 | 
						|
			if (FilCheck->CurPag == NoLink)
 | 
						|
			{
 | 
						|
				MaxKey(FilCheck->Base[FilCheck->PN].KeyLen, FilCheck->Key);
 | 
						|
				BTrRead(FilCheck, FilCheck->Key, WKey, IndSr, BError) ;
 | 
						|
				*BError = BTrEOF;
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{
 | 
						|
#ifdef DOS
 | 
						|
				if (adelete)
 | 
						|
				{
 | 
						|
					adelete = FALSE;
 | 
						|
#endif
 | 
						|
					Repos(FilCheck, BError) ;
 | 
						|
					if (*BError != NoErr)
 | 
						|
					{
 | 
						|
						if (*BError == BTrKeyNotFound)
 | 
						|
						{
 | 
						|
							strcpy(KKey,FilCheck->Key);
 | 
						|
							*IndSr = FilCheck->Ind ;
 | 
						|
							*BError = NoErr ;
 | 
						|
						}
 | 
						|
						return;
 | 
						|
					}
 | 
						|
#ifdef DOS
 | 
						|
				}
 | 
						|
				else
 | 
						|
					if (GetAPage(FilCheck, &PathPage, FilCheck->CurPag, BError) != NoErr) return;
 | 
						|
#endif
 | 
						|
				if (FilCheck->Pos < PathPage.PA.PageHeader.NKey)
 | 
						|
				{
 | 
						|
					FilCheck->Pos++;
 | 
						|
					GetAKey(PathPage, FilCheck->Base[FilCheck->PN].KeyLen, FilCheck->Pos, FilCheck->Key, IndSr);
 | 
						|
				}
 | 
						|
				else
 | 
						|
				{
 | 
						|
					if (PathPage.PA.PageHeader.Next == NoLink)
 | 
						|
					{
 | 
						|
						GetAKey(PathPage, FilCheck->Base[FilCheck->PN].KeyLen, FilCheck->Pos, FilCheck->Key, IndSr);
 | 
						|
						/*MaxKey(FilCheck->Base[FilCheck->PN].KeyLen, FilCheck->Key);*/
 | 
						|
						*BError = BTrEOF;
 | 
						|
					}
 | 
						|
					else
 | 
						|
					{
 | 
						|
						FilCheck->CurPag = PathPage.PA.PageHeader.Next;
 | 
						|
						if (GetAPage(FilCheck, &PathPage, FilCheck->CurPag, BError) != NoErr) return;
 | 
						|
						FilCheck->Pos = 1;
 | 
						|
						GetAKey(PathPage, FilCheck->Base[FilCheck->PN].KeyLen, FilCheck->Pos, FilCheck->Key, IndSr);
 | 
						|
					}
 | 
						|
				}
 | 
						|
				strcpy(KKey,FilCheck->Key);
 | 
						|
				FilCheck->Ind = *IndSr ;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
/*
 | 
						|
@($) BTrPrev  B+TREE
 | 
						|
 | 
						|
@(ID)
 | 
						|
Restituisce la chiave successiva all'ultima.
 | 
						|
@(FD)
 | 
						|
 | 
						|
@(ISV)
 | 
						|
WKey = variabile di lavoro contenente una chiave.
 | 
						|
 | 
						|
- Versione DOS e XENIX
 | 
						|
@(FSV)
 | 
						|
*/
 | 
						|
 | 
						|
	void                            BTrPrev(FilCheck, KKey, IndSr, BError)
 | 
						|
	FilCtrl                 *FilCheck; /* identificatore indice  */
 | 
						|
	TKey                            KKey;      /* valore della chiave (in output) */
 | 
						|
	RecNoType               *IndSr;    /* indice associato       */
 | 
						|
	int                                     *BError;   /* codice di errore       */
 | 
						|
 | 
						|
		{
 | 
						|
			TKey                    WKey;
 | 
						|
 | 
						|
			if (FilCheck->CurPag == NoLink)
 | 
						|
			{
 | 
						|
				MinKey(FilCheck->Base[FilCheck->PN].KeyLen, FilCheck->Key);
 | 
						|
				BTrRead(FilCheck, FilCheck->Key, WKey, IndSr, BError) ;
 | 
						|
				*BError = BTrBOF;
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{
 | 
						|
#ifdef DOS
 | 
						|
				if (adelete)
 | 
						|
				{
 | 
						|
					adelete = FALSE;
 | 
						|
#endif
 | 
						|
					Repos(FilCheck, BError) ;
 | 
						|
					if ((*BError != NoErr) && (*BError != BTrKeyNotFound))
 | 
						|
					{
 | 
						|
						if (*BError == BTrEOF)
 | 
						|
						{
 | 
						|
							strcpy(KKey,FilCheck->Key);
 | 
						|
							*IndSr = FilCheck->Ind ;
 | 
						|
							*BError = NoErr ;
 | 
						|
						}
 | 
						|
						return;
 | 
						|
					}
 | 
						|
#ifdef DOS
 | 
						|
				}
 | 
						|
				else
 | 
						|
					if (GetAPage(FilCheck, &PathPage, FilCheck->CurPag, BError) != NoErr) return;
 | 
						|
#endif
 | 
						|
				*BError = NoErr;
 | 
						|
				if (FilCheck->Pos > 1)
 | 
						|
				{
 | 
						|
					FilCheck->Pos--;
 | 
						|
					GetAKey(PathPage, FilCheck->Base[FilCheck->PN].KeyLen, FilCheck->Pos, FilCheck->Key, IndSr);
 | 
						|
				}
 | 
						|
				else
 | 
						|
				{
 | 
						|
					if (PathPage.PA.PageHeader.Prev == NoLink)
 | 
						|
					{
 | 
						|
						GetAKey(PathPage, FilCheck->Base[FilCheck->PN].KeyLen, FilCheck->Pos, FilCheck->Key, IndSr);
 | 
						|
						/*MinKey(FilCheck->Base[FilCheck->PN].KeyLen, FilCheck->Key);*/
 | 
						|
						*BError = BTrBOF;
 | 
						|
					}
 | 
						|
					else
 | 
						|
					{
 | 
						|
						FilCheck->CurPag = PathPage.PA.PageHeader.Prev;
 | 
						|
						if (GetAPage(FilCheck, &PathPage, FilCheck->CurPag, BError) != NoErr) return;
 | 
						|
						FilCheck->Pos = PathPage.PA.PageHeader.NKey;
 | 
						|
						GetAKey(PathPage, FilCheck->Base[FilCheck->PN].KeyLen, FilCheck->Pos, FilCheck->Key, IndSr);
 | 
						|
					}
 | 
						|
				}
 | 
						|
				strcpy(KKey, FilCheck->Key);
 | 
						|
				FilCheck->Ind = *IndSr ;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
/*
 | 
						|
@($) Move  B+TREE
 | 
						|
 | 
						|
@(ID)
 | 
						|
Sposta a destra od a sinistra un numero di byte "NByt" da una sorgente "Buff1"
 | 
						|
ad una destinazione "Buff2".
 | 
						|
@(FD)
 | 
						|
 | 
						|
@(ISV)
 | 
						|
w = area di transito.
 | 
						|
@(FSV)
 | 
						|
*/
 | 
						|
 | 
						|
	void                            Move(RghOrLft, NByt, BytBeg, BytDest, Buff1, Buff2)
 | 
						|
	byte                            RghOrLft; /* destra o sinistra */
 | 
						|
	int                                     NByt;     /* numero di byte da spostare */
 | 
						|
	int                                     BytBeg;   /* num. byte inizio sorgente  */
 | 
						|
	int                                     BytDest;  /* num. byte inizio destinazione */
 | 
						|
	AreaKey                 Buff1;    /* sorgente                      */
 | 
						|
	AreaKey                 Buff2;    /* destinazione                  */
 | 
						|
 | 
						|
		{
 | 
						|
			AreaKey         w;
 | 
						|
 | 
						|
			memcpy(w, &Buff1[BytBeg], NByt);
 | 
						|
			memcpy(&Buff2[BytDest], w, NByt);
 | 
						|
		}
 | 
						|
 | 
						|
/*
 | 
						|
@($) ShiftPage  B+TREE
 | 
						|
 | 
						|
@(ID)
 | 
						|
Esegue uno spostamento di un certo numero di posizioni (coppie chiave-puntatore)
 | 
						|
all'interno della pagina.
 | 
						|
@(FD)
 | 
						|
 | 
						|
@(ISV)
 | 
						|
Len = lunghezza di una coppia chiave-puntatore.
 | 
						|
 | 
						|
Beg = numero di byte dall'inizio della pagina alla chiave "StartK" (esclusa).
 | 
						|
 | 
						|
Dest =  byte al quale si deve postare la coppia chiave-puntatore.
 | 
						|
@(FSV)
 | 
						|
*/
 | 
						|
 | 
						|
	void                            ShiftPage(RghOrLft, StartK, NPos, MxKey, KeyLen, Page1)
 | 
						|
	byte                            RghOrLft; /* destra o sinistra  */
 | 
						|
	int                                     StartK;   /* chiave di partenza */
 | 
						|
	int                                     NPos;     /* numero di posizioni da saltare  */
 | 
						|
	int                                     MxKey;    /* numero max chiavi in una pagina */
 | 
						|
	int                                     KeyLen;   /* lunghezza di una chiave         */
 | 
						|
	Page                            *Page1;   /* pagina attiva                   */
 | 
						|
 | 
						|
	{
 | 
						|
		register int                                    Len = KeyLen + IndLen;
 | 
						|
		register int                                    Beg = (StartK - 1) * Len;
 | 
						|
		register int                                    Dest;
 | 
						|
 | 
						|
		if (RghOrLft == RightDir)
 | 
						|
		{
 | 
						|
			Dest = Beg + NPos * Len;
 | 
						|
			if (Page1->PA.PageHeader.NKey + NPos <= MxKey)
 | 
						|
			{
 | 
						|
				Move(RightDir, (Page1->PA.PageHeader.NKey - StartK + 1) * Len, Beg, Dest, Page1->PA.AreaForKey, Page1->PA.AreaForKey);
 | 
						|
				Page1->PA.PageHeader.NKey += NPos;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			Dest = Beg - NPos * Len;
 | 
						|
			if (StartK - NPos > 0)
 | 
						|
			{
 | 
						|
				if (StartK <= Page1->PA.PageHeader.NKey)
 | 
						|
					Move(LeftDir, (Page1->PA.PageHeader.NKey - StartK + 1) * Len, Beg, Dest, Page1->PA.AreaForKey, Page1->PA.AreaForKey);
 | 
						|
				Page1->PA.PageHeader.NKey -= NPos;
 | 
						|
				memset(&Page1->PA.AreaForKey[Page1->PA.PageHeader.NKey * Len], ' ', NPos * Len);
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
/*
 | 
						|
@($) ShiftOut  B+TREE
 | 
						|
 | 
						|
@(ID)
 | 
						|
Sposta un certo numero di chiavi da una pagina.
 | 
						|
@(FD)
 | 
						|
 | 
						|
@(ISV)
 | 
						|
Len = lunghezza coppia chiave-puntatore.
 | 
						|
@(FSV)
 | 
						|
*/
 | 
						|
 | 
						|
	void                            ShiftOut(FromK, Numk, ToK, KeyLen, Page1, Page2)
 | 
						|
	int                                     FromK; /* prima chiave da spostare               */
 | 
						|
	int                                     Numk;  /* numero di chiavi da spostare           */
 | 
						|
	int                                     ToK;   /* posizione nella pagina destinazione    */
 | 
						|
	int                                     KeyLen;/* lunghezza della chiave                 */
 | 
						|
	Page                            *Page1;/* puntatore alla pagina destinazione     */
 | 
						|
	Page                            *Page2;/* puntatore alla pagina sorgente         */
 | 
						|
 | 
						|
	{
 | 
						|
		register int                                    Len = KeyLen + IndLen;
 | 
						|
 | 
						|
		if (Page1->PA.PageHeader.TPage == Page2->PA.PageHeader.TPage)
 | 
						|
			Move(LeftDir, Numk * Len, (FromK - 1) * Len, (ToK - 1) * Len, Page2->PA.AreaForKey, Page1->PA.AreaForKey);
 | 
						|
	}
 | 
						|
 | 
						|
/*
 | 
						|
@($) FindPos  B+TREE
 | 
						|
 | 
						|
@(ID)
 | 
						|
Cerca una chiave all'interno di una pagina.
 | 
						|
Restituisce la chiave piu' simile.
 | 
						|
@(FD)
 | 
						|
 | 
						|
@(ISV)
 | 
						|
low = numero della chiave.
 | 
						|
 | 
						|
j   = incremento in byte di coppia chiave puntatore.
 | 
						|
@(FSV)
 | 
						|
 | 
						|
*/
 | 
						|
 | 
						|
	int                                     FindPos(ActPage, KKey, KeyLen, KeyOut, IndOut)
 | 
						|
	Page                            *ActPage;  /* pagina attiva          */
 | 
						|
	TKey                            KKey;      /* valore chiave (input)  */
 | 
						|
	int                                     KeyLen;    /* lunghezza della chiave */
 | 
						|
	TKey                            KeyOut;    /* valore chiave (output) */
 | 
						|
	RecNoType               *IndOut;   /* indice associato       */
 | 
						|
 | 
						|
	{
 | 
						|
		register int                            low = 1, j = 0;
 | 
						|
 | 
						|
		while (strcmp((char *)(ActPage->PA.AreaForKey + j), KKey) < 0)
 | 
						|
      if (low < ActPage->PA.PageHeader.NKey)
 | 
						|
			{
 | 
						|
				low++;
 | 
						|
				j += (KeyLen + IndLen);
 | 
						|
			}
 | 
						|
			else break;
 | 
						|
		strcpy(KeyOut, (char *)(ActPage->PA.AreaForKey + j));
 | 
						|
		*IndOut = *((RecNoType *)(ActPage->PA.AreaForKey + j + KeyLen));
 | 
						|
		return(low);
 | 
						|
	}
 | 
						|
 | 
						|
/*
 | 
						|
@($) PerformOp  B+TREE
 | 
						|
 | 
						|
@(ID)
 | 
						|
Effettua operazioni di Underflow e Overflow sull'indice.
 | 
						|
@(FD)
 | 
						|
 | 
						|
@(ISV)
 | 
						|
Pst    = variabile di lavoro contenente numeri chiave.
 | 
						|
 | 
						|
W      = contatore.
 | 
						|
 | 
						|
OldKey = variabile di lavoro contenente il valore di chiavi.
 | 
						|
@(FSV)
 | 
						|
*/
 | 
						|
 | 
						|
	void            PerformOp(RecOp,ActPage,Pg,OvUnFlow,Temp,MxKey,MnKey,KeyLen,BError)
 | 
						|
	KOp                                             RecOp; /* struttura contenente le operazioni da effettuare */
 | 
						|
	Page                                    *ActPage; /* pagina attiva           */
 | 
						|
	RecNoType                       Pg;       /* numero pagina           */
 | 
						|
	BOOLEAN                         *OvUnFlow;/* underflow opp. overflow */
 | 
						|
	KeyInd                          *Temp;    /* di lavoro, contiene una coppia chiave-puntatore */
 | 
						|
	int                                             MxKey;    /* numero max chiave       */
 | 
						|
	int                                             MnKey;    /* numero min chiave       */
 | 
						|
	int                                             KeyLen;   /* lunghezza della chiave  */
 | 
						|
	int                                             *BError;  /* codice errore           */
 | 
						|
 | 
						|
		{
 | 
						|
			int                                     Pst, W, i;
 | 
						|
			TKey                            OldKey;
 | 
						|
 | 
						|
			for (W = 0; W <= 1; W++)
 | 
						|
			{
 | 
						|
				if (RecOp[W].FlagOp)
 | 
						|
				{
 | 
						|
					RecOp[W].FlagOp = FALSE;
 | 
						|
					if (RecOp[W].Which == Inser)
 | 
						|
					{
 | 
						|
						Pst = 0;
 | 
						|
						while (Pst < ActPage->PA.PageHeader.NKey )
 | 
						|
						{
 | 
						|
							GetAKey(*ActPage, KeyLen, ++Pst, IntKey, &IntIndex);
 | 
						|
							if (IntIndex == RecOp[W].where) break;
 | 
						|
						}
 | 
						|
						if (ActPage->PA.PageHeader.NKey == MxKey)
 | 
						|
						{
 | 
						|
							GetAKey(*ActPage, KeyLen, MxKey, IntKey, &IntIndex);
 | 
						|
							if (strcmp(IntKey, RecOp[W].KeyAndInd.KKey) < 0)
 | 
						|
							{
 | 
						|
								strcpy(Temp->KKey, RecOp[W].KeyAndInd.KKey);
 | 
						|
								Temp->Ind = RecOp[W].KeyAndInd.Ind;
 | 
						|
							}
 | 
						|
							else
 | 
						|
							{
 | 
						|
								strcpy(Temp->KKey, IntKey);
 | 
						|
								Temp->Ind = IntIndex;
 | 
						|
								ActPage->PA.PageHeader.NKey--;
 | 
						|
								ShiftPage(RightDir, Pst, OnePos, MxKey, KeyLen, ActPage);
 | 
						|
								PutAKey(RecOp[W].KeyAndInd.KKey, RecOp[W].KeyAndInd.Ind, Pst, KeyLen, ActPage);
 | 
						|
							}
 | 
						|
							*OvUnFlow = TRUE;
 | 
						|
						}
 | 
						|
						else
 | 
						|
						{
 | 
						|
							*OvUnFlow = FALSE;
 | 
						|
							if (strcmp(IntKey, RecOp[W].KeyAndInd.KKey) < 0)
 | 
						|
							{
 | 
						|
								ActPage->PA.PageHeader.NKey++;
 | 
						|
								PutAKey(RecOp[W].KeyAndInd.KKey, RecOp[W].KeyAndInd.Ind, ActPage->PA.PageHeader.NKey, KeyLen, ActPage);
 | 
						|
								RecOp[W].FlagOp = TRUE;
 | 
						|
								RecOp[W].Which = Change;
 | 
						|
								RecOp[W].KeyAndInd.Ind = Pg;
 | 
						|
							}
 | 
						|
							else
 | 
						|
							{
 | 
						|
								ShiftPage(RightDir, Pst, OnePos, MxKey, KeyLen, ActPage);
 | 
						|
								PutAKey(RecOp[W].KeyAndInd.KKey, RecOp[W].KeyAndInd.Ind, Pst, KeyLen, ActPage);
 | 
						|
							}
 | 
						|
						}
 | 
						|
					}
 | 
						|
					else
 | 
						|
						if (RecOp[W].Which == Change)
 | 
						|
						{
 | 
						|
							Pst = 0;
 | 
						|
							GetAKey(*ActPage, KeyLen, ++Pst, IntKey, &IntIndex);
 | 
						|
							while ((IntIndex != RecOp[W].KeyAndInd.Ind) && (Pst < ActPage->PA.PageHeader.NKey))
 | 
						|
								GetAKey(*ActPage, KeyLen, ++Pst, IntKey, &IntIndex);
 | 
						|
							if (IntIndex == RecOp[W].KeyAndInd.Ind)
 | 
						|
								PutAKey(RecOp[W].KeyAndInd.KKey, IntIndex, Pst, KeyLen, ActPage);
 | 
						|
							*OvUnFlow = FALSE;
 | 
						|
							if ((IntIndex == RecOp[W].KeyAndInd.Ind) && (Pst == ActPage->PA.PageHeader.NKey))
 | 
						|
							{
 | 
						|
								RecOp[W].FlagOp = TRUE;
 | 
						|
								RecOp[W].Which = Change;
 | 
						|
								RecOp[W].KeyAndInd.Ind = Pg;
 | 
						|
							}
 | 
						|
						}
 | 
						|
						else
 | 
						|
							if (RecOp[W].Which == Delet)
 | 
						|
							{
 | 
						|
								Pst = 0;
 | 
						|
								GetAKey(*ActPage, KeyLen, ++Pst, IntKey, &IntIndex);
 | 
						|
								while ((IntIndex != RecOp[W].KeyAndInd.Ind) && (Pst < ActPage->PA.PageHeader.NKey))
 | 
						|
									GetAKey(*ActPage, KeyLen, ++Pst, IntKey, &IntIndex);
 | 
						|
								if (IntIndex == RecOp[W].KeyAndInd.Ind)
 | 
						|
								{
 | 
						|
									*OvUnFlow = (ActPage->PA.PageHeader.NKey == MnKey);
 | 
						|
									ShiftPage(LeftDir, ++Pst, OnePos, MxKey, KeyLen, ActPage);
 | 
						|
								}
 | 
						|
							}
 | 
						|
					if ((!OvUnFlow) && (Pst >= ActPage->PA.PageHeader.NKey))
 | 
						|
					{
 | 
						|
						RecOp[W].FlagOp = TRUE;
 | 
						|
						RecOp[W].Which = Change;
 | 
						|
						GetAKey(*ActPage, KeyLen, ActPage->PA.PageHeader.NKey, IntKey, &IntIndex);
 | 
						|
						strcpy(RecOp[W].KeyAndInd.KKey, IntKey);
 | 
						|
						RecOp[W].KeyAndInd.Ind = Pg;
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
/*
 | 
						|
@($)  ZrecOp  B+TREE
 | 
						|
 | 
						|
@(ID)
 | 
						|
Azzera la struttura delle operazioni da effettuare.
 | 
						|
@(FD)
 | 
						|
 | 
						|
@(ISV)
 | 
						|
i = contatore.
 | 
						|
@(FSV)
 | 
						|
*/
 | 
						|
 | 
						|
	void                            ZRecOp(R)
 | 
						|
	KOp                                     R; /* struttura operazioni da azzerare */
 | 
						|
 | 
						|
		{
 | 
						|
			int                                     i;
 | 
						|
 | 
						|
			for (i = 0; i <= 1; i++)
 | 
						|
			{
 | 
						|
				R[i].FlagOp = FALSE;
 | 
						|
				R[i].Which = Nothing;
 | 
						|
				R[i].Posit = NoLink;
 | 
						|
				R[i].where = -1;
 | 
						|
				MinKey(MaxArray, R[i].KeyAndInd.KKey);
 | 
						|
				R[i].KeyAndInd.Ind = NoLink;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 |