/***************************************************************************
 *                                                                         *
 *   SMBLOCK.C                                                             *
 *                                                                         *
 *   Copyright (c) 1997      Galacticomm, Inc.        All Rights Reserved. *
 *                                                                         *
 *   Block management API for searchable memory block API.                 *
 *                                                                         *
 *                                           - J. Alvrus    5/21/97        *
 *                                                                         *
 ***************************************************************************/

#include "gcomm.h"
#include "smbapi.h"
#ifdef GCDOS
#include "smcache.h"
#include "smfile.h"
#endif // GCDOS
#include "smblock.h"

#define FILREV "$Revision: 3 $"

#ifdef GCDOS
static VOID *smbSwapIn(SMBHANDLE smb,SMBPTR ref);
#endif // GCDOS

MARKSOURCE(smblock)

VOID *                             /*   ptr to block in cache, NULL if err */
smbAlloc(                          /* allocate a block                     */
SMBHANDLE smb,                     /*   block control struct               */
SMBPTR *pRef)                      /*   buffer to receive reference        */
{
     VOID *ptr;

#ifdef GCDOS
     SMBPTR ref;

     if ((ref=smfAlloc(smb->SwapFile)) == SMBNULL) {
          return(NULL);
     }
     ASSERT(ref != SMBNULL);
     ptr=smbSwapIn(smb,ref);
     *pRef=ref;
#else
     if ((ptr=malloc(sizeof(SMBHEADER)*smb->Keys+smb->RecordLength)) != NULL) {
          *pRef=ptr;
     }
#endif // GCDOS
     return(ptr);
}

VOID
smbFree(                           /* free a block                         */
SMBHANDLE smb,                     /*   block control struct               */
SMBPTR ref)                        /*   buffer to receive reference        */
{
#ifdef GCDOS
     smcFree(smb->Cache,ref);
     smfFree(smb->SwapFile,ref);
#else
     (VOID)smb;
     free(ref);
#endif // GCDOS
}

#ifdef GCDOS

VOID *                             /*   ptr to block in cache, NULL if err */
smbGet(                            /* get pointer a block                  */
SMBHANDLE smb,                     /*   block control struct               */
SMBPTR ref)                        /*   block to get                       */
{
     SMCACHE *smc;
     SMFILE *smf;
     VOID *ptr;

     smc=smb->Cache;
     smf=smb->SwapFile;
     if ((ptr=smcGet(smc,ref)) == NULL) {
          if ((ptr=smbSwapIn(smb,ref)) == NULL
           || !smfRead(smf,ptr,ref)) {
               smcFree(smc,ref);
               return(NULL);
          }
     }
     return(ptr);
}

static VOID *                      /*   pointer to block in cache          */
smbSwapIn(                         /* swap block into cache                */
SMBHANDLE smb,                     /*   block control struct               */
SMBPTR ref)                        /*   block to swap in                   */
{
     SMCACHE *smc;
     SMCPOS lrupos;
     VOID *ptr;

     smc=smb->Cache;
     if (smcFull(smc)) {
          lrupos=smcFindLRUPos(smc);
          if (!smfWrite(smb->SwapFile,smcGetByPos(smc,lrupos),
                        smcBlockFromPos(smc,lrupos))) {
               return(NULL);
          }
          smcFreeByPos(smc,lrupos);
     }
     ptr=smcAlloc(smc,ref);
     ASSERT(ptr != NULL);
     return(ptr);
}

#ifdef DEBUG

GBOOL
smbIsValidBlock(                   // is this a valid block pointer?
SMBHANDLE smb,                     //   block control struct
SMBPTR ref)                        //   block to check
{
     return(smfIsValidBlock(smb->SwapFile,ref));
}

#endif // DEBUG
#endif // GCDOS
