Modula-2 Reloaded

A Modern Typesafe & Literate Programming Notation

Site Menu

Project

Specification

Implementation

Recommendations

Reference

Needs Updating

Work in Progress

Wastebasket

Wiki Manual

edit SideBar

Key Value Store

DEFINITION MODULE @@module@@;

(* Generic Key Valye Storage Template *)

(* ---------------------------------------------------------------------------
 * This template is expanded by the M2R10 template engine utility. Expansion
 * can be invoked from within a compiling source file using the MAKE pragma:
 * <* MAKE = "m2te KeyValueStore module:'FooHashTab' component:'FooRecord'" *>
 * IMPORT FooHashTab;
 * ------------------------------------------------------------------------ *)


FROM Collections IMPORT Capacity, Status;


CONST

(* ---------------------------------------------------------------------------
 * Default table size
 * ------------------------------------------------------------------------ *)

    defaultCapacity = 1031;  (* 1031 buckets *)


(* ---------------------------------------------------------------------------
 * Maximum table size
 * ------------------------------------------------------------------------ *)

    maximumCapacity = 16777259;  (* more than 16 million buckets *)


(* ---------------------------------------------------------------------------
 * Maximum number of entries
 * ------------------------------------------------------------------------ *)

    entryLimit = 1024*1024*1024;  (* more than 1 billion entries *)


(* ---------------------------------------------------------------------------
 * Synonyms for status codes
 * ------------------------------------------------------------------------ *)

    invalidTable = invalidCollection;
    entryLimitReached = collectionFull;


TYPE

(* ---------------------------------------------------------------------------
 * Opaque handle type:  @@module@@.Table
 * ------------------------------------------------------------------------ *)

    @@module@@ = OPAQUE;


(* ---------------------------------------------------------------------------
 * function:  @@module@@.new ( size, status )
 * ---------------------------------------------------------------------------
 *
 * Creates  and returns a new table object  with a capacity of <size> buckets.
 * Each bucket  can hold  multiple entries.  If  zero  is passed in for <size>
 * then the table will be created  with defaultCapacity number of buckets.
 * If the value passed in for <size> is greater than maximumCapacity or if
 * memory could not be allocated then no table will be created and NIL will be
 * returned.
 *
 * The status of the operation is passed back in <status>. *)

PROCEDURE new ( size : Capacity; VAR status : Status ) : @@module@@;


(* ---------------------------------------------------------------------------
 * function:  @@module@@.storeValue( table, key, val, size, zT, status )
 * ---------------------------------------------------------------------------
 *
 * Adds a new entry  for key <key>  to table <table>.  The new entry is stored
 * by value.  Data is copied from the address passed in as <value>.  If <size>
 * is not zero, then <size> number of bytes are copied.  If <size> is zero and
 * <zeroTerminated> is true,  then data will be copied up to and including the
 * first zero-value byte encountered.  If <size> is zero  and <zeroTerminated>
 * is false,  then the operation will fail and no entry will be added.  If the
 * operation succeeds,  then the initial reference count of the new entry will
 * be set to one.  Keys must be unique.  Existing entries are not replaced.
 * Duplicate entries are not added.
 *
 * The status of the operation is passed back in <status>. *)

PROCEDURE storeValue ( table          : @@module@@;
                       key            : Key;
                       value          : ValueType;
                       size           : CARDINAL;
                       zeroTerminated : BOOLEAN;
                   VAR status         : Status );


(* ---------------------------------------------------------------------------
 * function:  @@module@@.storeReference( table, key, val, size, zT, status )
 * ---------------------------------------------------------------------------
 *
 * Adds a new entry  for key <key>  to table <table>.  The new entry is stored
 * by reference.  No data is copied.  If <size> is zero  and  <zeroTerminated>
 * is true,  then  the size of the referenced data  is calculated  by counting
 * up to  and including  the  first  zero-value byte.  The size of the data is
 * then stored for faster retrieval by-copy of the entry.  Entries  stored  by
 * reference  and for which  the size  is unknown cannot be retrieved by copy.
 * The initial reference count of the new entry will be set to one.  Keys must
 * be unique.  Existing  entries  are  not  replaced.  Duplicate  entries  are
 * not added.
 *
 * The status of the operation is passed back in <status>. *)

