701 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			701 lines
		
	
	
		
			22 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"
 | 
						|
#ifdef __WATCOMC__
 | 
						|
#include <malloc.h>
 | 
						|
#else
 | 
						|
#include        <memory.h>
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
 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) ;
 | 
						|
    WPag =  FilCheck->CurPag ;
 | 
						|
    WPos =  FilCheck->Pos ;
 | 
						|
    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
 | 
						|
      {
 | 
						|
        Repos(FilCheck, BError) ;
 | 
						|
        if (*BError != NoErr)
 | 
						|
        {
 | 
						|
          if (*BError == BTrKeyNotFound)
 | 
						|
          {
 | 
						|
            strcpy(KKey,FilCheck->Key);
 | 
						|
            *IndSr = FilCheck->Ind ;
 | 
						|
            *BError = NoErr ;
 | 
						|
          }
 | 
						|
          return;
 | 
						|
        }
 | 
						|
        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
 | 
						|
      {
 | 
						|
        Repos(FilCheck, BError) ;
 | 
						|
        if ((*BError != NoErr) && (*BError != BTrKeyNotFound))
 | 
						|
        {
 | 
						|
          if (*BError == BTrEOF)
 | 
						|
          {
 | 
						|
            strcpy(KKey,FilCheck->Key);
 | 
						|
            *IndSr = FilCheck->Ind ;
 | 
						|
            *BError = NoErr ;
 | 
						|
          }
 | 
						|
          return;
 | 
						|
        }
 | 
						|
        *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;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 |