sorry for the module size, but I couldn't add a .tlb as an attachment....
cannot even get a listing of where the error is. (cc/noop/list/show=all)
Code: Select all
//------------------------------------------------------------------------------
//
// rtl_c_virmem.c This module is responsible for mapping and
// allocating virtual memory zones (caches) for
// use by the application.
//
// Zone allocation is maintained in a linked List
// each node in the list contains a pointer to the
// linked list of blocks, which are the actual
// blocks of memory that has been allotted to the
// zone.
//
// Cached records are mapped to address ranges
// within each block. Holes are left at the end
// of the blocks when the record size is not
// an integer factor of the blocksize
//
// This routine builds a linked list of virutal memory zone data structures.
// Each node in the linked list corresponds to a virtual memory zone allocated
// from VMS. Each structure contains a pointer to a linked list of block
// data structures. Each block structure represents memory from a zone that
// has been allocated for use by the application. Records are written and
// read from the memory blocks. The program translates the record number into
// a block number and an offset into the block. This was necessary as VMS
// does not guarantee that blocks will be contiguous within a zone, or that
// they will be in order of allocation.
//
// Parameter Data type Description
//------------------------- --------------- ------------------------------
// (1) dscInstruction *descriptor_s Instruction to be performed
// 'W' - write a record
// 'R' - read a record
// 'C' - clear a zone
// 'F' - free a zone
// 'S' - search a zone
// 'SX' - search a zone at the beginning
// 'M' - move a zone into a buffer
//
// (2) dscZoneName *descriptor_s string with the name of the zone
//
// (3) dscRecordNumber *descriptor_s Record number to read/write
//
// (4) dscBuffer *descriptor_s Buffer holding record
//
// (5) dscSearch *descriptor_s Value to search for
//
// (6) dscStartRecord *descriptor_s Starting record number for search
//
// (7) dscFilChar *descriptor_s Char to init memory blocks to
//
// (8) dscDebugFlag *descriptor_s Debug flags
//
//
//
//date Author Modification(s)
//----------- ---------------- ---------------------------------------------
// 8-OCT-1999 Tim Lovern New module as of this date. Written as direct
// replacement for mds$vir_mem (the DBL version)
// This was due the large number of incorrect
// assumptions made in that module about how
// memory is actually allocated.
//
//21-OCT-1999 Tim Lovern Modified FindZone routine to use strcmp instead
// of strncmp
//
//------------------------------------------------------------------------------
//
// Zone------------>Zone------------>Zone------------>NULL
// | | |
// +-->Block +-->Block +-->Block
// | | |
// +-->Block +-->Block +-->NULL
// | |
// +-->NULL +-->NULL
//------------------------------------------------------------------------------
#ifdef __DECC
# pragma module rtl_c_virmem
#else
# module rtl_c_virmem
#endif
//------------------------------------------------------------------------------
// include header files as required
//------------------------------------------------------------------------------
#define __NEW_STARLET 1
#include <ctype.h>
#include <ints.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <varargs.h>
#include <lib$routines.h>
#include <libvmdef.h>
#include <libdef.h>
#include <descrip.h>
#include <starlet.h>
#include <ssdef.h>
//------------------------------------------------------------------------------
// typedef's an other misc declarations
//------------------------------------------------------------------------------
#define FOREVER for(;;) // infinite loop keyword
typedef struct dsc$descriptor_s DSCS_S;
//-------------------------------------------------------
// define the structure to hold a VM Block
//-------------------------------------------------------
typedef struct rVirMemBlock
{
int64 iBaseAddress; // base memory address for block
int32 iRecordCount; // count of records in block
struct rVirMemBlock *prNext; // pointer to next block in list
} VIR_MEM_BLOCK;
//-------------------------------------------------------
// define the structure to hold a zone definition
//-------------------------------------------------------
typedef struct rVirMemZone
{
char *psName; // VM zone name
int64 iZoneId; // VM memory zone id
int iBlockCount; // number of blocks in this zone
int32 iRecordSize; // (fixed) record size for block
int32 iRecordsPerBlock; // how many records fit in a block?
struct rVirMemBlock *prMemBlock; // pointer to first block in zone
struct rVirMemZone *prNext; // pointer to next VMZone
} VIR_MEM_ZONE;
//-------------------------------------------------------
// constants for processing
//-------------------------------------------------------
const int64 kVM_Algorithm = LIB$K_VM_FIXED; // fixed size zones
const int64 kVM_Argument = 16384; // 16k blocks per request
const int64 kVM_Flags = LIB$M_VM_GET_FILL0 &
LIB$M_VM_FREE_FILL0; // bits 1 and 3 are set
const int64 kVM_ExtendSize = 32; // extend size in pagelets
const int64 kVM_InitSize = 32; // initial size in pagelets
const int64 kVM_BlockSize = 16384; // 16k blocks per request
const int64 kVM_AllocBlockSize = 512; // 512 byte blocks per request
const int64 kVM_Alignment = 16; // quadword alignment
const int64 kVM_PageLimit = 0; // default to process limits
//------------------------------------------------------------------------------
// function prototypes for internal routines
//------------------------------------------------------------------------------
VIR_MEM_ZONE * FindZone(char *, VIR_MEM_ZONE *);
int CreateZone(VIR_MEM_ZONE **, char *);
int AddBlock2Zone(VIR_MEM_ZONE *, VIR_MEM_BLOCK **);
int AddRecord2Block(VIR_MEM_ZONE *, int, void *, int );
int GetRecordFromBlock(VIR_MEM_ZONE *, int, void *, int);
int RemoveVirMemZone(char *, VIR_MEM_ZONE **);
int RemoveBlock(VIR_MEM_ZONE *, int);
int FindDataInBlock(VIR_MEM_ZONE *, VIR_MEM_BLOCK *, void *, int, void **, int, int);
int FindDataInBlockStart(VIR_MEM_ZONE *, VIR_MEM_BLOCK *, void *, int, void **, int, int);
void KillBlockStructures(VIR_MEM_BLOCK *);
void TruncateString(char *);
int MoveZone2Buffer(char *, VIR_MEM_ZONE *, void *, int, int);
void DebugZoneDump(VIR_MEM_ZONE *);
//------------------------------------------------------------------------------
// module scope visible definitions
//------------------------------------------------------------------------------
int igFATAL_VIR_MEM_ERROR = 0; // could not do without one module scope variable
int igDEBUG_FLAGS = 0; // had to put debug flags at module scope
int igFillChar = 0; // fill character ended up lots of places
FILE *pfDEBUG_OUT = NULL;
//------------------------------------------------------------------------------
// mainline code starts here
//------------------------------------------------------------------------------
int rtl_c_virmem(va_alist)
va_dcl
{
va_list ArgPtr; // for walking thru the optional stuff
int iArgumentCount = 0, // number of arguments
iCurrentArg = 0, // which one are we dealing with
iStatus = 0, // return status variable
iLoop = 0, // loop counter
iBufferSize = 0, // size of the passed record
iRecordNumber = 0, // record number to process
iSearchForSize = 0, // size of the binary object to be searched for
iSearchStart = 0, // starting record for search
iRecordSearch = 0, // record within first block in search
iCurrentRecord = 0, // current record number
iCurrentBlock = 0, // current block number
iBlockNumber = 0, // block number
iRecordsPerBlock = 0, // how many records are in a block
iDebugFlags = 0; // used for debug purposes
char *prFillChar = NULL,
*psInstruction = NULL, // instruction for the call to this routine
*psZoneName = NULL; // name of the VM zone we are dealing with
void *prBuffer = NULL, // pointer to passed record
*prSearchFor = NULL; // search for value
int64 iZoneId = 0; // current zone id
static VIR_MEM_ZONE *prRootZone = NULL; // root of our linked list
VIR_MEM_ZONE *prThisZone = NULL; // current zone
VIR_MEM_BLOCK *prThisBlock = NULL; // current block
DSCS_S *dscInstruction = NULL,
*dscZoneName = NULL,
*dscRecordNumber = NULL,
*dscBuffer = NULL,
*dscSearch = NULL,
*dscStartRecord = NULL,
*dscFilChar = NULL,
*dscDebugFlag = NULL;
struct dsc64$descriptor dscCvtRecordNumber =
{
(short) 1, // must be one
DSC$K_DTYPE_L, // data type (32 bit signed)
DSC$K_CLASS_S, // fixed size class
(long) -1, // must be -1
(int64) sizeof(iRecordNumber), // size in bytes
(char *) &iRecordNumber // ptr to the data
};
struct dsc64$descriptor dscCvtStartRecord =
{
(short) 1, // must be one
DSC$K_DTYPE_L, // data type (32 bit signed)
DSC$K_CLASS_S, // fixed size class
(long) -1, // must be -1
(int64) sizeof(iSearchStart), // size in bytes
(char *) &iSearchStart // ptr to the data
};
//-------------------------------------------------------
// Go thru and figure out all the arguments
//-------------------------------------------------------
va_start(ArgPtr);
va_count(iArgumentCount);
psInstruction = NULL; // instruction for the call to this routine
psZoneName = NULL; // name of the VM zone we are dealing with
prBuffer = NULL; // pointer to passed record
prSearchFor = NULL; // search for value
prThisZone = NULL; // current zone
prThisBlock = NULL; // current block
dscInstruction = NULL;
dscZoneName = NULL;
dscRecordNumber = NULL;
dscBuffer = NULL;
dscSearch = NULL;
dscStartRecord = NULL;
igFillChar = 0;
if (iArgumentCount)
{
for (iCurrentArg = 0; iCurrentArg < iArgumentCount; iCurrentArg++)
switch (iCurrentArg)
{
//-----------------------------------
//--- instruction
//-----------------------------------
case 0:
dscInstruction = va_arg(ArgPtr, struct dsc$descriptor_s *);
psInstruction = malloc(dscInstruction->dsc$w_length + 1);
memset(psInstruction, 0, dscInstruction->dsc$w_length + 1);
strncpy(psInstruction, dscInstruction->dsc$a_pointer, dscInstruction->dsc$w_length);
*psInstruction = toupper(*psInstruction);
break;
//-----------------------------------
//--- Zone (cache) name
//-----------------------------------
case 1:
dscZoneName = va_arg(ArgPtr, struct dsc$descriptor_s *);
psZoneName = malloc(dscZoneName->dsc$w_length + 1);
memset(psZoneName, 0, dscZoneName->dsc$w_length + 1);
strncpy(psZoneName, dscZoneName->dsc$a_pointer, dscZoneName->dsc$w_length);
TruncateString(psZoneName);
break;
//-----------------------------------
//--- record number
//-----------------------------------
case 2:
dscRecordNumber = va_arg(ArgPtr, struct dsc$descriptor_s *);
if (dscRecordNumber != NULL)
{
iStatus = LIB$CVT_DX_DX((void *) dscRecordNumber, (void *) &dscCvtRecordNumber);
if (iStatus != SS$_NORMAL)
return 1;
}
break;
//-----------------------------------
//--- Buffer (record) information
//-----------------------------------
case 3:
dscBuffer = va_arg(ArgPtr, struct dsc$descriptor_s *);
if (dscBuffer != NULL)
{
prBuffer = dscBuffer->dsc$a_pointer; // get the pointer to our record
iBufferSize = dscBuffer->dsc$w_length; // get the size of the record
}
break;
//-----------------------------------
//--- Search for data
//-----------------------------------
case 4:
dscSearch = va_arg(ArgPtr, struct dsc$descriptor_s *);
if (dscSearch != NULL)
{
prSearchFor = dscSearch->dsc$a_pointer;
iSearchForSize = dscSearch->dsc$w_length;
}
break;
//-----------------------------------
//--- Search for start record number
//-----------------------------------
case 5:
dscStartRecord = va_arg(ArgPtr, struct dsc$descriptor_s *);
if (dscStartRecord != NULL)
{
iStatus = LIB$CVT_DX_DX((void *) dscStartRecord, (void *) &dscCvtStartRecord);
if (iStatus != SS$_NORMAL)
return 1;
}
break;
//-----------------------------------
//--- Fill Char
//-----------------------------------
case 6:
dscFilChar = va_arg(ArgPtr, struct dsc$descriptor_s *);
if (dscFilChar != NULL)
{
prFillChar = dscFilChar->dsc$a_pointer; // get the pointer to our char
igFillChar = *prFillChar;
}
break;
//-----------------------------------
//--- Debug Flags
//-----------------------------------
case 7:
dscDebugFlag = va_arg(ArgPtr, struct dsc$descriptor_s *);
igDEBUG_FLAGS = 1;
break;
}
}
va_end(ArgPtr);
//-------------------------------------------------------
// check for debug information
//-------------------------------------------------------
if (igDEBUG_FLAGS)
{
if (pfDEBUG_OUT == NULL)
pfDEBUG_OUT = fopen("debug_mem.dmp", "w");
if (dscDebugFlag != NULL)
if (strncmp(dscDebugFlag->dsc$a_pointer, "DUMP", dscDebugFlag->dsc$w_length) == 0)
DebugZoneDump(prRootZone);
if (strcmp(psInstruction, "SX"))
fprintf(pfDEBUG_OUT,"\nI (%2.2s) %s #%i -> %50.50s",
psInstruction, psZoneName, iRecordNumber, (char *)prBuffer);
else
fprintf(pfDEBUG_OUT,"\nI (%2.2s) %s #%i >> %50.50s",
psInstruction, psZoneName, iRecordNumber, (char *)prSearchFor);
}
//-------------------------------------------------------
// load any processing assumptions here
//-------------------------------------------------------
// APLDEF.ERRNB = 0; // start out with success
//-------------------------------------------------------
// check the instruction (what are we supposed to do?)
//-------------------------------------------------------
switch(*psInstruction)
{
//---------------------------------------------
// read a record from a cache
//---------------------------------------------
case 'R':
//-----------------------------------
// step one find the zone
//-----------------------------------
if (prRootZone == NULL)
{
memset(prBuffer, (int) ' ', (size_t) iBufferSize);
iStatus = 0;
break;
}
else
{
prThisZone = FindZone(psZoneName, prRootZone);
if (prThisZone == NULL)
{
memset(prBuffer, (int) ' ', (size_t) iBufferSize);
iStatus = 0;
break;
}
//-----------------------------------
// step two get the record
//-----------------------------------
iStatus = GetRecordFromBlock(prThisZone, iRecordNumber, prBuffer, iBufferSize);
if (iStatus)
{
// couldn't get the record from the zone
if (igFATAL_VIR_MEM_ERROR)
{
iStatus = 1;
igFATAL_VIR_MEM_ERROR = 1;
break;
}
}
}
break;
//---------------------------------------------
// write a record to a cache
//---------------------------------------------
case 'W':
//-----------------------------------
// step one find zone
// (create it if it doesn't exist)
//-----------------------------------
if (prRootZone == NULL)
{
iStatus = CreateZone(&prRootZone, psZoneName);
if (iStatus)
{
igFATAL_VIR_MEM_ERROR = 1; // we errored
iStatus = 1;
break;
}
prThisZone = prRootZone;
}
else
{
prThisZone = FindZone(psZoneName, prRootZone);
if (prThisZone == NULL)
{
iStatus = CreateZone(&prRootZone, psZoneName);
if (iStatus)
{
igFATAL_VIR_MEM_ERROR = 1; // we errored
iStatus = 1;
break;
}
prThisZone = FindZone(psZoneName, prRootZone);
if (prThisZone == NULL)
{
igFATAL_VIR_MEM_ERROR = 1; // we errored
iStatus = 1;
break;
}
}
}
//-----------------------------------
// step two write record
//-----------------------------------
iStatus = AddRecord2Block(prThisZone, iRecordNumber,
prBuffer, iBufferSize);
if (iStatus)
{
igFATAL_VIR_MEM_ERROR = 1; // we errored
iStatus = 1;
break;
}
break;
//---------------------------------------------
// clear a zone (cache)
//---------------------------------------------
case 'C':
//-----------------------------------
// step one find the zone
//-----------------------------------
if (prRootZone == NULL)
{
iStatus = 0; // nothing to do but call it
break; // an unqualified success
}
prThisZone = FindZone(psZoneName, prRootZone);
if (prThisZone == NULL)
{
iStatus = 0;
break;
}
iZoneId = prThisZone->iZoneId;
iStatus = LIB$RESET_VM_ZONE_64((void *) &iZoneId);
if (iStatus == SS$_NORMAL)
{
if (prThisZone->prMemBlock != NULL)
KillBlockStructures(prThisZone->prMemBlock);
iStatus = 0;
prThisZone->iBlockCount = 0;
prThisZone->prMemBlock = NULL;
}
else
{
// we hosed
igFATAL_VIR_MEM_ERROR = 1; // we errored
iStatus = 1;
break;
}
break;
//---------------------------------------------
// free up a cache
//---------------------------------------------
case 'F':
if (prRootZone == NULL)
iStatus = 0; // nothing to do...
else
iStatus = RemoveVirMemZone(psZoneName, &prRootZone);
break;
//---------------------------------------------
// search a cache
//---------------------------------------------
case 'S':
//-----------------------------------
// find the zone first
//-----------------------------------
if (prRootZone == NULL) // no zones to search
{
memset((void *) prBuffer, (int) ' ', (size_t) iBufferSize);
iStatus = 0;
break;
}
prThisZone = FindZone(psZoneName, prRootZone);
if (prThisZone == NULL) // our zone doesn't exist
{
memset((void *) prBuffer, (int) ' ', (size_t) iBufferSize);
iStatus = 0;
iRecordNumber = 0;
break;
}
//-----------------------------------
// search buffer
//-----------------------------------
prThisBlock = prThisZone->prMemBlock;
// need to deal with the starting record number...
iRecordsPerBlock = prThisZone->iRecordsPerBlock;
if (iSearchStart < 1)
iSearchStart = 1;
iBlockNumber = (iSearchStart - 1) / iRecordsPerBlock;
iCurrentBlock = 0;
iRecordSearch = (iSearchStart - 1) - (iBlockNumber * iRecordsPerBlock);
if (iRecordSearch < 0)
iRecordSearch = 0;
while (iCurrentBlock != iBlockNumber)
{
prThisBlock = prThisBlock->prNext;
if (prThisBlock == NULL)
break;
iCurrentBlock++;
}
if (prThisBlock == NULL)
{
memset((void *) prBuffer, (int) ' ', (size_t) iBufferSize);
iStatus = 0;
iRecordNumber = 0;
break;
}
FOREVER
{
if (strncmp(psInstruction, "SX", 2) == 0)
iStatus = FindDataInBlockStart(prThisZone,
prThisBlock,
prSearchFor,
iSearchForSize,
&prBuffer,
iBufferSize, iRecordSearch);
else
iStatus = FindDataInBlock(prThisZone,
prThisBlock,
prSearchFor,
iSearchForSize,
&prBuffer,
iBufferSize, iRecordSearch);
//-----------------------------------
// iStatus will contain the record number
// within the block if we get a hit
//-----------------------------------
if (iStatus)
break;
prThisBlock = prThisBlock->prNext;
if (prThisBlock == NULL)
{
memset((void *) prBuffer, (int) ' ', (size_t) iBufferSize);
iStatus = 0;
iRecordNumber = 0;
//---------------------------------------------
// convert record number to type of passed
// record number and load the descriptor
//---------------------------------------------
iStatus = LIB$CVT_DX_DX((void *) &dscCvtRecordNumber, (void *) dscRecordNumber);
if (iStatus != SS$_NORMAL)
{
iStatus = 1;
igFATAL_VIR_MEM_ERROR = 1;
}
else
iStatus = 0;
break;
}
iCurrentBlock++;
}
//---------------------------------------------
// If we got a hit then iStatus is holding the
// record number. Otherwise it is 0. It is
// possible that we have an error, so we look
// igFATAL_VIR_MEM_ERROR
//---------------------------------------------
if (iStatus && !igFATAL_VIR_MEM_ERROR)
iRecordNumber = (iStatus + (iCurrentBlock * iRecordsPerBlock));
else
iRecordNumber = 0;
//---------------------------------------------
// convert record number to type of passed
// record number and load the descriptor
//---------------------------------------------
iStatus = LIB$CVT_DX_DX((void *) &dscCvtRecordNumber, (void *) dscRecordNumber);
if (iStatus != SS$_NORMAL)
{
iStatus = 1;
igFATAL_VIR_MEM_ERROR = 1;
}
else
iStatus = 0;
break;
//---------------------------------------------
// Move a cache
//---------------------------------------------
case 'M':
iStatus = MoveZone2Buffer(psZoneName, prRootZone,
prBuffer, iBufferSize, iRecordNumber);
break;
//---------------------------------------------
// sort a cache
//---------------------------------------------
case 'O':
break;
//---------------------------------------------
// error, unknown instruction
//---------------------------------------------
default:
break;
};
//-------------------------------------------------------
// here we need to sort out the error conditions and
// return values before returning to our caller
//-------------------------------------------------------
if ((iStatus == 1) || (igFATAL_VIR_MEM_ERROR == 1))
{
//-----------------------------------
// return an empty buffer on an error
//-----------------------------------
memset(prBuffer, (int) ' ', (size_t) iBufferSize);
iStatus = 1; // error
}
else
iStatus = 0; // success
if (igDEBUG_FLAGS)
{
if (pfDEBUG_OUT == NULL)
pfDEBUG_OUT = fopen("debug_mem.dmp", "w");
fprintf(pfDEBUG_OUT,"\nO (%2.2s) %s #%i -> %50.50s",psInstruction, psZoneName, iRecordNumber, (char *)prBuffer);
}
//---------------------------------------------
// release allocated data structures that are
// non-persistent
//---------------------------------------------
free(psInstruction);
free(psZoneName);
return iStatus;
}
//-------------------------------------------------------
//find a zone by name
//-------------------------------------------------------
VIR_MEM_ZONE* FindZone(char *psName, VIR_MEM_ZONE *prZone)
{
VIR_MEM_ZONE *prThisZone = prZone;
FOREVER
{
if (prThisZone == NULL)
break;
if (prThisZone->psName == NULL)
break;
if (!strcmp(prThisZone->psName, psName))
break;
prThisZone = prThisZone->prNext;
}
if (prThisZone != NULL)
{
if (prThisZone->psName == NULL)
return NULL;
}
return prThisZone;
}
//-------------------------------------------------------
//create a new zone
//-------------------------------------------------------
int CreateZone(VIR_MEM_ZONE **prRoot, char *psName)
{
int iStatus = 0;
int64 iZoneId = 0; //64 bit zone id for vm call
VIR_MEM_ZONE *prThisZone = NULL;
//-------------------------------------------------------
// first we need to find the end of the linked list
// of zones so we can add our new zone
//-------------------------------------------------------
prThisZone = *prRoot;
if (prThisZone == NULL)
{
prThisZone = malloc(sizeof(VIR_MEM_ZONE));
if (prThisZone == NULL)
{
igFATAL_VIR_MEM_ERROR = 1; // WE FATALED
iStatus = -1;
return iStatus;
}
*prRoot = prThisZone;
}
else
{
while(prThisZone->prNext != NULL)
prThisZone = prThisZone->prNext;
//-------------------------------------------------------
// now we need to allocate the new node in the linked list
// and set the pointer to it.
//-------------------------------------------------------
prThisZone->prNext = malloc(sizeof(VIR_MEM_ZONE));
if (prThisZone->prNext == NULL)
{
igFATAL_VIR_MEM_ERROR = 1; // WE FATALED
iStatus = -1;
return iStatus;
}
//-------------------------------------------------------
// set the pointer (to simplify the reference) and
// initialize to nulls (we always want to init to a known
// value whenever we allocate anything from memory
//-------------------------------------------------------
prThisZone = prThisZone->prNext;
}
memset(prThisZone, 0, sizeof(VIR_MEM_ZONE));
//-------------------------------------------------------
// allocate space to hold the name and load it
//-------------------------------------------------------
prThisZone->psName = malloc(strlen(psName)+1);
if (prThisZone->psName == NULL)
{
igFATAL_VIR_MEM_ERROR = 1; // WE FATALED
iStatus = -1;
return iStatus;
}
strcpy(prThisZone->psName, psName);
//-------------------------------------------------------
// now we are ready to do the deed and create the VM zone
//-------------------------------------------------------
iStatus = LIB$CREATE_VM_ZONE_64((void *) &iZoneId,
&kVM_Algorithm,
&kVM_Argument,
&kVM_Flags,
&kVM_ExtendSize,
&kVM_InitSize,
&kVM_AllocBlockSize,
&kVM_Alignment,
&kVM_PageLimit);
switch (iStatus)
{
//---------------------------------------------
// successful completion
//---------------------------------------------
case SS$_NORMAL:
prThisZone->iZoneId = iZoneId;
iStatus = 0; // our idea of success flag
break;
//---------------------------------------------
// insufficient virtual memory
//---------------------------------------------
case LIB$_INSVIRMEM:
igFATAL_VIR_MEM_ERROR = 1; // WE FATALED
iStatus = -1;
break;
//---------------------------------------------
// invald argument
//---------------------------------------------
case LIB$_INVARG:
igFATAL_VIR_MEM_ERROR = 1; // WE FATALED
iStatus = -1;
break;
//---------------------------------------------
// invalid string descriptor for zone name
//---------------------------------------------
case LIB$_INVSTRDES:
igFATAL_VIR_MEM_ERROR = 1; // WE FATALED
iStatus = -1;
break;
};
return iStatus;
}
//-------------------------------------------------------
// add a memory block to a zone
//the zone must have already been found or created and
//is passed to us.
//-------------------------------------------------------
int AddBlock2Zone(VIR_MEM_ZONE *prZone, VIR_MEM_BLOCK **pprVmBlock)
{
VIR_MEM_BLOCK *prThisBlock = NULL;
int iStatus = 0;
int64 iBlockRequestSize = 0,
iBaseAddress = 0,
iZoneId = 0;
//-------------------------------------------------------
// need to figure out where this block needs to be added
// is it the very first block in a zone, or a new block
// being added to the end of the linked list of blocks
//-------------------------------------------------------
if (prZone->prMemBlock == NULL)
{
prZone->prMemBlock = malloc(sizeof(VIR_MEM_BLOCK));
if (prZone->prMemBlock == NULL)
{
igFATAL_VIR_MEM_ERROR = 1; // WE FATALED
iStatus = -1;
return iStatus;
}
prThisBlock = prZone->prMemBlock;
}
else // we are adding to the end of the linked list
{
prThisBlock = prZone->prMemBlock;
while (prThisBlock->prNext != NULL)
prThisBlock = prThisBlock->prNext;
prThisBlock->prNext = malloc(sizeof(VIR_MEM_BLOCK));
if (prThisBlock->prNext == NULL)
{
igFATAL_VIR_MEM_ERROR = 1; // WE FATALED
iStatus = -1;
return iStatus;
}
prThisBlock = prThisBlock->prNext;
}
//-------------------------------------------------------
// always init allocated structure to a known state
//-------------------------------------------------------
memset(prThisBlock, 0, sizeof(VIR_MEM_BLOCK));
//-------------------------------------------------------
// now we ask for the memory...
//-------------------------------------------------------
iBlockRequestSize = kVM_BlockSize;
iZoneId = prZone->iZoneId;
iStatus = LIB$GET_VM_64(&iBlockRequestSize, (void *) &iBaseAddress, &iZoneId);
switch(iStatus)
{
//---------------------------------------------
// we were successful in our request for memory
//---------------------------------------------
case SS$_NORMAL:
prThisBlock->iBaseAddress = iBaseAddress;
prZone->iBlockCount++;
*pprVmBlock = prThisBlock;
memset((void *) iBaseAddress, igFillChar, (size_t) iBlockRequestSize);
iStatus = 0; // our idea of success flag
break;
//---------------------------------------------
// Invalid Zone id or the zone is corrupt
//---------------------------------------------
case LIB$_BADBLOADR:
igFATAL_VIR_MEM_ERROR = 1; // WE FATALED
iStatus = -1;
break;
//---------------------------------------------
// bad block size
//---------------------------------------------
case LIB$_BADBLOSIZ:
igFATAL_VIR_MEM_ERROR = 1; // WE FATALED
iStatus = -1;
break;
//---------------------------------------------
// insufficient virtual memory (VMS said no)
//---------------------------------------------
case LIB$_INSVIRMEM:
igFATAL_VIR_MEM_ERROR = 1; // WE FATALED
iStatus = -1;
break;
//---------------------------------------------
// Allocation exceeds the page limit defined
// by the zone at create time
//---------------------------------------------
case LIB$_PAGLIMEXC:
igFATAL_VIR_MEM_ERROR = 1; // WE FATALED
iStatus = -1;
break;
};
return iStatus;
}
//-------------------------------------------------------
// add a record to a block in a zone
// the zone must have already been found (or created)
// and we are passed a pointer to the correct zone
//-------------------------------------------------------
int AddRecord2Block(VIR_MEM_ZONE *prZone, int iRecordNumber, void *prRecord, int iRecordSize)
{
int iStatus = 0, // return status variable
iRecordsPerBlock = 0, // how many records fit in a block?
iCurrentBlock = 0, // what is the current block we're on
iBlockNumber = 0; // block number to use
VIR_MEM_BLOCK *prThisBlock = NULL; // block to use
int64 iOffsetIntoBlock = 0; // used to calculate offset into block
//-------------------------------------------------------
// determine which block we want to get to...
//-------------------------------------------------------
if (prZone->iRecordSize == 0)
{
if (iRecordSize > kVM_BlockSize)
{
igFATAL_VIR_MEM_ERROR = 1; // WE FATALED
iStatus = -1;
return iStatus;
}
prZone->iRecordSize = iRecordSize;
}
//-------------------------------------------------------
// calculate a number of useful values
// blocks are numbered starting at 0
//-------------------------------------------------------
if (prZone->iRecordsPerBlock == 0)
{
iRecordsPerBlock = (kVM_BlockSize/ iRecordSize);
prZone->iRecordsPerBlock = iRecordsPerBlock;
}
else
iRecordsPerBlock = prZone->iRecordsPerBlock;
iBlockNumber = (iRecordNumber - 1) / iRecordsPerBlock;
iOffsetIntoBlock = iRecordNumber - (iBlockNumber * iRecordsPerBlock);
iOffsetIntoBlock--;
iOffsetIntoBlock *= prZone->iRecordSize;
if ((iBlockNumber + 1) > prZone->iBlockCount)
{
//-------------------------------------------------------
// we need to add blocks until we get to the block number
// desired
//-------------------------------------------------------
while((iBlockNumber + 1) > prZone->iBlockCount)
{
iStatus = AddBlock2Zone(prZone, &prThisBlock);
if (iStatus != 0)
{
igFATAL_VIR_MEM_ERROR = 1; // WE FATALED
iStatus = -1;
return iStatus;
}
}
}
else
{
//-------------------------------------------------------
//walk thru linked list until we find our block
//-------------------------------------------------------
iCurrentBlock = 0;
prThisBlock = prZone->prMemBlock;
while (iCurrentBlock != iBlockNumber)
{
prThisBlock = prThisBlock->prNext;
iCurrentBlock++;
if (prThisBlock == NULL)
{
//-----------------------------------
// we need to add blocks until we get
// to the block number desired
//-----------------------------------
while (iBlockNumber > iCurrentBlock)
{
iStatus = AddBlock2Zone(prZone, &prThisBlock);
if (iStatus != 0)
{
igFATAL_VIR_MEM_ERROR = 1; // WE FATALED
iStatus = -1;
return iStatus;
}
iCurrentBlock++;
}
break;
}
}
}
//-------------------------------------------------------
// at this point we now have all the info we need to
// write the record to the record within the current block
// of the current virtual memory zone.
//-------------------------------------------------------
if (iRecordSize > prZone->iRecordSize)
iRecordSize = prZone->iRecordSize;
memset((void *) (prThisBlock->iBaseAddress + iOffsetIntoBlock),
(int) ' ', (size_t) prZone->iRecordSize);
//-------------------------------------------------------
// the use of LIB$MOVC3 is an artifact from the original
// DIBOL version of this routine (plus originally I did not
// know how to get the pointers to be 64 bits in size.)
//-------------------------------------------------------
LIB$MOVC3 ((void *) &iRecordSize, (void *) prRecord,
(void *) (prThisBlock->iBaseAddress + iOffsetIntoBlock));
return iStatus;
}
//-------------------------------------------------------
// get a record from a block within a zone
// the zone must be set and the exist,
// if the block doesn't exist then an empty record is
// loaded
//-------------------------------------------------------
int GetRecordFromBlock(VIR_MEM_ZONE *prZone, int iRecordNumber, void *prRecord, int iRecordSize)
{
int iStatus = 0, // return status variable
iRecordsPerBlock = 0, // how many records fit in a block?
iCurrentBlock = 0, // what is the current block we're on
iBlockNumber = 0; // block number to use
VIR_MEM_BLOCK *prThisBlock = NULL; // block to use
int64 iOffsetIntoBlock = 0; // used to calculate offset into block
//-------------------------------------------------------
// calculate a number of useful values
// blocks are numbered starting at 0!
//-------------------------------------------------------
iRecordsPerBlock = prZone->iRecordsPerBlock;
iBlockNumber = (iRecordNumber - 1) / iRecordsPerBlock;
iOffsetIntoBlock = iRecordNumber - (iBlockNumber * iRecordsPerBlock);
iOffsetIntoBlock--;
iOffsetIntoBlock *= prZone->iRecordSize;
if ((iBlockNumber + 1) > prZone->iBlockCount)
{
memset(prRecord, (int) ' ', iRecordSize);
iStatus = 0;
return iStatus;
}
else
{
//-------------------------------------------------------
//walk thru linked list until we find our block
//-------------------------------------------------------
iCurrentBlock = 0;
prThisBlock = prZone->prMemBlock;
while (iCurrentBlock != iBlockNumber)
{
prThisBlock = prThisBlock->prNext;
iCurrentBlock++;
if (prThisBlock == NULL)
{
memset(prRecord, (int) ' ', iRecordSize);
iStatus = 0;
return iStatus;
}
}
}
//-------------------------------------------------------
// at this point we now have all the info we need to
// get the record to the record within the current block
// of the current virtual memory zone.
//-------------------------------------------------------
if (iRecordSize > prZone->iRecordSize)
iRecordSize = prZone->iRecordSize;
//-------------------------------------------------------
// the use of LIB$MOVC3 is an artifact from the original
// DIBOL version of this routine (plus originally I did not
// know how to get the pointers to be 64 bits in size.)
//-------------------------------------------------------
LIB$MOVC3((void *) &iRecordSize,
(void *) (prThisBlock->iBaseAddress + iOffsetIntoBlock),
(void *) prRecord);
return iStatus;
}
//-------------------------------------------------------
// remove zone
// this routine uses the zone name to remove an entry
// from the linked list and free up the entire memory zone
//-------------------------------------------------------
int RemoveVirMemZone( char *psZoneName, VIR_MEM_ZONE **pprRootZone)
{
int iStatus = 0; // return status variable
VIR_MEM_ZONE *prThisZone = NULL, // current zone
*prTheRoot = NULL, // dereference for **prRootZone
*prPrevZone = NULL; // previous zone
int64 iZoneId = 0;
//-------------------------------------------------------
// find the zone structure we want to free up
//-------------------------------------------------------
prTheRoot = *pprRootZone;
if (!strcmp(prTheRoot->psName, psZoneName))
{
prThisZone = prTheRoot;
*pprRootZone = prThisZone->prNext;
}
else
{
prThisZone = prTheRoot->prNext;
prPrevZone = prTheRoot;
if (prThisZone == NULL)
{
//-----------------------------------
// no zone, so there's nothing to do
//-----------------------------------
iStatus = 0;
return iStatus;
}
while (strcmp(prThisZone->psName, psZoneName))
{
prPrevZone = prThisZone;
prThisZone = prThisZone->prNext;
if (prThisZone == NULL)
{
//-----------------------------------
// no zone, so there's nothing to do
//-----------------------------------
iStatus = 0;
return iStatus;
}
} // while
prPrevZone->prNext = prThisZone->prNext;
if (prPrevZone == prTheRoot)
*pprRootZone = prPrevZone;
} // else
//-------------------------------------------------------
// ok, let's blow the zone away...
//-------------------------------------------------------
if (prThisZone)
{
iZoneId = prThisZone->iZoneId;
iStatus = LIB$DELETE_VM_ZONE_64((void *) &iZoneId);
switch (iStatus)
{
//---------------------------------------------
// normal completion, the zone is toast
//---------------------------------------------
case SS$_NORMAL:
if (prThisZone->prMemBlock != NULL)
KillBlockStructures(prThisZone->prMemBlock);
free(prThisZone); // free up the memory that was malloc'd
iStatus = 0; // set the status to our version of success
break;
//---------------------------------------------
// zone id was bad or the zone is corrupted
//---------------------------------------------
case LIB$_BADBLOADR:
igFATAL_VIR_MEM_ERROR = 1; // WE FATALED
iStatus = -1;
break;
};
}
//-------------------------------------------------------
// return to the caller
//-------------------------------------------------------
return iStatus;
}
//-------------------------------------------------------
// remove block of memory from linked list
//-------------------------------------------------------
int RemoveBlock(VIR_MEM_ZONE *prZone, int iBlockNumber)
{
int iStatus = 0, // return status variable
iCurrentBlock = 0; // current block we're on
VIR_MEM_BLOCK *prThisBlock = NULL, // pointer to current block
*prPriorBlock = NULL; // pointer to prior block
int64 iBlockRequestSize = 0,
iBaseAddress = 0,
iZoneId = 0;
//-------------------------------------------------------
//
//-------------------------------------------------------
if ((iBlockNumber + 1) > prZone->iBlockCount)
{
iStatus = 0;
return iStatus;
}
//-------------------------------------------------------
// get the block and adjust the linked list pointers
//-------------------------------------------------------
if (iBlockNumber == 0)
{
prThisBlock = prZone->prMemBlock;
prZone->prMemBlock = prThisBlock->prNext;
prZone->iBlockCount--;
}
else
{
prThisBlock = prZone->prMemBlock;
while (iCurrentBlock != iBlockNumber)
{
prPriorBlock = prThisBlock;
prThisBlock = prThisBlock->prNext;
iCurrentBlock++;
if (prThisBlock == NULL)
{
// we hosed the linked list somehow...
}
}
prPriorBlock->prNext = prThisBlock->prNext;
prZone->iBlockCount--;
}
//-------------------------------------------------------
// now let's free up that sucker...
//-------------------------------------------------------
iBlockRequestSize = kVM_BlockSize;
iBaseAddress = prThisBlock->iBaseAddress;
iZoneId = prZone->iZoneId;
memset((void *) iBaseAddress, 0, (size_t) iBlockRequestSize);
iStatus = LIB$FREE_VM_64((void *) &iBlockRequestSize, (void *) &iBaseAddress, (void *) &iZoneId);
switch(iStatus)
{
//---------------------------------------------
// successful, normal completion
//---------------------------------------------
case SS$_NORMAL:
free(prThisBlock); // release the malloc'd memory
iStatus = 0; // return our version of success
break;
//---------------------------------------------
// the base address argument had an invalid
// address, the zone was corrupt, or the alignment
// was incorrect.
//---------------------------------------------
case LIB$_BADBLOADR:
igFATAL_VIR_MEM_ERROR = 1; // WE FATALED
iStatus = -1;
break;
//---------------------------------------------
// the block size was wrong
//---------------------------------------------
case LIB$_BADBLOSIZ:
igFATAL_VIR_MEM_ERROR = 1; // WE FATALED
iStatus = -1;
break;
//---------------------------------------------
// the boundary tag field(s) is/are corrupted
//---------------------------------------------
case LIB$_BADTAGVAL:
igFATAL_VIR_MEM_ERROR = 1; // WE FATALED
iStatus = -1;
break;
};
//-------------------------------------------------------
// return to the caller
//-------------------------------------------------------
return iStatus;
}
//-------------------------------------------------------
// search a block for some binary data
//
// we are writing records into the cache as is. There
// can be embedded integers, floating point, and other
// binary values. For this reason, we cannot use string
// searches but have to do memcmp's as we walk thru the
// memory held by the zone.
//
//-------------------------------------------------------
int FindDataInBlock(VIR_MEM_ZONE *prZone, VIR_MEM_BLOCK *prThisBlock, void *prLookFor,
int iByteCount, void **prFound, int iBufferSize, int iStartRecord)
{
int iStatus = 0, // return status variable
iRecordNumber = 0, // what is the record number we found it in?
iFoundOne = 0, // flag for success in search
iRecordSize = 0, // get the recordsize (without the pointer)
iRecordsPerBlock = 0; // how many records fit in a block?
int64 iByteRange = 0, // what is the last position we can look at
iRangeStart = 0, // start of block (sans pointer)
iSearchOffset = 0; // offset for memcmp into block
//-------------------------------------------------------
// get some useful values
//-------------------------------------------------------
iRecordSize = prZone->iRecordSize;
iRecordsPerBlock = prZone->iRecordsPerBlock;
iByteRange = iRecordSize * iRecordsPerBlock;
iRangeStart = prThisBlock->iBaseAddress;
//-------------------------------------------------------
// Do the search
//-------------------------------------------------------
iSearchOffset = iRangeStart; // start for search
iFoundOne = 0; // make sure flag is reset each time
//-------------------------------------------------------
// adjust start range for first search by starting record value
//-------------------------------------------------------
iSearchOffset = iSearchOffset + (iRecordSize * iStartRecord);
FOREVER
{
if (!memcmp((void *) iSearchOffset, prLookFor, (size_t)iByteCount))
{
iFoundOne = 1; // we got a hit!
break; // bail from loop
}
iSearchOffset++; // next position
//-------------------------------------------------------
// if the remaining bytes in the block is less than the
// size of the search for object, then bail
//-------------------------------------------------------
if (((iSearchOffset - iRangeStart) + iByteCount) > iByteRange)
break;
}
//-------------------------------------------------------
// did we find a match?
//-------------------------------------------------------
if (!iFoundOne)
{
iStatus = 0; // not found
return iStatus; // bail
}
//-------------------------------------------------------
// now we need to figure out which record it is within
// the block
//-------------------------------------------------------
iRecordNumber = ((iSearchOffset - prThisBlock->iBaseAddress) / iRecordSize) + 1;
if (iRecordSize <= iBufferSize)
memmove((void *)*prFound,
(void *) (prThisBlock->iBaseAddress + ((iRecordNumber - 1) * iRecordSize)),
(size_t) iRecordSize);
else
memmove((void *)*prFound,
(void *) (prThisBlock->iBaseAddress + ((iRecordNumber - 1) * iRecordSize)),
(size_t) iBufferSize);
iStatus = iRecordNumber; // return the record number to the caller
//-------------------------------------------------------
// return to caller
//-------------------------------------------------------
return iStatus;
}
//-------------------------------------------------------
// search a block for some binary data at the start of
// each record
//
// we are writing records into the cache as is. There
// can be embedded integers, floating point, and other
// binary values. For this reason, we cannot use string
// searches but have to do memcmp's as we walk thru the
// memory held by the zone.
//
//-------------------------------------------------------
int FindDataInBlockStart(VIR_MEM_ZONE *prZone, VIR_MEM_BLOCK *prThisBlock, void *prLookFor,
int iByteCount, void **prFound, int iBufferSize, int iStartRecord)
{
int iStatus = 0, // return status variable
iRecordNumber = 0, // what is the record number we found it in?
iFoundOne = 0, // flag for success in search
iRecordSize = 0, // get the recordsize (without the pointer)
iRecordsPerBlock = 0; // how many records fit in a block?
int64 iByteRange = 0, // what is the last position we can look at
iRangeStart = 0, // start of block (sans pointer)
iSearchOffset = 0; // offset for memcmp into block
//-------------------------------------------------------
// get some useful values
//-------------------------------------------------------
iRecordSize = prZone->iRecordSize;
iRecordsPerBlock = prZone->iRecordsPerBlock;
iByteRange = iRecordSize * iRecordsPerBlock;
iRangeStart = prThisBlock->iBaseAddress;
//-------------------------------------------------------
// Do the search
//-------------------------------------------------------
iSearchOffset = iRangeStart; // start for search
iFoundOne = 0; // make sure flag is reset each time
//-------------------------------------------------------
// adjust start range for first search by starting record value
//-------------------------------------------------------
iSearchOffset = iSearchOffset + (iRecordSize * iStartRecord);
FOREVER
{
if (!memcmp((void *) iSearchOffset, prLookFor, (size_t)iByteCount))
{
iFoundOne = 1; // we got a hit!
break; // bail from loop
}
iSearchOffset += iRecordSize; // next position (we go by yhe size of the record)
//-------------------------------------------------------
// if the remaining bytes in the block is less than the
// size of the search for object, then bail
//-------------------------------------------------------
if (((iSearchOffset - iRangeStart) + iByteCount) > iByteRange)
break;
}
//-------------------------------------------------------
// did we find a match?
//-------------------------------------------------------
if (!iFoundOne)
{
iStatus = 0; // not found
return iStatus; // bail
}
//-------------------------------------------------------
// now we need to figure out which record it is within
// the block
//-------------------------------------------------------
iRecordNumber = ((iSearchOffset - prThisBlock->iBaseAddress) / iRecordSize) + 1;
if (iRecordSize > iBufferSize)
iRecordSize = iBufferSize;
memmove((void *)*prFound,
(void *) (prThisBlock->iBaseAddress + ((iRecordNumber - 1) * iRecordSize)),
(size_t) iRecordSize);
iStatus = iRecordNumber; // return the record number to the caller
//-------------------------------------------------------
// return to caller
//-------------------------------------------------------
return iStatus;
}
//-------------------------------------------------------
// recursive routine to free up all the VM block
// data structures
//-------------------------------------------------------
void KillBlockStructures(VIR_MEM_BLOCK *prBlock)
{
if (prBlock->prNext != NULL)
KillBlockStructures(prBlock->prNext);
memset((void *) prBlock->iBaseAddress, 0, (size_t) kVM_BlockSize);
free(prBlock);
return;
}
//-------------------------------------------------------
// truncate string
//-------------------------------------------------------
void TruncateString(char *psString)
{
int iLength = 0,
iIndex = 0;
char *psThisChar = NULL;
iLength = strlen(psString);
iIndex = iLength - 1;
if (!iLength)
return;
psThisChar = psString + iIndex;
while ((*psThisChar == ' ') || (*psThisChar == 0))
{
*psThisChar = 0;
iIndex--;
if (iIndex < 0)
break;
psThisChar--;
}
return;
}
//-------------------------------------------------------
//move (copy) the contents of the entire zone into a buffer
//-------------------------------------------------------
int MoveZone2Buffer(char *psZoneName, VIR_MEM_ZONE *prRootZone,
void *prBuffer, int iBufferSize, int iRecordCount)
{
int iBail = 0, // we're done flag
iMovedCount = 0, // howmany records have we moved
iStatus = 0; // return status variable
int64 iBaseAddress = 0, // dereference the base address
iOffsetIntoBlock = 0, // offset into block
iOffsetIntoBuffer = 0, // for computing record starts
iBlockByteCount = 0, // total useable bytes in block
iBytes2Move = 0; // number of bytes to copy
char *psBlankString = NULL, // to use to load spaces
*psNullString = NULL; // for a block of NULLs
VIR_MEM_ZONE *prThisZone = NULL; // pointer to zone we are using
VIR_MEM_BLOCK *prThisBlock = NULL; // pointer to current VM Block
//---------------------------------------------
// find the virtual memory zone we need
//---------------------------------------------
prThisZone = FindZone(psZoneName, prRootZone);
if (prThisZone == NULL)
{
// fill the buffer with spaces and return
memset((void *)prBuffer, (int) ' ', (size_t) iBufferSize);
iStatus = 0;
return iStatus;
}
//---------------------------------------------
// calc the number of bytes in a zone
//---------------------------------------------
iBytes2Move = prThisZone->iRecordSize;
iBlockByteCount = iBytes2Move * (prThisZone->iRecordsPerBlock);
iOffsetIntoBuffer = (int64) prBuffer;
psNullString = malloc((size_t) iBytes2Move);
psBlankString = malloc((size_t) iBytes2Move);
if ((psNullString == NULL) || (psBlankString == NULL))
{
free(psNullString);
free(psBlankString);
iStatus = 1;
igFATAL_VIR_MEM_ERROR = 1;
return iStatus;
}
memset((void *)psNullString, 0, (size_t) iBytes2Move);
memset((void *)psBlankString, (int) ' ', (size_t) iBytes2Move);
//---------------------------------------------
// find the first block within the zone
//---------------------------------------------
prThisBlock = prThisZone->prMemBlock;
if (prThisBlock == NULL)
{
// fill the buffer with spaces and return
memset((void *)prBuffer, (int) ' ', (size_t) iBufferSize);
iStatus = 0;
return iStatus;
}
//---------------------------------------------
// loop thru the blocks and grab the data
//---------------------------------------------
iBail = 0;
iMovedCount = 0;
while ((prThisBlock != NULL) && (!iBail))
{
iBaseAddress = prThisBlock->iBaseAddress;
iOffsetIntoBlock = iBaseAddress;
while((iOffsetIntoBlock - iBaseAddress) < iBlockByteCount)
{
if (memcmp( (void *) psNullString,
(void *)(iOffsetIntoBlock),
(size_t) iBytes2Move))
{
LIB$MOVC3((void *) &iBytes2Move,
(void *) iOffsetIntoBlock,
(void *) iOffsetIntoBuffer);
iMovedCount++;
if (iRecordCount)
if (iMovedCount == iRecordCount)
{
iBail = 1;
break;
}
}
else
{
iBail = 1;
break;
}
iOffsetIntoBuffer += iBytes2Move;
iOffsetIntoBlock += iBytes2Move;
}
prThisBlock = prThisBlock->prNext;
}
free(psBlankString);
free(psNullString);
return iStatus;
}
//-------------------------------------------------------
//debug dump of data structures
//-------------------------------------------------------
void DebugZoneDump(VIR_MEM_ZONE *prRootZone)
{
VIR_MEM_ZONE *prThisZone = NULL;
VIR_MEM_BLOCK *prThisBlock = NULL;
int iStatus = 0,
iRecNum = 0;
unsigned short iOutLen = 0;
int64 iArgList[2] = {0,0};
char szTempStr[50 + 1],
szOutBuff[80+1];
DSCS_S dscControlStr = { 3, DSC$K_DTYPE_T, DSC$K_CLASS_S, "!ZQ"},
dscControlStr2 = { 3, DSC$K_DTYPE_T, DSC$K_CLASS_S, "!XQ"},
dscOutStr = {80, DSC$K_DTYPE_T, DSC$K_CLASS_S, szOutBuff};
memset(szOutBuff, 0, 81);
prThisZone = prRootZone;
//-------------------------------------------------------
// walk thru the list of VM zones we have in use
//-------------------------------------------------------
while(prThisZone != NULL)
{
iArgList[0] = prThisZone->iZoneId;
iStatus = sys$faol_64(&dscControlStr, &iOutLen, &dscOutStr, &iArgList[0]);
fprintf (pfDEBUG_OUT, "\n %s [%s] blks: %d rsiz: %d fit: %d",
prThisZone->psName, szOutBuff,
prThisZone->iBlockCount, prThisZone->iRecordSize,
prThisZone->iRecordsPerBlock);
prThisBlock = prThisZone->prMemBlock;
//-------------------------------------------------------
// walk thru the blocks in this zone
//-------------------------------------------------------
while (prThisBlock != NULL)
{
iRecNum++;
memset(szOutBuff, 0, 81);
iArgList[0] = prThisBlock->iBaseAddress;
iStatus = sys$faol_64(&dscControlStr2, &iOutLen, &dscOutStr, &iArgList[0]);
fprintf(pfDEBUG_OUT, "\n #%04d [%s] cnt: %04d ",
iRecNum, szOutBuff,
prThisBlock->iRecordCount);
//-------------------------------------------------------
// print the first 50 bytes of data
//-------------------------------------------------------
memset (szTempStr, 0, 51);
if (prThisZone->iRecordSize >= 50)
memcpy (szTempStr, (void*) prThisBlock->iBaseAddress, 50);
else
memcpy (szTempStr, (void*) prThisBlock->iBaseAddress, prThisZone->iRecordSize);
fprintf(pfDEBUG_OUT, "%s", szTempStr);
prThisBlock = prThisBlock->prNext;
}
prThisZone = prThisZone->prNext;
}
return;
}