PROCEDURE storeReference ( table          : @@module@@;
                           key            : Key;
                           value          : ValueType;
                           size           : CARDINAL;
                           zeroTerminated : BOOLEAN;
                       VAR status         : Status );


(* ---------------------------------------------------------------------------
 * function:  @@module@@.entryExists( table, key, status )
 * ---------------------------------------------------------------------------
 *
 * Returns  TRUE  if a  valid entry  for <key>  is stored in <table>,  returns
 * FALSE otherwise.  If an entry is found,  valid or invalid,  then it will be
 * cached internally  and a  subsequent search request  for the same key  will
 * check the cached entry first,  which is  slighly faster  than a lookup of a
 * non-cached entry.  The reference count of the entry is  not  modified.
 *
 * The status of the operation is passed back in <status>. *)

PROCEDURE entryExists ( table   : @@module@@;
                        key    : Key;
                    VAR status : Status ) : ValueType;


(* ---------------------------------------------------------------------------
 * function:  @@module@@.getEntry( table, copy, key, size, zT, status )
 * ---------------------------------------------------------------------------
 *
 * Retrieves the table entry stored in <table> for <key>  either by copy or by
 * reference.  If  TRUE  is passed in for <copy>,  then  the  function returns
 * the entry's data by-copy,  otherwise it returns the data by-reference.
 *
 * For by-copy retrieval,  if the entry exists,  a newly allocated copy of its
 * value is created,  and a pointer to it is returned as function result.  The
 * size of the entry's data (in bytes)  is passed back in <size>.  However, if
 * the size of the entry's data is unknown,  then  no copy is made and  NIL is
 * returned.  The entry's reference count is never incremented when retrieving
 * by copy.
 *
 * For by-reference retrieval,  if the entry exists,  a pointer to the entry's
 * data  is returned as function result  and  the  entry's reference count  is
 * incremented.  The size of the  entry's data  (in bytes)  is  passed back in
 * <size>.  However,  if the size of the entry's data is  unknown,  then  zero
 * is passed back in <size>.
 *
 * If the entry's data is zero-terminated,  then  TRUE  will be passed back in
 * <zeroTerminated>,  otherwise  FALSE  will be passed back.
 *
 * If the entry has been successfully retrieved,  then it is cached within the
 * table,  regardless of whether it was returned by copy or by reference.
 *
 * If the entry does not exist,  or,  if it has been marked for removal,  then
 * no data is copied,  no table meta data is modified,  no entry meta data  is
 * modified  and NIL is returned.
 *
 * The status of the operation is passed back in <status>. *)

PROCEDURE getEntry ( table          : @@module@@;
                     copy           : BOOLEAN;
                     key            : Key;
                 VAR size           : Capacity;
                 VAR zeroTerminated : BOOLEAN;
                 VAR status         : Status ) : ValueType;


(* ---------------------------------------------------------------------------
 * function:  @@module@@.valueForKey( table, key, status )
 * ---------------------------------------------------------------------------
 *
 * Retrieves the entry stored in table <table> for <key> and returns a pointer
 * to a  newly  allocated  copy  of the  entry's value.  The entry's reference
 * count is NOT incremented.  Entries that have been stored  by reference  and
 * are not zero-terminated can  only  be retrieved by value if their data size
 * was  explicitly  passed in  when  they  were  stored.  If  no entry  exists
 * for <key>  or if the entry is pending removal  or  if the size of the entry
 * is unknown,  then  NIL  is  returned.
 *
 * The status of the operation is passed back in <status>. *)

PROCEDURE valueForKey ( table  : @@module@@;
                        key    : Key;
                    VAR status : Status ) : ValueType;


(* ---------------------------------------------------------------------------
 * function:  @@module@@.referenceForKey( table, key, status )
 * ---------------------------------------------------------------------------
 *
 * Retrieves the entry stored in table <table> for <key> and returns a pointer
 * to the  entry's value  in the table  and  increments the  entry's reference
 * count.  If  no entry exists  for <key>  or if the entry is pending removal,
 * is unknown then NIL is returned.
 *
 * The status of the operation is passed back in <status>. *)

