Skip to content

gmSCPagingSystemClass

The service class PagingSystem manages the access of files whose entire content may not be stored in memory at the same time. These files are ultimately read and written via the Offline class, but they contain information that must be persistent which either grows during the time that it is being used or is too large to be stored entirely in memory. To work with these files, they are broken into fixed sized blocks, not all of which need to be memory resident at the same time. The methods in this class keep track of which blocks are currently in memory, where those blocks are in memory, and whether or not those blocks have been changed since they were last accessed. In addition, they must decide which file block to remove from memory when the allocated memory block count for the file has been exhausted.

There are three different approaches that can be used — BlockVector, BlockSequence, and SearchForBlock. The BlockVector approach keeps a linear byte array indexed by the maximum number of blocks to be stored on the file. Each byte simply contains the number of the memory area containing the file block, if that block is in memory, or a zero if that block is not in memory. This approach is by far the fastest, but it requires as many bytes of memory as there are blocks on the file and it requires that the maximum size of the file be known when it is opened or created. The BlockSequence approach uses the MemorySequence class to maintain the memory block numbers that correspond to the file block numbers. The advantage here is that the maximum size of the file need not be known when it is opened or created. The disadvantage is slightly slower performance and the need to potentially create an extremely large memory sequence. The SearchForBlock approach keeps a linear array indexed by the maximum number of blocks allowed in memory. The blocks are always kept in numeric order by their number in the file. Each time a block is accessed, this array is binary searched to determine if the block is currently in memory. This approach is the most general since its memory requirements are independent of the size of the file but this approach is also the slowest.

The names of these paging approaches are in the PagingType enumeration. This enumeration contains two additional entries — MemoryMapped and MemorySequence. These two approaches retain the entire file content in memory and can obviously only be used when the file size makes this possible. They are both much more efficient then approaches describe above, but do not support persistence. The MemoryMapped approach has the entire file mapped into memory. It can be used to work with a previously created file whose size will not change. The MemorySequence approach stores block pointers in a MemorySequence and therefore allows the information stored to grow; however, there is no actual file backing the information up so it is not persistent.

The notion of semi-permanent pointers pervades this approach to information management. The basic idea is that a page pointer is a valid memory pointer until the block which it contains is swapped out of memory. Thus these pointers can be used safely within local blocks of code where efficiency is needed, even though they cannot be saved and reused over longer stretches of code.


Prototype

UBYTE* PagingSystem_Access(void* This,int BlockNumber,int Delta);

The PagingSystem_Access method accesses a block from a paged file. It returns a pointer to the start of a page in the paging system which contains a specified block from the file being managed. Blocks are numbered sequentially starting at 1. Note that passing the method a block number larger than the current block count may force it to add new blocks to the back of the file. This method should only be passed existing block numbers. The method PagingSystem_AddBlock should be used to expand the file. Its parameters are:

ParameterDescription
ThisSpecifies the handle for the paging system to be accessed. This must have been
obtained from the PagingSystem_Create method.
BlockNumberSpecifies the number of the desired block, where blocks are numbered starting
at 1, for the desired page.
DeltaSpecifies a flag, which if non-zero, indicates that the caller intends to change
the information within the block. Only blocks accessed via a non-zero delta are
written back to their file when the block is removed from memory.

The method returns a semi-permanent pointer to the start of the block, or a NULL if something went wrong.


Prototype

UBYTE* PagingSystem_AddBlock(void* This,int* BlockNumber);

The PagingSystem_AddBlock method adds a new block to a paging system and returns a semi-permanent pointer to its memory image. In addition, the number of the block may be returned. Note that this method is the only one to be used to add blocks to the file. The PagingSystemAccess method is only used to access existing blocks. Its parameters are:

ParameterDescription
ThisSpecifies the handle for the paging system to be accessed. This must have been
obtained from the PagingSystem_Create method.
BlockNumberreturns the number of the block that been has created, if it is not NULL.

If the paging system has a maximum number of blocks specified, then it returns NULL if that maximum has been exceeded; else it returns a semi-permanent byte pointer to the start of the new block. This new block is initialized at zero.


Prototype

void PagingSystem_Close(void* This);

The PagingSystem_Close method closes a PagingSystem instance, by returning any memory occupied by it to the operating system. Before doing so it writes any of its blocks that have been changed in memory to the file being controlled by the system. Note that this method does not close the actual file, just as the PagingSystem_Create method does not open the file. Its parameter is:

ParameterDescription
ThisSpecifies the handle for the paging system to be accessed. This must have been
obtained from the PagingSystem_Create method.

The method has no return value.


Prototype

void* PagingSystem_Create(void* File,int Algorithm,int PageSize,int MaxPages,int MaxBlocks,int BlockCount);

The PagingSystem_Create method creates a PagingSystem instance for a file. This instance can then be used to access blocks on the file as stored in memory pages. Its parameters are:

ParameterDescription
FileSpecifies the handle for the file as returned either by the
Offline_OpenFile or Offline_CreateFile methods. The methods in the
Offline class perform all physical file accesses for the file.
AlgorithmSpecifies the algorithm to be used for determining if a given block on the file is
currently in memory and if so which page is it in. One of the three enumeration
entries: PagingType_BlockVector, PagingType_BlockSequence, or
PagingType_SearchForBlock must be used. These are explained in the header for this
class.
PageSizeSpecifies the size of each page and thus block of the file specified in bytes. If
set to zero then the PagingSystem_PageSize value is used. Note that the page
size of the file when it is opened must match the pagesize when it is created. It
is up to the user of this class to ensure this.
MaxPagesSpecifies the maximum number of pages to be stored in memory for the file. This
value cannot exceed 255. If it is larger than 255 or zero, then the
MAX_PAGES_DEFAULT value is used.
MaxBlocksSpecifies the maximum number of blocks to be on the file. This value is needed
only for the BlockVector algorithm. It is used by the other algorithms only
by the PagingSystem_AddBlock method as a constraint on the overall
filesize. If no such constraint is desired, then set this parameter to zero.
BlockCountspecifies the actual number of blocks on the file. When the file is initially
created, this should be zero. When the file is opened it should reflect the actual
number of blocks on the file. As with pagesize, it is up to the user of this
method to determine this value.

If all goes well this method returns a handle for the control structure that will page the blocks of the file. If there is insufficient memory to allocate the various needed components, then a NULL is returned.