PROCEDURE referenceForKey ( table  : @@module@@;
                            key    : Key;
                        VAR status : Status ) : ValueType;


(* ---------------------------------------------------------------------------
 * function:  @@module@@.sizeForKey( table, key, status )
 * ---------------------------------------------------------------------------
 *
 * Returns  the size of the data of the entry stored in <table> for <key>.  If
 * no entry exists for <key> then zero is returned.
 *
 * The status of the operation is passed back in <status>. *)

PROCEDURE sizeForKey ( table  : @@module@@;
                       key    : Key;
                   VAR status : Status ) : CARDINAL;


(* ---------------------------------------------------------------------------
 * function:  @@module@@.dataForKeyIsZeroTerminated( table, key, status )
 * ---------------------------------------------------------------------------
 *
 * Returns the zero-terminated flag of the entry stored in <table>  for <key>.
 * If no entry exists for <key> in <table> then FALSE is returned.
 *
 * The status of the operation is passed back in <status>. *)

PROCEDURE dataForKeyIsZeroTerminated ( table  : @@module@@;
                                       key    : Key;
                                   VAR status : Status ) : BOOLEAN;


(* ---------------------------------------------------------------------------
 * function:  @@module@@.referenceCountForKey( table, key, status )
 * ---------------------------------------------------------------------------
 *
 * Returns the  reference count  of the entry stored in <table> for <key>.  If
 * no entry exists for <key> in <table> then zero is returned.  Valid  entries
 * always have a reference count greater than zero.
 *
 * The status of the operation is passed back in <status>. *)

PROCEDURE referenceCountForKey ( table  : @@module@@;
                                 key    : Key;
                             VAR status : Status ) : CARDINAL;


(* ---------------------------------------------------------------------------
 * function:  @@module@@.releaseEntry( table, key, status )
 * ---------------------------------------------------------------------------
 *
 * Decrements  the reference count  of the entry stored in <table>  for <key>.
 * If the entry has previously been marked for removal and its reference count
 * reaches one as a result of this release then the entry will be removed.
 *
 * The status of the operation is passed back in <status>. *)

PROCEDURE releaseEntry ( table  : @@module@@;
                         key    : Key;
                     VAR status : Status );



(* ---------------------------------------------------------------------------
 * function:  @@module@@.removeEntry( table, key, status )
 * ---------------------------------------------------------------------------
 *
 * Marks the entry stored in <table> for <key> as removed.  An entry which has
 * been marked as removed can no longer be retrieved  and will be removed when
 * its reference count reaches zero.
 *
 * The status of the operation is passed back in <status>. *)

PROCEDURE removeEntry ( table  : @@module@@;
                        key    : Key;
                    VAR status : Status );


(* ---------------------------------------------------------------------------
 * function:  @@module@@.capacity( table )
 * ---------------------------------------------------------------------------
 *
 * Returns the number of buckets of <table>,  returns zero if NIL is passed in
 * for <table>. *)

PROCEDURE capacity ( table : @@module@@ ) : Capacity;


(* ---------------------------------------------------------------------------
 * function:  @@module@@.entryCount( table )
 * ---------------------------------------------------------------------------
 *
 * Returns the number of entries stored in table <table>,  returns zero if NIL
 * is passed in for <table>. *)

PROCEDURE entryCount ( table : @@module@@ ) : Capacity;


(* ---------------------------------------------------------------------------
 * function:  @@module@@.isResizable( table )
 * ---------------------------------------------------------------------------
 *
 * Returns TRUE  if the number of buckets of <table> can change  after <table>
 * has been instatiated,  returns FALSE otherwise. *)

PROCEDURE isResizable ( table : @@module@@ ) : BOOLEAN;


(* ---------------------------------------------------------------------------
 * function:  @@module@@.dispose( table )
 * ---------------------------------------------------------------------------
 *
 * Disposes of table object <table> and returns NIL. *)

PROCEDURE dispose ( table : @@module@@ ) : @@module@@;


END @@module@@.