diff gsm-fw/g23m-aci/aci/db.c @ 775:eedbf248bac0

gsm-fw/g23m-aci subtree: initial import from LoCosto source
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Sun, 12 Oct 2014 01:45:14 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gsm-fw/g23m-aci/aci/db.c	Sun Oct 12 01:45:14 2014 +0000
@@ -0,0 +1,4841 @@
+/* 
++----------------------------------------------------------------------------- 
+|  Project :  PHB
+|  Modul   :  DBM
++----------------------------------------------------------------------------- 
+|  Copyright 2005 Texas Instruments Berlin, AG 
+|                 All rights reserved. 
+| 
+|                 This file is confidential and a trade secret of Texas 
+|                 Instruments Berlin, AG 
+|                 The receipt of or possession of this file does not convey 
+|                 any rights to reproduce or disclose its contents or to 
+|                 manufacture, use, or sell anything it may describe, in 
+|                 whole, or in part, without the specific written consent of 
+|                 Texas Instruments Berlin, AG. 
++----------------------------------------------------------------------------- 
+|  Purpose :  Implementation of DBM functions
++----------------------------------------------------------------------------- 
+*/ 
+
+#ifdef TI_PS_FFS_PHB
+
+#include "db_int.h"
+#include <string.h>
+
+#ifdef _SIMULATION_
+int sprintf (char *, const char *, ...); /* Use appropriate include ... */
+#endif
+
+/* For DB Testing */
+
+/* Check if we are closing FFS files properly */
+/* Implements measure 54 */
+
+/* A simple check to make sure that all allocated 
+   memory is freed to avoid memory leak */
+// #define DB_MEMORY_CHECK
+
+/**************************
+  D E F I N I T I O N S & 
+  D E C L A R A T I O N S
+ **************************/
+
+#define INVALID_FD      (-1)
+#define IS_FD_VALID(fd) ((fd) >= 0)
+
+GLOBAL UBYTE              UsedDBs;								          /* Number of existing databases  */
+GLOBAL int                LastFFS_ReturnCode;			          /* Last FFS return code          */
+GLOBAL T_DBM_MASTERRECORD DbmMaster [MAX_DBs];              /* Database Master               */
+GLOBAL T_DBM_STATE        DBM_State = DBM_NOT_INITIALISED;  /* DBM State                     */
+GLOBAL T_DB_CHANGED       DB_History_log;                   /* History log                   */
+/* Implements Measure#32: Row 1167, 1171, 1189 & 1200 */
+LOCAL const char * const format_sUDd_str="%s/UD_%04X";
+/* Implements Measure#32: Row 1170, 1177 & 1193 */
+LOCAL const char * const format_sUDd_sortd_str="%s/UD_%04X_sort_%d";
+/* Implements Measure#32: Row 1178, 1182, 1186, 1190, 1195, 1198 & 1202 */
+LOCAL const char * const format_sDDd_str="%s/DD_%d";
+
+#ifdef FFS_CLOSE_BEFORE_OPEN
+
+  T_FFS_FD Dummy_FFSFileHandle = INVALID_FD;
+  #define INVALID_FLD_CTR  0xFF
+  #define NOT_OPENED       0x00
+  #define OPENED_FOR_READ  0x01
+  #define OPENED_FOR_WRITE 0x02
+
+#endif
+
+#ifdef DB_TEST
+
+  S8 db_test_ffs_open_ctr = 0; 
+  T_FFS_SIZE db_test_ffs_ret_code = EFFS_OK;
+
+  #define DB_FFS_OPEN( ret, file, flag ) \
+  { \
+    ret = ffs_open( file, flag ); \
+    \
+    if( ret >= EFFS_OK ) \
+    { \
+      ++db_test_ffs_open_ctr; \
+      TRACE_EVENT_P1( "DB_FFS_OPEN:db_test_ffs_open_ctr:%d", db_test_ffs_open_ctr ); \
+    } else { \
+      TRACE_EVENT_P1( "DB_FFS_OPEN:FFS ERROR:%d", ret ); \
+    } \
+  }
+
+
+  #define DB_FFS_CLOSE( fd ) \
+  { \
+    T_FFS_SIZE db_test_ffs_ret_code = ffs_close( fd ); \
+    \
+    if( db_test_ffs_ret_code >= EFFS_OK ) \
+    { \
+      --db_test_ffs_open_ctr; \
+      TRACE_EVENT_P1( "DB_FFS_CLOSE:db_test_ffs_open_ctr:%d", db_test_ffs_open_ctr ); \
+    } else { \
+      TRACE_EVENT_P1( "DB_FFS_CLOSE:FFS ERROR:%d", db_test_ffs_ret_code ); \
+    } \
+    \
+    fd = INVALID_FD; \
+  }
+
+  #define DB_RETURN( ret ) \
+  { \
+    TRACE_EVENT_P1( "DB_RETURN:ret:%d", ret ); \
+    return ret; \
+  }
+ 
+  #define DB_VALUE_RETURN( ret ) \
+  { \
+    TRACE_EVENT_P1( "DB_VALUE_RETURN:ret:%d", ret ); \
+    return ret; \
+  }
+ 
+#else
+
+  #define DB_FFS_OPEN( ret, file, flag ) { ret = ffs_open( file, flag ); }
+  #define DB_FFS_CLOSE( fd ) { ffs_close( fd ); fd = INVALID_FD; }
+  #define DB_RETURN( ret ) return ret;
+  #define DB_VALUE_RETURN( ret ) return ret;
+
+#endif
+
+#ifdef DB_MEMORY_CHECK
+
+  LOCAL UBYTE alloc_ctr = 0;
+
+  LOCAL void db_mfree (void *ptr)
+  {
+    if (ptr NEQ NULL) 
+    {
+      --alloc_ctr;
+      TRACE_EVENT_P1( "DB Memory Free:%d", alloc_ctr );
+      ACI_MFREE( ptr );
+    }
+    else
+    {
+      TRACE_ERROR ("Attempted to free NULL");
+    }
+  }
+
+  LOCAL void *db_malloc (ULONG num_of_bytes)
+  {
+    void *ptr;
+    
+    ++alloc_ctr;
+    TRACE_EVENT_P1( "DB Memory Alloc:%d", alloc_ctr );
+    ACI_MALLOC( ptr, num_of_bytes );
+    return ptr;
+  }
+
+  #define DB_MALLOC( ptr, size )  { ptr = db_malloc ( size ); }
+  #define DB_MFREE( ptr )         { db_mfree ( ptr ); }
+
+
+#else
+
+  #define DB_MALLOC( ptr, num_of_bytes ) ACI_MALLOC( ptr, num_of_bytes )
+  #define DB_MFREE( ptr ) ACI_MFREE( ptr ) 
+
+#endif
+
+
+#ifdef _SIMULATION_
+  #define DB_DIR "/dbm"
+  #define DB_MASTER_FILE "/dbm/DD_master"
+#else
+  #define DB_DIR "/gsm/dbm" 
+  #define DB_MASTER_FILE "/gsm/dbm/DD_master"
+#endif
+
+/* Implements Measure#32: Row 1179, 1184, 1191, 1196, 1199 & 1203 */
+LOCAL const char * const db_dir=DB_DIR;
+/* Implements Measure#32: Row 1181, 1188 & 1201 */
+LOCAL  char * const db_master_file=DB_MASTER_FILE;
+
+#define FILENAME_LEN 40
+
+#define T_DB_MASTER_RECORD_SIZE 18        
+/* DBM master record
+   File: DB_DIR/DD_master
+   Data: 
+      1)	DBDirectory (16 bytes, based on MAX_LEN_DIRECTORY=16)
+      2)	NumOfFiles (1 byte, based on MAX_NUM_FILES=255)
+      3) Clean (1 byte)
+ */
+
+
+#define T_DB_FIELD_RECORD_SIZE 43         
+/* Based on the following data written into FFS 
+   File: DB_DIR/DD_<DBDirectory>
+   Data: 
+    1)	FieldID (2 bytes, given in Interface)
+    2)	DBType (1 byte)
+    3)	RecordSize (2 bytes, based on MAX_RECORD_SIZE=65kb)
+    4)	NumOfRecords (1 byte, based on MAX_NUM_RECORDS=255)
+    5) SortIndexes (MAX_NUM_OF_SORT_INDEXS bytes, 1 byte for each index)
+    6)	RecordBitMap (32 bytes, as of now based on MAX_NUM_RECORDS=255)
+    7) Clean (1 byte)
+ */
+
+#define RecordBitMap_OFFSET 10  /* depending on structure in DB_DIR/DD_<DBDirectory> */
+
+#define SortIndexList_OFFSET 6  /* depending on structure in DB_DIR/DD_<DBDirectory> */
+
+#define SEARCH_FAILED -1
+
+/* For FFS strctures */
+#define FFS_CLEAN       0x01
+#define FFS_DIRTY       0x00
+
+#define FFS_TRACKED 0x01
+#define FFS_NOT_TRACKED 0x00
+
+#define NOT !
+
+#define INVALID_RECORD_NUM 0xFF
+
+/*
+    Internal function to initialize RAM structures with FFS
+ */
+LOCAL T_DB_CODE init_RAM_with_FFS ( void );
+
+#define	DBM_State_check \
+  if ( DBM_State EQ DBM_NOT_INITIALISED ) DB_RETURN( DB_NOT_INITIALISED );
+
+LOCAL T_DB_CODE db_handle_check ( int db_handle );
+
+LOCAL UBYTE field_id_search ( int db_handle, 
+                              USHORT field_id );
+
+LOCAL T_DB_CODE update_history_log ( int    db_handle,
+                                     USHORT field_id,
+                                     USHORT record_num );
+
+LOCAL void db_set_bit_in_bitmap (UBYTE *bitmap, 
+                                 USHORT position,
+                                 BOOL value);
+
+LOCAL UBYTE db_search_bit_in_bitmap (UBYTE* bitmap,
+                                     USHORT max_record,
+                                     BOOL value);
+
+LOCAL T_DB_CODE populate_sorted_list_from_FFS ( 
+
+#ifdef FFS_CLOSE_BEFORE_OPEN
+                                                UBYTE db_ctr,
+#endif
+                                                char*   sort_file,
+                                                UBYTE   num_of_elements,
+                                                UBYTE** sort_list_ptr );
+
+LOCAL T_DB_CODE write_sorted_list_to_FFS ( 
+                                     
+#ifdef FFS_CLOSE_BEFORE_OPEN
+                                          UBYTE db_ctr,
+#endif
+                                          char*   sort_file,
+                                          UBYTE   num_of_elements,
+                                          UBYTE*  sort_list );
+
+LOCAL int db_binary_search ( UBYTE*            sort_list,
+                             UBYTE             num_of_elements,
+                             SHORT*            order_num,
+                             T_SEARCH_FUNC     search_function, 
+                             ULONG             flags, 
+                             const UBYTE*      search_tag,
+                             int               db_handle,
+                             USHORT            field_id );
+
+LOCAL T_DB_CODE update_field_data_in_FFS ( T_FFS_FD*   filehandle,
+                                           UBYTE       db_handle,
+                                           UBYTE       fld_ctr,
+                                           UBYTE*      field_data,
+                                           USHORT      offset,
+                                           USHORT      length );
+
+LOCAL UBYTE cal_NextRecordNum ( const char* DBDirectory,
+                                USHORT      FieldID,
+                                USHORT      RecordSize );
+
+
+LOCAL T_DB_CODE read_write_user_record_from_FFS ( const char      *user_field_file,
+
+#ifdef FFS_CLOSE_BEFORE_OPEN
+                                            UBYTE       db_ctr,
+                                            UBYTE       fld_ctr,
+#endif
+                                                  T_FFS_FD        *filehandle,
+                                            UBYTE       record_num,
+                                            USHORT      record_size,
+                                            USHORT      offset,
+                                            USHORT      length,
+                                                  UBYTE           *record_buffer,
+                                                  T_FFS_OPEN_FLAGS open_option);
+
+LOCAL T_DB_CODE check_ffs_ret_code (T_FFS_SIZE ffs_ret_code,
+                                    T_FFS_FD  *filehandle,
+                                    T_FFS_FD   ffs_fd,
+                                    BOOL       check_invalid);
+
+
+LOCAL T_DB_CODE delete_file_dir_from_FFS ( const char* filename );
+
+LOCAL T_DB_CODE update_dbm_data_in_FFS ( const char* filename,
+                                         UBYTE       db_ctr,
+                                         UBYTE       db_data_max_size,
+                                         UBYTE*      db_data,
+                                         USHORT      offset,
+                                         USHORT      length );
+
+LOCAL T_DB_CODE remove_field_from_FFS ( UBYTE db_ctr,
+                                        UBYTE fld_ctr );
+
+
+#ifdef FFS_CLOSE_BEFORE_OPEN
+
+LOCAL T_FFS_FD db_open_user_field_file ( UBYTE            db_ctr, 
+                                         UBYTE            fld_ctr, 
+                                         const char*      user_field_file,
+                                         T_FFS_OPEN_FLAGS open_option );
+
+
+LOCAL void db_close_user_field_files ( UBYTE db_ctr );
+
+LOCAL BOOL db_open_full_for_read ( UBYTE db_ctr );
+
+LOCAL BOOL db_open_full_for_write ( UBYTE db_ctr );
+
+LOCAL void db_close_for_write ( UBYTE db_ctr );
+
+LOCAL void db_close_for_read ( UBYTE db_ctr );
+
+LOCAL UBYTE db_status_user_field_file ( UBYTE db_ctr,
+                                        UBYTE fld_ctr );
+
+
+#endif /* FFS_CLOSE_BEFORE_OPEN */
+
+LOCAL T_DB_CODE delete_dir_forced ( const char* filename );
+
+LOCAL void get_sort_lists_from_FFS ( UBYTE db_ctr,
+                                     UBYTE fld_ctr );
+
+LOCAL void new_in_sort_lists ( UBYTE db_ctr,
+                               UBYTE fld_ctr,
+                               UBYTE record_num );
+
+LOCAL void update_in_sort_lists ( UBYTE db_ctr,
+                                  UBYTE fld_ctr,
+                                  UBYTE record_num );
+
+LOCAL void delete_in_sort_lists ( UBYTE db_ctr,
+                                  UBYTE fld_ctr,
+                                  UBYTE record_num );
+
+LOCAL void insertion_sort ( UBYTE*        sort_list,
+                            UBYTE         num_of_elements,
+                            T_COMP_FUNC   compare_function, 
+                            ULONG         flags,
+                            int           db_handle,
+                            USHORT        field_id ); 
+
+LOCAL void insert_element ( UBYTE*        sort_list,
+                            UBYTE         num_of_elements,
+                            UBYTE         bottom,
+                            UBYTE         top,
+                            UBYTE         record_num,
+                            T_COMP_FUNC   compare_function, 
+                            ULONG         flags,
+                            int           db_handle,
+                            USHORT        field_id );
+
+LOCAL T_DB_CODE internal_db_sort ( int          db_handle, 
+                                   USHORT       field_id, 
+                                   UBYTE        sort_index, 
+                                   T_COMP_FUNC  compare_function, 
+                                   ULONG        flags );
+
+LOCAL void db_close_for_read_write ( FileHandleRecord  *tmp_open_fields,
+                                     UBYTE             *tmp_old,
+                                     UBYTE              max_per_db);
+
+
+
+
+/******************************
+  I M P L E M E N T A T I O N 
+ ******************************/
+
+/**********************/
+/* INTERNAL FUNCTIONS */
+/**********************/
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: db_handle_check      |
++--------------------------------------------------------------------+
+
+    PURPOSE : DB Handle checks
+*/
+
+LOCAL T_DB_CODE db_handle_check ( int db_handle )
+{
+  /* Check for db_handle range */
+  if( db_handle >= MAX_DBs )
+    return DB_INVALID_DB;
+  
+  /* Check for DBState of db_handle is CLOSED or UNUSED_ENTRY
+     If yes, return DB_INVALID_DB  */
+
+  if( ( DbmMaster[db_handle].DBState EQ CLOSED       ) OR
+      ( DbmMaster[db_handle].DBState EQ UNUSED_ENTRY ) )
+    return DB_INVALID_DB;
+  
+  return DB_OK;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: field_id_search      |
++--------------------------------------------------------------------+
+
+    PURPOSE : checks for the existence of field id in RAM
+*/
+LOCAL UBYTE field_id_search ( int     db_handle, 
+                              USHORT  field_id )
+{
+  UBYTE  fld_ctr;
+  
+  for( fld_ctr = 0; fld_ctr < DbmMaster[db_handle].NumOfFiles; ++fld_ctr )
+  {
+    if( DbmMaster[db_handle].ptrFieldRecord[fld_ctr].FieldID EQ field_id )
+    {
+      return fld_ctr;
+    }
+  }
+  return fld_ctr;
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: update_history_log   |
++--------------------------------------------------------------------+
+
+    PURPOSE : Updating history log
+*/
+LOCAL T_DB_CODE update_history_log ( int    db_handle,
+                                     USHORT field_id,
+                                     USHORT record_num )
+{
+  UBYTE i;
+
+  /* Check if database is tracked */
+  if (!DbmMaster[db_handle].Tracked) /* if db is NOT tracked */
+    return DB_OK;
+
+  /* Search history log if the record is present
+     If present, return DB_OK */
+  for( i = 0; i < DB_History_log.entries; ++i )
+  {
+    if( DB_History_log.field_id[i] EQ field_id )
+      if( DB_History_log.record[i] EQ record_num )
+        return DB_OK;
+  }
+
+  /* If the number of existing logs in history is reached limit, DB_MAX_AFFECTED, 
+     return error "DB_HISTORY_FULL". */
+  if( DB_History_log.entries EQ DB_MAX_AFFECTED )
+    return DB_HISTORY_FULL;
+
+  /* Add new entry */
+  DB_History_log.field_id [DB_History_log.entries] = field_id;
+  DB_History_log.record [DB_History_log.entries] = record_num;
+  ++DB_History_log.entries;
+
+  return DB_OK;
+
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: db_get_bit_in_bitmap |
++--------------------------------------------------------------------+
+
+    PURPOSE : Gets a bit in record bitmap
+*/
+LOCAL BOOL db_get_bit_in_bitmap (const UBYTE *bitmap, USHORT position)
+{
+  USHORT offset;
+  UBYTE mask;
+
+  position--; /* We count from 1 */
+  offset = position >> 3;
+  mask = 0x80 >> (position & 0x7);
+  return ((bitmap[offset] & mask) NEQ 0);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: set_bit_in_bitmap    |
++--------------------------------------------------------------------+
+
+    PURPOSE : Sets a bit in record bitmap
+*/
+LOCAL void db_set_bit_in_bitmap (UBYTE *bitmap, USHORT position, BOOL value)
+{
+  USHORT offset;
+  UBYTE mask;
+
+  //TISH modified for MSIM
+  if (position==0) return;
+  
+  position--; /* We count from 1 */
+  offset = position >> 3;
+  mask = 0x80 >> (position & 0x7);
+  if (value)
+    bitmap[offset] |= mask;
+  else
+    bitmap[offset] &= ~mask;
+}
+
+/*
++----------------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                          |
+|                                       ROUINE: db_search_bit_in_bitmap      |
++----------------------------------------------------------------------------+
+
+    PURPOSE : Searches for the bit not set in record bitmap which 
+              indicates free record 
+*/
+LOCAL UBYTE db_search_bit_in_bitmap (UBYTE* bitmap, USHORT max_record, BOOL value)
+{
+  UBYTE i;
+
+  for (i = 1; i <= max_record; i++)
+  {
+    if (db_get_bit_in_bitmap (bitmap, i) EQ value)
+      return i;
+  }
+  return 0; /* Not found */
+}
+
+/*
++----------------------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                                |
+|                                       ROUINE: populate_sorted_list_from_FFS      |
++----------------------------------------------------------------------------------+
+
+    PURPOSE : Reads the sorted list from FFS
+*/
+LOCAL T_DB_CODE populate_sorted_list_from_FFS ( 
+
+#ifdef FFS_CLOSE_BEFORE_OPEN
+                                                UBYTE db_ctr,
+#endif
+                                                char*   sort_file,
+                                                UBYTE   num_of_elements,
+                                                UBYTE** sort_list_ptr )
+{
+  T_FFS_FD   ffs_fd_sort_file;
+  T_FFS_SIZE ffs_ret_code;
+  UBYTE*     sort_list;
+
+#ifdef FFS_CLOSE_BEFORE_OPEN
+  /* READ */
+  if( db_open_full_for_read( db_ctr ) )
+  {
+     db_close_for_read( db_ctr );  
+  }
+#endif
+
+  DB_FFS_OPEN( ffs_fd_sort_file, sort_file, FFS_O_RDONLY );
+
+  if( (ffs_fd_sort_file EQ EFFS_NAMETOOLONG ) OR
+      (ffs_fd_sort_file EQ EFFS_BADNAME     ) OR
+      (ffs_fd_sort_file EQ EFFS_NOTFOUND    ) OR
+      (ffs_fd_sort_file EQ EFFS_INVALID     ) OR
+      (ffs_fd_sort_file EQ EFFS_LOCKED      ) )
+
+  {
+	  TRACE_EVENT_P1( "populate_sorted_list_from_FFS:DB_FFS_OPEN %d", ffs_fd_sort_file );
+    return DB_FAIL;
+  }
+
+  if( ffs_fd_sort_file < EFFS_OK )
+  {
+    LastFFS_ReturnCode = ffs_fd_sort_file;
+	  TRACE_EVENT_P1( "populate_sorted_list_from_FFS:DB_FFS_OPEN %d", ffs_fd_sort_file );
+    return DB_FAIL_FS;
+  }
+
+  /* This seek is not required as file pointer will be at start of file,
+     but ffs guide doesn't say so ! This needs to be clarified and 
+     accordingly all ffs_seek at start of file after opening the file
+     can be removed ! */
+  ffs_ret_code = ffs_seek( ffs_fd_sort_file, 0, FFS_SEEK_SET );
+
+  if( ( ffs_ret_code EQ EFFS_BADFD )   OR
+      ( ffs_ret_code EQ EFFS_INVALID ) OR
+      ( ffs_ret_code EQ EFFS_BADOP )   )
+  {
+    DB_FFS_CLOSE( ffs_fd_sort_file );
+	  TRACE_EVENT_P1( "populate_sorted_list_from_FFS:ffs_seek %d", ffs_ret_code );
+    return DB_FAIL;
+  }
+
+  DB_MALLOC( sort_list, num_of_elements + 1 );
+  memset( sort_list, INVALID_RECORD_NUM, num_of_elements + 1 );
+
+  ffs_ret_code = ffs_read( ffs_fd_sort_file, 
+                           sort_list, 
+                           num_of_elements );
+
+  if( (ffs_ret_code EQ EFFS_BADFD ) OR
+      (ffs_ret_code EQ EFFS_BADOP ) )
+  {
+    DB_MFREE( sort_list );
+    DB_FFS_CLOSE( ffs_fd_sort_file );
+	  TRACE_EVENT_P1( "populate_sorted_list_from_FFS:ffs_read %d", ffs_ret_code );
+    return DB_FAIL;
+  }
+
+  if( ffs_ret_code < EFFS_OK )
+  {
+    LastFFS_ReturnCode = ffs_fd_sort_file;
+    DB_MFREE( sort_list );
+	  TRACE_EVENT_P1( "populate_sorted_list_from_FFS:ffs_read %d", ffs_ret_code );
+    DB_FFS_CLOSE( ffs_fd_sort_file );
+    return DB_FAIL_FS;
+  }
+
+  DB_FFS_CLOSE( ffs_fd_sort_file );
+
+  /* to avoid memory leak */
+  if( *sort_list_ptr NEQ NULL )
+    DB_MFREE( *sort_list_ptr );
+
+  *sort_list_ptr = sort_list;
+
+  return DB_OK;
+}
+
+/*
++-----------------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                           |  
+|                                       ROUINE: write_sorted_list_to_FFS      |
++-----------------------------------------------------------------------------+
+
+    PURPOSE : Writes the sorted list into FFS
+*/
+LOCAL T_DB_CODE write_sorted_list_to_FFS ( 
+                                     
+#ifdef FFS_CLOSE_BEFORE_OPEN
+                                           UBYTE db_ctr,
+#endif
+                                           char*   sort_file,
+                                           UBYTE   num_of_elements,
+                                           UBYTE*  sort_list )
+{
+  T_FFS_FD   ffs_fd_sort_file;
+  T_FFS_SIZE ffs_ret_code;
+
+#ifdef FFS_CLOSE_BEFORE_OPEN
+  /* WRITE */
+  if( db_open_full_for_write( db_ctr ) )
+  {
+     db_close_for_write( db_ctr );  
+  }
+#endif
+
+  /* FFS_O_TRUNC => If file already exists and it is opened for writing, its 
+                    length is truncated to zero. */
+                    
+  DB_FFS_OPEN( ffs_fd_sort_file, sort_file, FFS_O_CREATE | FFS_O_WRONLY | FFS_O_TRUNC );
+
+  if( (ffs_fd_sort_file EQ EFFS_NAMETOOLONG ) OR
+      (ffs_fd_sort_file EQ EFFS_BADNAME     ) )
+  {
+	  TRACE_EVENT_P1( "write_sorted_list_to_FFS:DB_FFS_OPEN %d", ffs_fd_sort_file );
+    return DB_FAIL;
+  }
+
+  if( ffs_fd_sort_file < EFFS_OK )
+  {
+	  TRACE_EVENT_P1( "write_sorted_list_to_FFS:DB_FFS_OPEN %d", ffs_fd_sort_file );
+    LastFFS_ReturnCode = ffs_fd_sort_file;
+    return DB_FAIL_FS;
+  }
+
+
+  ffs_ret_code = ffs_seek( ffs_fd_sort_file, 0, FFS_SEEK_SET );
+
+  if( ( ffs_ret_code EQ EFFS_BADFD )   OR
+      ( ffs_ret_code EQ EFFS_INVALID ) OR
+      ( ffs_ret_code EQ EFFS_BADOP )   )
+  {
+	  TRACE_EVENT_P1( "write_sorted_list_to_FFS:ffs_seek %d", ffs_ret_code );
+    DB_FFS_CLOSE( ffs_fd_sort_file );
+    return DB_FAIL;
+  }
+
+  ffs_ret_code = ffs_write( ffs_fd_sort_file, 
+                            sort_list, 
+                            num_of_elements );
+   
+  if( ( ffs_ret_code EQ EFFS_BADFD ) OR
+      ( ffs_ret_code EQ EFFS_BADOP ) )
+  {
+    DB_FFS_CLOSE( ffs_fd_sort_file );
+    ffs_ret_code = ffs_remove( sort_file );
+	  TRACE_EVENT_P1( "write_sorted_list_to_FFS:ffs_write %d", ffs_ret_code );
+    return DB_FAIL;
+  }
+
+  if( ffs_ret_code < EFFS_OK )
+  {
+    LastFFS_ReturnCode = ffs_ret_code;
+    DB_FFS_CLOSE( ffs_fd_sort_file );
+    ffs_ret_code = ffs_remove( sort_file );
+	  TRACE_EVENT_P1( "write_sorted_list_to_FFS:ffs_write %d", ffs_ret_code );
+    return DB_FAIL_FS;
+  }
+
+  DB_FFS_CLOSE( ffs_fd_sort_file ); /* yeah, we close it here ! */
+
+  return DB_OK;
+
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: db_binary_search     |
++--------------------------------------------------------------------+
+
+    PURPOSE : Searches for the record; uses binary search and compare
+              function is passed as a parameter.
+*/
+LOCAL int db_binary_search ( UBYTE*            sort_list,
+                             UBYTE             num_of_elements,
+                             SHORT*            order_num,
+                             T_SEARCH_FUNC     search_function, 
+                             ULONG             flags, 
+                             const UBYTE*      search_tag,
+                             int               db_handle,
+                             USHORT            field_id ) 
+{
+  UINT32 left, right;
+  UINT32 mid;
+  int cmp_res;
+  BOOL matched;
+
+  TRACE_FUNCTION ("db_binary_search()");
+
+  left = *order_num;
+  right = num_of_elements;
+
+  if (left >= right)
+    return SEARCH_FAILED;
+
+  /* As often the 1st element is the matching one we try a shortcut. */
+  cmp_res = search_function (flags, 
+                             search_tag, 
+                             db_handle, 
+                             field_id, 
+                             sort_list[left]);
+  if (cmp_res EQ 0)
+  {
+    *order_num = left + 1;
+    return *order_num;
+  }
+  else if (cmp_res > 0)
+    return SEARCH_FAILED; /* We learned already no exact match possible */
+
+  /* Get the first (leftmost) matching element in the sorted list. */
+  matched = FALSE;
+  do
+  {
+    mid = (left + right) >> 1;
+    cmp_res = search_function (flags, 
+                               search_tag, 
+                               db_handle, 
+                               field_id, 
+                               sort_list[mid]);
+
+    if (cmp_res EQ 0)
+      matched = TRUE;
+
+    if (cmp_res < 0)
+      left = mid + 1;
+    else
+      right = mid;
+  }
+  while (left < right);
+
+  if (matched)
+  {
+    *order_num = left + 1;
+    return *order_num;
+  }
+  return SEARCH_FAILED;
+}
+
+
+/*
++-----------------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                           |
+|                                       ROUINE: update_field_data_in_FFS      |
++-----------------------------------------------------------------------------+
+
+    PURPOSE : Updates elementary file data in FFS
+
+    PARAMS:   filehandle: Pointer to file handle, maybe INVALID_FD
+              db_handle: Handle of the particular DB
+              fld_ctr: Number of field (0..n)
+              field_data: (const) Pointer to data to be written
+              offset: offset within the data
+              length: length of data to be written
+
+*/
+LOCAL T_DB_CODE update_field_data_in_FFS ( T_FFS_FD*   filehandle,
+                                           UBYTE       db_handle,
+                                           UBYTE       fld_ctr,
+                                           UBYTE*      field_data,
+                                           USHORT      offset,
+                                           USHORT      length )
+{
+  T_FFS_FD   ffs_fd = *filehandle;
+  T_FFS_SIZE ffs_ret_code;
+  CHAR field_file[FILENAME_LEN];
+
+  /* Updating field data in FFS in file "field_file" */
+/* Implements Measure#32: */
+  sprintf(field_file, format_sDDd_str, db_dir, db_handle);    
+
+  if (!IS_FD_VALID(ffs_fd))
+  {
+    DB_FFS_OPEN( ffs_fd, field_file, FFS_O_WRONLY );
+
+    if( ( ffs_fd EQ EFFS_NOTFOUND )    OR
+        ( ffs_fd EQ EFFS_NAMETOOLONG ) OR
+        ( ffs_fd EQ EFFS_BADNAME )     OR
+        ( ffs_fd EQ EFFS_INVALID )     )
+    {
+	    TRACE_EVENT_P1( "update_field_data_in_FFS:DB_FFS_OPEN %d", ffs_fd );
+      return DB_FAIL;
+    }
+
+    if( ffs_fd < EFFS_OK )
+    {
+      LastFFS_ReturnCode = ffs_fd;
+	    TRACE_EVENT_P1( "update_field_data_in_FFS:DB_FFS_OPEN %d", ffs_fd );
+      return DB_FAIL_FS;
+    }
+
+    *filehandle = ffs_fd;
+
+  } /* filehandle invalid? */
+
+  /* Seek the file to fld_ctr position to update the entry */
+  ffs_ret_code = ffs_seek( ffs_fd, 
+                           ( fld_ctr * T_DB_FIELD_RECORD_SIZE ) + offset, 
+                           FFS_SEEK_SET );
+
+  if( ( ffs_ret_code EQ EFFS_BADFD )   OR
+      ( ffs_ret_code EQ EFFS_INVALID ) OR
+      ( ffs_ret_code EQ EFFS_BADOP )   )
+  {
+    TRACE_EVENT_P1( "update_field_data_in_FFS:ffs_seek %d", ffs_ret_code );
+    DB_FFS_CLOSE( ffs_fd );
+    *filehandle = INVALID_FD;
+    return DB_FAIL;
+  }
+
+  if( ffs_ret_code < EFFS_OK )
+  {
+    TRACE_EVENT_P1( "update_field_data_in_FFS:ffs_seek %d", ffs_ret_code );
+    LastFFS_ReturnCode = ffs_ret_code;
+    DB_FFS_CLOSE( ffs_fd );
+    *filehandle = INVALID_FD;
+    return DB_FAIL_FS;
+  }
+
+  /* clean is reset in memset, so no processing for it 
+     (in case of non-tracked database, anyway we ignore it ! */ 
+
+  ffs_ret_code = ffs_write( ffs_fd, 
+                            field_data, 
+                            length );
+
+  if( (ffs_ret_code EQ EFFS_BADFD ) OR
+      (ffs_ret_code EQ EFFS_BADOP ) )
+  {
+    TRACE_EVENT_P1( "update_field_data_in_FFS:ffs_write %d", ffs_ret_code );
+    DB_FFS_CLOSE( ffs_fd );
+    *filehandle = INVALID_FD;
+    return DB_FAIL;
+  }
+
+  if( ffs_ret_code < EFFS_OK )
+  {
+    TRACE_EVENT_P1( "update_field_data_in_FFS:ffs_write %d", ffs_ret_code );
+    DB_FFS_CLOSE ( ffs_fd );
+    *filehandle = INVALID_FD;
+    LastFFS_ReturnCode = ffs_ret_code;
+    return DB_FAIL_FS;
+  }
+
+  /* DB_FFS_CLOSE( ffs_fd ); we will do it in db_flush */
+  /* updation is over */
+
+#ifdef FFS_OPEN_PROBLEM_PATCH
+  DB_FFS_CLOSE( ffs_fd );
+  *filehandle = INVALID_FD;
+#endif
+
+#ifndef FFS_CLOSE_BEFORE_OPEN
+  /* this is db file, but we do not close it */
+#endif
+
+  return DB_OK;
+
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: cal_NextRecordNum    |
++--------------------------------------------------------------------+
+
+    PURPOSE : Reads the status of the file and returns 
+              the next available record (position)
+*/
+LOCAL UBYTE cal_NextRecordNum ( const char* db_directory,
+                                USHORT      field_id,
+                                USHORT      record_size )
+{
+  char user_field_file[FILENAME_LEN];
+
+  T_FFS_SIZE ffs_ret_code;
+  T_FFS_STAT ffs_file_stat;
+
+/* Implements Measure#32: Row 1167 */
+  sprintf( user_field_file, 
+          format_sUDd_str, 
+          db_directory, 
+          field_id );
+
+  ffs_ret_code = ffs_stat( user_field_file, &ffs_file_stat );
+
+  if( ffs_ret_code EQ EFFS_OK )
+  {
+    return ( (ffs_file_stat.size / record_size) + 1);
+  }
+
+  if( ffs_ret_code EQ EFFS_NOTFOUND )
+  {
+    TRACE_EVENT( "cal_NextRecordNum:ffs_stat:FILE NOT FOUND" );
+    return 1;
+  }
+
+  /* this is a problem with user_field_file, raise an error and 
+     return 0 */
+
+  TRACE_ERROR( "cal_NextRecordNum: PROBLEM with user_field_file" );
+  TRACE_EVENT_P1( "cal_NextRecordNum:ffs_stat %d", ffs_ret_code );
+  return 1;
+
+}
+
+
+/* Implements Measure # 211 */
+
+/*
++-----------------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                           |
+|                                       ROUINE: delete_file_dir_from_FFS      |
++-----------------------------------------------------------------------------+
+
+    PURPOSE : Deletes a file from FFS
+*/
+LOCAL T_DB_CODE delete_file_dir_from_FFS ( const char* filename )
+{
+  T_FFS_SIZE ffs_ret_code;
+
+  TRACE_EVENT_P1( "delete_file_dir_from_FFS %s", filename );
+
+  ffs_ret_code = ffs_remove( filename );
+
+  if( ffs_ret_code EQ EFFS_DIRNOTEMPTY )
+  {
+    TRACE_EVENT( "Inconsistency; going for delete_dir_forced" );
+    return delete_dir_forced( filename ); 
+  }
+
+  if( ffs_ret_code EQ EFFS_NOTFOUND )
+  {
+    TRACE_EVENT( "delete_file_dir_from_FFS:ffs_remove:FILE NOT FOUND" );
+    return DB_OK;
+  }
+
+  if( ( ffs_ret_code EQ EFFS_ACCESS   ) OR
+      ( ffs_ret_code EQ EFFS_LOCKED   ) )
+  {
+    TRACE_EVENT_P1( "delete_file_dir_from_FFS:ffs_remove %d", ffs_ret_code );
+    return DB_FAIL;
+  }
+
+  if( ffs_ret_code < EFFS_OK )
+  {
+    TRACE_EVENT_P1( "delete_file_dir_from_FFS:ffs_remove %d", ffs_ret_code );
+    LastFFS_ReturnCode = ffs_ret_code;
+    return DB_FAIL_FS;
+  }
+
+  return DB_OK;
+
+}
+
+/*
++---------------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                         |
+|                                       ROUINE: update_dbm_data_in_FFS      |
++---------------------------------------------------------------------------+
+
+    PURPOSE : Updates the database manager information of a 
+              particular database
+*/
+LOCAL T_DB_CODE update_dbm_data_in_FFS ( const char* filename,
+                                         UBYTE       db_ctr,
+                                         UBYTE       db_data_max_size,
+                                         UBYTE*      db_data,
+                                         USHORT      offset,
+                                         USHORT      length )
+{
+  T_FFS_FD   ffs_fd = INVALID_FD;
+  T_FFS_SIZE ffs_ret_code;
+
+  /* See if file already opened, 
+     if not open it and update the file handle */
+
+#ifdef FFS_CLOSE_BEFORE_OPEN
+  /* WRITE */
+  if( db_open_full_for_write( db_ctr ) )
+  {
+     db_close_for_write( db_ctr );  
+  }
+#endif
+
+  DB_FFS_OPEN( ffs_fd, filename, FFS_O_WRONLY );
+
+  if( ( ffs_fd EQ EFFS_NAMETOOLONG ) OR
+      ( ffs_fd EQ EFFS_BADNAME )     OR
+      ( ffs_fd EQ EFFS_NOTFOUND )    OR
+      ( ffs_fd EQ EFFS_INVALID )     OR
+      ( ffs_fd EQ EFFS_LOCKED )      )
+  {
+    TRACE_EVENT_P1( "update_dbm_data_in_FFS:DB_FFS_OPEN %d", ffs_fd );
+     return DB_FAIL;
+  }
+
+  if( ffs_fd < EFFS_OK )
+  {
+    TRACE_EVENT_P1( "update_dbm_data_in_FFS:DB_FFS_OPEN %d", ffs_fd );
+    LastFFS_ReturnCode = ffs_fd;
+    return DB_FAIL_FS;
+  }
+
+  ffs_ret_code = ffs_seek( ffs_fd, db_ctr * db_data_max_size, FFS_SEEK_SET );
+
+  if( ( ffs_ret_code EQ EFFS_BADFD )   OR
+      ( ffs_ret_code EQ EFFS_INVALID ) OR
+      ( ffs_ret_code EQ EFFS_BADOP )   )
+  {
+    TRACE_EVENT_P1( "update_dbm_data_in_FFS:ffs_seek %d", ffs_ret_code );
+    DB_FFS_CLOSE( ffs_fd );
+    return DB_FAIL;
+  }
+
+  if( ffs_ret_code < EFFS_OK )
+  {
+    TRACE_EVENT_P1( "update_dbm_data_in_FFS:ffs_seek %d", ffs_ret_code );
+    LastFFS_ReturnCode = ffs_ret_code;
+    DB_FFS_CLOSE( ffs_fd );
+    return DB_FAIL_FS;
+  }
+
+  ffs_ret_code = ffs_write( ffs_fd, db_data, db_data_max_size );
+   
+  if( ( ffs_ret_code EQ EFFS_BADFD ) OR
+      ( ffs_ret_code EQ EFFS_BADOP ) )
+  {
+    TRACE_EVENT_P1( "update_dbm_data_in_FFS:ffs_write %d", ffs_ret_code );
+    DB_FFS_CLOSE( ffs_fd );
+    return DB_FAIL;
+  }
+
+  if( ffs_ret_code < EFFS_OK )
+  {
+    TRACE_EVENT_P1( "update_dbm_data_in_FFS:ffs_write %d", ffs_ret_code );
+    DB_FFS_CLOSE( ffs_fd );
+    LastFFS_ReturnCode = ffs_ret_code;
+    return DB_FAIL_FS;
+  }
+
+  DB_FFS_CLOSE( ffs_fd );  /* yeah, DB file, so ok to close it here ! */
+
+  /* updation of dbm data done */
+
+  return DB_OK;
+}
+
+/*
++--------------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                        |
+|                                       ROUINE: remove_field_from_FFS      |
++--------------------------------------------------------------------------+
+
+    PURPOSE : Removes the elementary file and associated Index 
+              file from FFS
+*/
+LOCAL T_DB_CODE remove_field_from_FFS ( UBYTE db_ctr,
+                                        UBYTE fld_ctr )
+{
+  T_DBM_FIELDRECORD* tmp_ptrFieldRecord;
+  char               user_field_file[FILENAME_LEN],
+                     sort_file[FILENAME_LEN];
+  T_DB_CODE          db_ret_code;
+  UBYTE              sort_index_ctr;
+
+  /* Assumed that DBState is not IN_USE */
+
+  tmp_ptrFieldRecord = DbmMaster[db_ctr].ptrFieldRecord + fld_ctr;
+  
+  if( tmp_ptrFieldRecord -> FieldID EQ INVALID_FIELD_ID ) /* if not valid field id */
+    return DB_OK;
+
+  /* Close of user record files not required as DBState is not IN_USE */
+
+  /* Delete file "<DBDirectory>/UD_<field_id>" */
+
+/* Implements Measure#32: Row 1171 */
+  sprintf( user_field_file, 
+           format_sUDd_str, 
+           (char *)DbmMaster[db_ctr].DBDirectory, 
+           tmp_ptrFieldRecord -> FieldID );
+
+  db_ret_code = delete_file_dir_from_FFS ( user_field_file );
+
+  if( db_ret_code NEQ DB_OK )
+    return db_ret_code;
+
+  /* For sorted lists */
+
+  for( sort_index_ctr = 0; sort_index_ctr < MAX_NUM_OF_SORT_INDEXS; ++sort_index_ctr )
+  {
+   
+    /* Delete the SortedLists from memory */
+    if (tmp_ptrFieldRecord->SortedLists[sort_index_ctr] NEQ NULL)
+    {
+      DB_MFREE (tmp_ptrFieldRecord->SortedLists[sort_index_ctr]);
+      tmp_ptrFieldRecord->SortedLists[sort_index_ctr] = NULL;
+    }
+
+    /* Delete the SortedLists from the FFS */
+    if( tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] NEQ INVALID_SORT_INDEX )
+    {
+      /* Sort file, "<DBDirectory>/UD_<field_id>_sort_<sort_index>" */
+
+/* Implements Measure#32: Row 1170 */
+      sprintf( sort_file, 
+               format_sUDd_sortd_str, 
+               (char *)DbmMaster[db_ctr].DBDirectory, 
+               tmp_ptrFieldRecord -> FieldID,
+               tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] );
+
+      db_ret_code = delete_file_dir_from_FFS ( sort_file );
+
+      if( db_ret_code NEQ DB_OK )
+        return db_ret_code;        
+    }
+  }
+
+  return DB_OK;
+
+}
+
+
+
+#ifdef FFS_CLOSE_BEFORE_OPEN
+
+LOCAL T_FFS_FD db_open_user_field_file ( UBYTE            db_ctr, 
+                                         UBYTE            fld_ctr, 
+                                         const char*      user_field_file,
+                                         T_FFS_OPEN_FLAGS open_option )
+{
+  UBYTE i;
+  FileHandleRecord* tmp_open_fields;
+  UBYTE*            tmp_old;
+  UBYTE             tmp_max;
+
+  /* sanity checks not done (db_ctr >= MAX_DBs OR fld_ctr EQ INVALID_FLD_CTR) */
+
+  /* note that we store field counters and not field ids */
+
+  /* Search in write/read list */
+  for( i = 0; i < MAX_OPEN_WRITE_PER_DB; ++i )
+  {
+    if( DbmMaster[db_ctr].WRITE_OPEN_FIELDS[i].fld_ctr EQ fld_ctr )
+      return DbmMaster[db_ctr].WRITE_OPEN_FIELDS[i].filehandle;
+  } /* for */
+
+  /* Search in read only list */
+  for( i = 0; i < MAX_OPEN_READ_PER_DB; ++i )
+  {
+    if( DbmMaster[db_ctr].READ_OPEN_FIELDS[i].fld_ctr EQ fld_ctr )
+    {
+      if( NOT ( open_option & FFS_O_WRONLY ) ) /* if not opened for writing */
+      {
+        return DbmMaster[db_ctr].READ_OPEN_FIELDS[i].filehandle;
+      }
+
+      /* we need to reopen it in write mode */
+      DB_FFS_CLOSE( DbmMaster[db_ctr].READ_OPEN_FIELDS[i].filehandle );
+      DbmMaster[db_ctr].READ_OPEN_FIELDS[i].filehandle = INVALID_FD;
+      DbmMaster[db_ctr].READ_OPEN_FIELDS[i].fld_ctr = INVALID_FLD_CTR;
+      break;
+      
+    }
+  } /* for */
+
+  /* field is not present in both lists */
+
+  if( open_option & FFS_O_WRONLY )
+  {
+
+    /* for writing and reading both */
+    tmp_open_fields = DbmMaster[db_ctr].WRITE_OPEN_FIELDS;
+    tmp_old = &(DbmMaster[db_ctr].old_write);
+    tmp_max = MAX_OPEN_WRITE_PER_DB;
+
+  } else {
+
+    /* for reading only */
+    tmp_open_fields = DbmMaster[db_ctr].READ_OPEN_FIELDS;
+    tmp_old = &(DbmMaster[db_ctr].old_read);
+    tmp_max = MAX_OPEN_READ_PER_DB;
+  }
+
+
+  /* search the list */
+  for( i = 0; i < tmp_max; ++i )
+  {
+    if( tmp_open_fields[i].fld_ctr EQ INVALID_FLD_CTR )
+    {
+      DB_FFS_OPEN( tmp_open_fields[i].filehandle,
+                   user_field_file,
+                   open_option );
+
+      tmp_open_fields[i].fld_ctr = fld_ctr;
+
+      return tmp_open_fields[i].filehandle;
+    }
+  } /* for */
+
+  /* we need to close the some file for opening this */
+
+  if( *tmp_old >= tmp_max )
+    *tmp_old = 0;
+
+  DB_FFS_CLOSE( tmp_open_fields[*tmp_old].filehandle );
+
+  DB_FFS_OPEN( tmp_open_fields[*tmp_old].filehandle,
+               user_field_file,
+               open_option );
+
+  if( tmp_open_fields[*tmp_old].filehandle >= EFFS_OK )
+  {
+    tmp_open_fields[*tmp_old].fld_ctr = fld_ctr;
+    ++(*tmp_old);
+    return tmp_open_fields[*tmp_old - 1].filehandle;
+  } 
+  
+  tmp_open_fields[*tmp_old].fld_ctr = INVALID_FLD_CTR;
+
+  return tmp_open_fields[*tmp_old].filehandle;
+
+}
+
+LOCAL void db_close_user_field_files ( UBYTE db_ctr )
+{
+  UBYTE i;
+  FileHandleRecord* tmp_open_fields;
+
+  /* sanity check not done */
+
+  /* for write list */
+
+  tmp_open_fields = DbmMaster[db_ctr].WRITE_OPEN_FIELDS;
+
+  for( i = 0; i < MAX_OPEN_WRITE_PER_DB; ++i )
+  {
+    if( tmp_open_fields[i].fld_ctr NEQ INVALID_FLD_CTR )
+    {
+      DB_FFS_CLOSE( tmp_open_fields[i].filehandle );
+      tmp_open_fields[i].filehandle = INVALID_FD;
+      tmp_open_fields[i].fld_ctr = INVALID_FLD_CTR;
+    }
+  }
+
+  /* for read list */
+
+  tmp_open_fields = DbmMaster[db_ctr].READ_OPEN_FIELDS;
+
+  for( i = 0; i < MAX_OPEN_READ_PER_DB; ++i )
+  {
+    if( tmp_open_fields[i].fld_ctr NEQ INVALID_FLD_CTR )
+    {
+      DB_FFS_CLOSE( tmp_open_fields[i].filehandle );
+      tmp_open_fields[i].filehandle = INVALID_FD;
+      tmp_open_fields[i].fld_ctr = INVALID_FLD_CTR;
+    }
+  }
+
+}
+
+LOCAL BOOL db_open_full_for_read ( UBYTE db_ctr )
+{
+  UBYTE i;
+  FileHandleRecord* tmp_open_fields;
+
+  /* sanity check not done */
+
+  /* for read list */
+
+  tmp_open_fields = DbmMaster[db_ctr].READ_OPEN_FIELDS;
+
+  for( i = 0; i < MAX_OPEN_READ_PER_DB; ++i )
+  {
+    if( tmp_open_fields[i].fld_ctr EQ INVALID_FLD_CTR )
+      return FALSE;
+  }
+
+  return TRUE;
+}
+
+LOCAL BOOL db_open_full_for_write ( UBYTE db_ctr )
+{
+  UBYTE i;
+  FileHandleRecord* tmp_open_fields;
+
+  /* sanity check not done */
+
+  /* for write list */
+
+  tmp_open_fields = DbmMaster[db_ctr].WRITE_OPEN_FIELDS;
+
+  for( i = 0; i < MAX_OPEN_WRITE_PER_DB; ++i )
+  {
+    if( tmp_open_fields[i].fld_ctr EQ INVALID_FLD_CTR )
+      return FALSE;
+  }
+
+  return TRUE;
+}
+
+LOCAL void db_close_for_read ( UBYTE db_ctr )
+{
+  /* Implements Measure # 83 */
+  db_close_for_read_write (DbmMaster[db_ctr].READ_OPEN_FIELDS, 
+                         &(DbmMaster[db_ctr].old_read), MAX_OPEN_READ_PER_DB);
+
+  return;
+
+}
+
+LOCAL void db_close_for_write ( UBYTE db_ctr )
+{
+  /* Implements Measure # 83 */
+  db_close_for_read_write (DbmMaster[db_ctr].WRITE_OPEN_FIELDS,
+                         &(DbmMaster[db_ctr].old_write), MAX_OPEN_WRITE_PER_DB);
+
+  return;
+
+}
+
+
+LOCAL UBYTE db_status_user_field_file ( UBYTE db_ctr,
+                                        UBYTE fld_ctr )
+{
+  UBYTE i;
+  FileHandleRecord* tmp_open_fields;
+
+  /* sanity check not done */
+
+  /* for write list */
+
+  tmp_open_fields = DbmMaster[db_ctr].WRITE_OPEN_FIELDS;
+
+  for( i = 0; i < MAX_OPEN_WRITE_PER_DB; ++i )
+  {
+    if( tmp_open_fields[i].fld_ctr EQ fld_ctr )
+      return OPENED_FOR_WRITE;
+  }
+
+  /* for read list */
+
+  tmp_open_fields = DbmMaster[db_ctr].READ_OPEN_FIELDS;
+
+  for( i = 0; i < MAX_OPEN_READ_PER_DB; ++i )
+  {
+    if( tmp_open_fields[i].fld_ctr EQ fld_ctr )
+      return OPENED_FOR_READ;
+  }
+
+  return NOT_OPENED;
+}
+
+
+#endif /* FFS_CLOSE_BEFORE_OPEN */
+
+/*
++-----------------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                           |
+|                                       ROUINE: delete_dir_forced             |
++-----------------------------------------------------------------------------+
+
+    PURPOSE : Removes contents of dir and then delete the dir
+              (it uses recursion)
+*/
+LOCAL T_DB_CODE delete_dir_forced ( const char* dir )
+{
+  T_FFS_SIZE ffs_ret_code;
+  T_FFS_DIR  ffs_dir; /*lint !e813 big var on stack, not true for target */
+  T_FFS_STAT tmp_ffs_stat;
+
+  char  pathname[FILENAME_LEN];
+  UBYTE dir_len;
+
+  /* Open dir, if does not exist, just return DB_OK */
+
+  ffs_ret_code = ffs_opendir (dir, &ffs_dir);
+
+  if( ffs_ret_code EQ EFFS_NOTFOUND )
+    DB_RETURN( DB_OK );
+
+  if( ffs_ret_code < EFFS_OK )
+  {
+    TRACE_EVENT_P2( "delete_dir_forced:ffs_remove %d, %s", ffs_ret_code, dir );
+    LastFFS_ReturnCode = ffs_ret_code;
+    DB_RETURN( DB_FAIL_FS )
+  }
+
+  /* read dir recursively */
+  sprintf( pathname, 
+           "%s/", 
+           dir );
+
+  dir_len = strlen( pathname );
+
+  while( 1 )
+  {
+    /* filename inside the directory would be copied at pathname + dirlen */
+
+    ffs_ret_code = ffs_readdir( &ffs_dir,
+                                pathname + dir_len,
+                                FILENAME_LEN - dir_len - 1 );
+
+    if( ffs_ret_code EQ 0 ) /* dir is empty now */
+    {
+      break;
+    }
+
+    if( ffs_ret_code < EFFS_OK )
+    {
+      TRACE_EVENT_P2( "delete_dir_forced:ffs_readdir:%d, %s", ffs_ret_code, dir );
+      LastFFS_ReturnCode = ffs_ret_code;
+      DB_RETURN( DB_FAIL_FS )
+    }
+
+    ffs_ret_code = ffs_stat( pathname, &tmp_ffs_stat );
+
+    if( ffs_ret_code < EFFS_OK )
+    {
+      TRACE_EVENT_P2( "delete_dir_forced:ffs_stat:%d, %s", ffs_ret_code, pathname);
+      LastFFS_ReturnCode = ffs_ret_code;
+      DB_RETURN( DB_FAIL_FS )
+    }
+
+    if( tmp_ffs_stat.type EQ OT_DIR )
+    {
+      /* Directory !! */
+
+      T_DB_CODE db_code;
+
+      TRACE_EVENT_P1( "Warning: directory %s", pathname );
+
+      /* Recursion */
+      db_code = delete_dir_forced( pathname ); 
+
+      if( db_code NEQ DB_OK )
+        DB_RETURN( db_code );
+
+    } else {
+
+      /* normal file (OT_FILE) or symbolic link (OT_LINK) */
+
+      ffs_ret_code = ffs_remove( pathname );
+
+      if( ffs_ret_code < EFFS_OK )
+      {
+        TRACE_EVENT_P2( "delete_dir_forced:ffs_remove:%d, %s", ffs_ret_code, pathname );
+        LastFFS_ReturnCode = ffs_ret_code;
+        DB_RETURN( DB_FAIL_FS )
+      }
+
+    } /* if( tmp_ffs_stat.type EQ OT_DIR ) */
+
+  } /* while( 1 ) */
+
+  /* now delete the directory */
+  ffs_ret_code = ffs_remove( dir );
+
+  if( ffs_ret_code < EFFS_OK )
+  {
+    TRACE_EVENT_P2( "delete_dir_forced:ffs_remove:%d, %s", ffs_ret_code, dir );
+    LastFFS_ReturnCode = ffs_ret_code;
+    DB_RETURN( DB_FAIL_FS )
+  }
+
+  DB_RETURN( DB_OK )
+}
+
+
+LOCAL void get_sort_lists_from_FFS ( UBYTE db_ctr,
+                                     UBYTE fld_ctr )
+{
+  UBYTE sort_index_ctr;
+
+  T_DB_CODE db_ret_code;
+
+  char sort_file[FILENAME_LEN];
+
+  T_DBM_FIELDRECORD* tmp_ptrFieldRecord = DbmMaster[db_ctr].ptrFieldRecord + fld_ctr;
+
+  /* for all existing sort indexes */
+  for( sort_index_ctr = 0; sort_index_ctr < MAX_NUM_OF_SORT_INDEXS; ++sort_index_ctr )
+  {
+    /* valid index ? */
+    if( tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] NEQ INVALID_SORT_INDEX )
+    {
+      /* Check if we already have sorted list in RAM structure SortedLists */
+
+      if( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] EQ NULL )
+      { 
+        /* If no, populate the sorted list from file, 
+           "<DBDirectory>/UD_<field_id>_sort_<sort_index>". 
+           Sorted lists are freed in db_flush */
+
+/* Implements Measure#32: Row 1177 */
+        sprintf( sort_file, 
+                 format_sUDd_sortd_str, 
+                 (char *)DbmMaster[db_ctr].DBDirectory, 
+                 tmp_ptrFieldRecord -> FieldID,
+                 tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] );
+
+        db_ret_code = 
+          populate_sorted_list_from_FFS (  
+#ifdef FFS_CLOSE_BEFORE_OPEN
+                                          db_ctr,
+#endif
+                                          sort_file,
+                                          tmp_ptrFieldRecord -> NumOfRecords,
+                                          &(tmp_ptrFieldRecord -> SortedLists[sort_index_ctr]) );
+        if( db_ret_code NEQ DB_OK )
+        {
+          /* Failure, still we can continue as later during actual sorting, 
+             FFS would be retried */
+
+          TRACE_EVENT( "Warning: populate_sorted_list_from_FFS failed" );
+          TRACE_EVENT_P3( "db_ctr %d field_id %04X sort_index %d",
+                          db_ctr,
+                          tmp_ptrFieldRecord -> FieldID,
+                          tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] );
+
+          continue;
+        }
+    
+      } /* if we have sort list */
+
+    } /* if valid index */
+
+  } /* for all sort indexes */
+
+  return;
+
+}
+
+LOCAL void new_in_sort_lists ( UBYTE db_ctr,
+                               UBYTE fld_ctr,
+                               UBYTE record_num )
+{
+  UBYTE sort_index_ctr;
+
+  T_DBM_FIELDRECORD* tmp_ptrFieldRecord = DbmMaster[db_ctr].ptrFieldRecord + fld_ctr;
+
+  /* make a note that this record needs to be sorted */
+
+  /* for all existing sort indexes */
+  for( sort_index_ctr = 0; sort_index_ctr < MAX_NUM_OF_SORT_INDEXS; ++sort_index_ctr )
+  {
+    if( tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] NEQ INVALID_SORT_INDEX )
+    {
+      /* add it at the end like all sorted records + INVALID RECORD + .... */
+      tmp_ptrFieldRecord -> SortedLists[sort_index_ctr][tmp_ptrFieldRecord -> UsedRecords] 
+        = record_num;
+    }
+  }
+
+  return;
+
+}
+
+LOCAL void update_in_sort_lists ( UBYTE db_ctr,
+                                  UBYTE fld_ctr,
+                                  UBYTE record_num )
+{
+  UBYTE sort_index_ctr,
+        rec_ctr;
+
+  T_DBM_FIELDRECORD* tmp_ptrFieldRecord = DbmMaster[db_ctr].ptrFieldRecord + fld_ctr;
+
+  /* make a note that this record needs to be sorted */
+
+  /* for all existing sort indexes */
+  for( sort_index_ctr = 0; sort_index_ctr < MAX_NUM_OF_SORT_INDEXS; ++sort_index_ctr )
+  {
+    if( tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] NEQ INVALID_SORT_INDEX )
+    {
+      /* search entry in sorted records */
+      rec_ctr = 0;
+      while( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr][rec_ctr] NEQ INVALID_RECORD_NUM )
+      {
+        if( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr][rec_ctr] EQ record_num )
+        {
+          /* found in sorted records, 
+             now delete this entry */
+
+          memmove( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] + rec_ctr,                    /* dest */
+                   (const char*)(tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] + rec_ctr + 1), /* source */
+                   tmp_ptrFieldRecord -> UsedRecords - rec_ctr );                                  /* size */   
+
+          tmp_ptrFieldRecord -> SortedLists[sort_index_ctr][tmp_ptrFieldRecord -> UsedRecords] 
+            = record_num;
+
+          break;
+        }
+
+        ++rec_ctr;
+      }
+
+    } /* NEQ INVALID_SORT_INDEX */
+
+  } /* for sort_index_ctr */
+
+  return;
+}
+
+LOCAL void delete_in_sort_lists ( UBYTE db_ctr,
+                                  UBYTE fld_ctr,
+                                  UBYTE record_num )
+{
+  UBYTE sort_index_ctr,
+        rec_ctr;
+
+  T_DBM_FIELDRECORD* tmp_ptrFieldRecord = DbmMaster[db_ctr].ptrFieldRecord + fld_ctr;
+
+  /* make a note that this record needs to be sorted */
+
+  /* for all existing sort indexes */
+  for( sort_index_ctr = 0; sort_index_ctr < MAX_NUM_OF_SORT_INDEXS; ++sort_index_ctr )
+  {
+    if( tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] NEQ INVALID_SORT_INDEX )
+    {
+      /* search entry in sorted records */
+      rec_ctr = 0;
+      while( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr][rec_ctr] NEQ INVALID_RECORD_NUM )
+      {
+        if( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr][rec_ctr] EQ record_num )
+          break;
+
+        ++rec_ctr;
+      }
+
+      if( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr][rec_ctr] NEQ INVALID_RECORD_NUM )
+      {
+        /* found in sorted records, 
+           now delete this entry */
+
+        memmove( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] + rec_ctr,
+                 (const char*)(tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] + rec_ctr + 1),
+                 tmp_ptrFieldRecord -> UsedRecords - rec_ctr );
+
+        tmp_ptrFieldRecord -> SortedLists[sort_index_ctr][tmp_ptrFieldRecord -> UsedRecords] 
+          = INVALID_RECORD_NUM;
+
+      } else {
+
+        /* search in UN-sorted records */
+
+        ++rec_ctr;
+        while( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr][rec_ctr] NEQ INVALID_RECORD_NUM )
+        {
+          if( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr][rec_ctr] EQ record_num )
+          {
+            /* delete this entry */
+            memmove( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] + rec_ctr,
+                     (const char*)(tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] + rec_ctr + 1),
+                     tmp_ptrFieldRecord -> UsedRecords - rec_ctr );
+
+            tmp_ptrFieldRecord -> SortedLists[sort_index_ctr][tmp_ptrFieldRecord -> UsedRecords] 
+              = INVALID_RECORD_NUM;
+
+            break;
+          }
+          ++rec_ctr;
+        }
+
+      }
+
+    } /* NEQ INVALID_SORT_INDEX */
+
+  } /* for sort_index_ctr */
+
+  return;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: insertion_sort       |
++--------------------------------------------------------------------+
+
+    PURPOSE : Sorts the user data records in FFS based on insertion sort method
+*/
+LOCAL void insertion_sort ( UBYTE*        sort_list,
+                            UBYTE         num_of_elements,
+                            T_COMP_FUNC   compare_function, 
+                            ULONG         flags,
+                            int           db_handle,
+                            USHORT        field_id )
+{
+  UBYTE rec_ctr;
+
+  /* sanity check */
+  if( num_of_elements EQ 0 )
+    return;
+
+  if( sort_list[0] EQ INVALID_RECORD_NUM )
+  {
+    /* This is beginning of new sort list,
+       Let's add first element */
+    sort_list[0] = sort_list[1];
+    sort_list[1] = INVALID_RECORD_NUM;
+  }
+
+
+  /* So now here we have list something like this
+     { Sorted records } + INVALID_RECORD_NUM + { UNsorted records }
+  */
+
+  /* let's get to Unsorted records */
+  rec_ctr = 1;
+  while( sort_list[rec_ctr] NEQ INVALID_RECORD_NUM )
+  {
+    ++rec_ctr;
+  }
+  ++rec_ctr;
+
+  /* rec_ctr is now pointing at UNsorted records */
+
+  /* now add UNsorted records one by one */
+
+  /* Not required "( sort_list[rec_ctr] NEQ INVALID_RECORD_NUM )", right ? */
+
+  while( rec_ctr <= num_of_elements )
+  {
+    insert_element( sort_list,
+                    rec_ctr,                /* num_of_elements */
+                    0,                      /* bottom */
+                    rec_ctr - 2,            /* top */
+                    sort_list[rec_ctr],     /* record_num to be inserted */
+                    compare_function,
+                    flags,
+                    db_handle,
+                    field_id );
+
+    ++rec_ctr;
+  }
+
+  /* done ! */
+  return;
+}
+
+LOCAL void insert_element ( UBYTE*        sort_list,
+                            UBYTE         num_of_elements,
+                            UBYTE         bottom,
+                            UBYTE         top,
+                            UBYTE         record_num,
+                            T_COMP_FUNC   compare_function, 
+                            ULONG         flags,
+                            int           db_handle,
+                            USHORT        field_id )
+{
+  UBYTE middle = ( top + bottom ) / 2;
+
+  /* use binary algorithm to find the right place for insertion */
+  while( middle NEQ bottom )
+  {
+    if( compare_function( db_handle, 
+                          field_id,
+                          sort_list[middle],
+                          record_num,
+                          flags ) 
+        < 0 )
+    {
+      bottom = middle;
+    } else {
+      top = middle;
+    }
+    middle = ( top + bottom ) / 2;
+
+  } /* while( middle NEQ bottom ) */
+
+  if( compare_function( db_handle, 
+                        field_id,
+                        sort_list[bottom],
+                        record_num,
+                        flags ) 
+      < 0 )
+  {
+
+    if( compare_function( db_handle, 
+                          field_id,
+                          sort_list[top],
+                          record_num,
+                          flags ) 
+        < 0 )
+    {
+      /* insert at top + 1 */
+      memmove( sort_list + top + 2,            /* dest */
+               sort_list + top + 1,            /* source */
+               num_of_elements - (top + 1) );  /* size */
+
+      sort_list[top + 1] = record_num;
+
+    } else {
+
+      /* insert at bottom + 1 */
+      memmove( sort_list + bottom + 2,            /* dest */
+               sort_list + bottom + 1,            /* source */
+               num_of_elements - (bottom + 1) );  /* size */
+
+      sort_list[bottom + 1] = record_num;
+
+    } /* if top_th < insert_th */
+
+  } else {
+
+    /* insert at bottom */
+    memmove( sort_list + bottom + 1,       /* dest */
+             sort_list + bottom,           /* source */
+             num_of_elements - bottom );   /* size */
+
+    sort_list[bottom] = record_num;
+
+  } /* if bottom_th < insert_th */
+
+  return;
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: internal_db_sort     |
++--------------------------------------------------------------------+
+
+    PURPOSE : (Internal) Creates or updates a sort index for
+              a given (database, field)
+*/
+LOCAL T_DB_CODE internal_db_sort ( int          db_handle, 
+                                   USHORT       field_id, 
+                                   UBYTE        sort_index, 
+                                   T_COMP_FUNC  compare_function, 
+                                   ULONG        flags )
+{
+  UBYTE  fld_ctr,
+         sort_index_ctr,
+         remb_sort_index_ctr,
+         record_num;
+  UBYTE* sort_list;
+  UBYTE* copy_sort_list;
+  T_DB_CODE  db_ret_code;
+  T_DBM_FIELDRECORD* tmp_ptrFieldRecord;
+  UBYTE* field_data;
+
+  TRACE_FUNCTION("internal_db_sort()");
+
+  /* DBM_State check */
+  DBM_State_check;
+
+  /* db_handle check */
+  db_ret_code = db_handle_check( db_handle );
+  if( db_ret_code NEQ DB_OK )
+    DB_RETURN( db_ret_code );
+
+  /*	field id search; if field not found, return error DB_INVALID_FIELD */
+  fld_ctr = field_id_search( db_handle, field_id );
+  if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles )
+    DB_RETURN( DB_INVALID_FIELD );
+
+  tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord + fld_ctr;
+
+  /* Check if this is existing sort index */
+  remb_sort_index_ctr = MAX_NUM_OF_SORT_INDEXS;
+
+  for( sort_index_ctr = 0; sort_index_ctr < MAX_NUM_OF_SORT_INDEXS; ++sort_index_ctr )
+  {
+    if( tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] EQ sort_index )
+      break;
+
+    if( tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] EQ INVALID_SORT_INDEX )
+      remb_sort_index_ctr = sort_index_ctr;
+
+  }
+
+  if( sort_index_ctr EQ MAX_NUM_OF_SORT_INDEXS )
+  { 
+    /* ok, this is new index, so
+       Check if limit for sort list corresponding to field_id (for a given database) 
+       has reached limit, MAX_NUM_OF_SORT_INDEXS. If so, return DB_FULL. */
+
+    if( remb_sort_index_ctr EQ MAX_NUM_OF_SORT_INDEXS )
+      DB_RETURN( DB_FULL );
+    
+    sort_index_ctr = remb_sort_index_ctr;
+
+    /* update file , "~/dbm/DD_<db_handle>" for SortIndexes. */
+
+    /* create the field data that is to be written */
+
+    DB_MALLOC( field_data, MAX_NUM_OF_SORT_INDEXS );
+    memcpy( field_data, tmp_ptrFieldRecord -> SortIndexList, MAX_NUM_OF_SORT_INDEXS );
+
+    field_data[sort_index_ctr] = sort_index;
+
+    db_ret_code = 
+      update_field_data_in_FFS ( &DbmMaster[db_handle].FFSFileHandle,
+                                 db_handle,
+                                 fld_ctr,
+                                 field_data,
+                                 SortIndexList_OFFSET,
+                                 MAX_NUM_OF_SORT_INDEXS );
+    if( db_ret_code NEQ DB_OK )
+    {
+      DB_MFREE( field_data );
+      DB_RETURN( db_ret_code )
+    }
+
+    DB_MFREE( field_data );
+    /* updation of DD_<db_handle> is over */
+  }
+
+  /* create sort list (if not there) */
+  if( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] NEQ NULL )
+  {
+    sort_list = tmp_ptrFieldRecord -> SortedLists[sort_index_ctr];
+  } 
+  else
+  {
+    DB_MALLOC( sort_list, tmp_ptrFieldRecord -> NumOfRecords + 1 );
+    memset( sort_list, INVALID_RECORD_NUM, tmp_ptrFieldRecord -> NumOfRecords + 1 );
+
+      /* the first element would be INVALID_RECORD_NUM (0xFF) */
+      copy_sort_list = sort_list + 1;
+
+    /* The list of available records is prepared from RecordBitMap */
+    for (record_num = 1; record_num <= tmp_ptrFieldRecord->NumOfRecords; record_num++)
+    {
+      if (db_get_bit_in_bitmap (tmp_ptrFieldRecord->RecordBitMap, record_num))
+      {
+        *copy_sort_list++ = record_num;
+      }
+    }
+
+  } /* sort_list is NULL */
+
+  /* Sort the records with given "comparison_function" (it takes record numbers, 
+     field_id and db_handle). Note that the sorted list would be kept in RAM 
+     (structure SortedLists, part of field record) till db_flush is called and 
+     cleared in db_flush. */
+
+    insertion_sort( sort_list,
+                    tmp_ptrFieldRecord -> UsedRecords,   /* only used records */
+                    compare_function,
+                    flags,
+                    db_handle,
+                    field_id );
+
+  /* writing sorted list to FFS would be done in db_flush */
+ 
+  /* Update corresponding field SortIndexList in RAM structures. */
+
+  tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] = sort_index;
+  tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] = sort_list;
+
+  DB_RETURN( DB_OK )
+}
+
+
+
+/***********************/
+/* INTERFACE FUNCTIONS */
+/***********************/
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: db_init              |
++--------------------------------------------------------------------+
+
+    PURPOSE : Initialises database manager
+*/
+void db_init ( void )
+{
+  UBYTE db_ctr;
+
+#ifdef FFS_CLOSE_BEFORE_OPEN
+  UBYTE fld_ctr;
+#endif
+
+  TRACE_FUNCTION("db_init()");
+
+  /* 1) Check DBM_State and if already initialized, return DB_OK */
+  if ( DBM_State EQ DBM_INITIALISED )
+    return;
+
+  /* 2)	Initialize DbmMaster structure */
+  for ( db_ctr = 0; db_ctr < MAX_DBs; ++db_ctr )
+  {
+    DbmMaster[db_ctr].DBState = UNUSED_ENTRY;
+
+#ifdef FFS_CLOSE_BEFORE_OPEN 
+
+    for( fld_ctr = 0; fld_ctr < MAX_OPEN_READ_PER_DB; ++fld_ctr )
+    {
+      DbmMaster[db_ctr].READ_OPEN_FIELDS[fld_ctr].fld_ctr = INVALID_FLD_CTR;
+    }
+    for( fld_ctr = 0; fld_ctr < MAX_OPEN_WRITE_PER_DB; ++fld_ctr )
+    {
+      DbmMaster[db_ctr].WRITE_OPEN_FIELDS[fld_ctr].fld_ctr = INVALID_FLD_CTR;
+    }
+    DbmMaster[db_ctr].old_read = 0;
+    DbmMaster[db_ctr].old_write = 0;
+
+#endif
+
+  }
+
+  UsedDBs = 0;
+
+#ifdef _SIMULATION_
+  {
+    T_FFS_SIZE ffs_ret_code = ffs_init();
+
+    TRACE_EVENT_P1("Initialization of FFS Simulation %d", ffs_ret_code );
+
+    /* Delete existing database */
+    init_RAM_with_FFS();
+
+    for( db_ctr = 0; db_ctr < MAX_DBs; ++db_ctr )
+    {
+      if( DbmMaster[db_ctr].DBState NEQ UNUSED_ENTRY )
+        db_remove( DbmMaster[db_ctr].DBDirectory );
+    }
+
+    db_exit();
+  }
+#endif
+
+  return;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: init_RAM_with_FFS    |
++--------------------------------------------------------------------+
+
+    PURPOSE : Initialise DBM RAM structures with FFS data
+*/
+LOCAL T_DB_CODE init_RAM_with_FFS ( void )
+{
+  /* Initializing "DBM related data" in RAM from FFS */
+
+  T_FFS_FD            ffs_dbm_fd;
+  T_FFS_SIZE          ffs_ret_code;
+  T_FFS_STAT          ffs_status;
+  UBYTE*              db_buffer;
+  UBYTE*              remb_db_buffer;
+  UBYTE*              field_buffer;
+  UBYTE*              remb_field_buffer;
+  UBYTE               db_ctr,
+                      fld_ctr,
+                      i;
+  char                filename[FILENAME_LEN];
+/* Implements Measure#32: Row 1181 */
+  char*               dbm_file = db_master_file;
+  T_DBM_MASTERRECORD  *dbm;
+
+  TRACE_FUNCTION("init_RAM_with_FFS()");
+
+  /* Check the presence of FFS directory DB_DIR */
+/* Implements Measure#32: Row 1184 */
+  ffs_ret_code = ffs_stat( db_dir, &ffs_status );
+
+  TRACE_EVENT_P1( "init_RAM_with_FFS:ffs_stat %d", ffs_ret_code );
+  /* error values of ffs_ret_code are handled later */
+
+  if( ffs_ret_code >= EFFS_OK )
+  {
+    /* Directory is present */
+     
+    /* Synchronize DB related data between FFS and RAM 
+       i.e. structures DbmMasterRecord and corresponding DbmFieldRecord. */
+
+    /* For DbmMaster */
+
+    DB_FFS_OPEN( ffs_dbm_fd, dbm_file, FFS_O_RDONLY );
+
+    if( (ffs_dbm_fd EQ EFFS_NAMETOOLONG ) OR
+        (ffs_dbm_fd EQ EFFS_BADNAME     ) OR
+        (ffs_dbm_fd EQ EFFS_NOTFOUND    ) OR
+        (ffs_dbm_fd EQ EFFS_INVALID     ) OR
+        (ffs_dbm_fd EQ EFFS_LOCKED      ) )
+
+    {
+      TRACE_EVENT_P1( "init_RAM_with_FFS:DB_FFS_OPEN %d", ffs_dbm_fd );
+      return DB_FAIL;
+    }
+
+    if( ffs_dbm_fd < EFFS_OK )
+    {
+      TRACE_EVENT_P1( "init_RAM_with_FFS:DB_FFS_OPEN %d", ffs_dbm_fd );
+      LastFFS_ReturnCode = ffs_dbm_fd;
+      return DB_FAIL_FS;
+    }
+
+    /* buffer for master records */
+    DB_MALLOC( db_buffer, T_DB_MASTER_RECORD_SIZE ); 
+    remb_db_buffer = db_buffer;
+
+    for( db_ctr = 0; db_ctr < MAX_DBs; ++db_ctr )
+    {
+      dbm = &DbmMaster[db_ctr];
+
+      db_buffer = remb_db_buffer;
+      ffs_ret_code = ffs_read( ffs_dbm_fd, db_buffer, T_DB_MASTER_RECORD_SIZE );
+
+      if( ( ffs_ret_code EQ EFFS_BADFD ) OR
+          ( ffs_ret_code EQ EFFS_BADOP ) )
+      {
+        TRACE_EVENT_P1( "init_RAM_with_FFS:ffs_read %d", ffs_ret_code );
+        DB_FFS_CLOSE( ffs_dbm_fd );
+        DB_MFREE( db_buffer );
+        return DB_FAIL;
+      }
+
+      if( ffs_ret_code EQ 0 ) /* number of bytes read EQ 0 */
+        break;
+
+      if( *db_buffer EQ 0xFF ) /* if invalid database */
+        continue;
+
+      memcpy( dbm->DBDirectory, db_buffer, MAX_LEN_DIRECTORY );
+      db_buffer += MAX_LEN_DIRECTORY;
+
+      dbm->NumOfFiles = *db_buffer++; /* Maximum number of supported fields */
+
+      dbm->Clean   = TRUE;
+      dbm->Tracked = (*db_buffer++ EQ FFS_TRACKED);
+
+      dbm->UsedFiles = 0;
+
+      dbm->DBState = CLOSED;
+
+      ++UsedDBs;
+
+      /* we need not "seek" here file pointer would have moved to next */
+    }
+    
+    DB_FFS_CLOSE( ffs_dbm_fd ); 
+    DB_MFREE( remb_db_buffer ); /* freeing db_buffer */
+
+    /* For FieldRecords */
+
+    /* buffer for field records */
+    DB_MALLOC( field_buffer, T_DB_FIELD_RECORD_SIZE ); 
+    remb_field_buffer = field_buffer;
+
+    for( db_ctr = 0; db_ctr < MAX_DBs; ++db_ctr )
+    {
+      dbm = &DbmMaster[db_ctr];
+
+      if( dbm->DBState EQ UNUSED_ENTRY )
+        continue;
+
+      /* Field file = DD_<pos. in DD_master> */
+
+/* Implements Measure#32: Row 1182, 1184 */
+      sprintf( filename, format_sDDd_str, db_dir, db_ctr);  
+
+      DB_FFS_OPEN( ffs_dbm_fd, filename, FFS_O_RDONLY );
+
+      if(  ( ffs_dbm_fd EQ EFFS_NOTFOUND ) OR   /* Field file not found */
+           ( ffs_dbm_fd EQ EFFS_NUMFD )    OR   /* FFS specific errors */
+           ( ffs_dbm_fd EQ EFFS_LOCKED)    )
+      {
+        TRACE_EVENT_P1( "init_RAM_with_FFS:DB_FFS_OPEN %d", ffs_dbm_fd );
+        DB_MFREE( field_buffer );
+        return DB_FAIL;
+      }
+
+      /* Allocate memory for field records */
+      DB_MALLOC( dbm->ptrFieldRecord, 
+                 dbm->NumOfFiles * sizeof(T_DBM_FIELDRECORD) );
+
+      for (fld_ctr = 0; fld_ctr < dbm->NumOfFiles; fld_ctr++)
+      {
+        field_buffer = remb_field_buffer;
+
+        ffs_ret_code = ffs_read( ffs_dbm_fd, field_buffer, T_DB_FIELD_RECORD_SIZE );
+
+        if( (ffs_ret_code EQ EFFS_BADFD ) OR
+            (ffs_ret_code EQ EFFS_BADOP ) )
+        {
+          TRACE_EVENT_P2( "init_RAM_with_FFS:ffs_read %d, fld_ctr %d", ffs_ret_code, fld_ctr );
+          DB_FFS_CLOSE ( ffs_dbm_fd );
+          DB_MFREE( field_buffer );
+          DB_MFREE( dbm->ptrFieldRecord );
+          dbm->ptrFieldRecord = NULL;
+          return DB_FAIL; 
+        }
+
+        if( ffs_ret_code < T_DB_FIELD_RECORD_SIZE )
+        {
+          /* we need not go further, just make rest of field ids as invalid (not existing) */
+          for( ; fld_ctr < dbm->NumOfFiles; ++fld_ctr )
+          {
+            dbm->ptrFieldRecord[fld_ctr].FieldID = INVALID_FIELD_ID;
+          }
+          break;
+        }
+
+        /* Syncing of field records (FFS => RAM) */
+        dbm->ptrFieldRecord[fld_ctr].FieldID = *field_buffer++;
+        dbm->ptrFieldRecord[fld_ctr].FieldID <<= 8;
+        dbm->ptrFieldRecord[fld_ctr].FieldID |= *field_buffer++;
+
+        dbm->ptrFieldRecord[fld_ctr].DBType = (T_DB_TYPE)*field_buffer++;
+
+        dbm->ptrFieldRecord[fld_ctr].RecordSize = *field_buffer++;
+        dbm->ptrFieldRecord[fld_ctr].RecordSize <<= 8;
+        dbm->ptrFieldRecord[fld_ctr].RecordSize |= *field_buffer++;
+
+        dbm->ptrFieldRecord[fld_ctr].NumOfRecords = *field_buffer++;
+
+        for (i = 0; i < MAX_NUM_OF_SORT_INDEXS; i++)
+        {
+          dbm->ptrFieldRecord[fld_ctr].SortIndexList[i] = *field_buffer++;
+          dbm->ptrFieldRecord[fld_ctr].SortedLists[i] = NULL;
+        }
+
+        memcpy (dbm->ptrFieldRecord[fld_ctr].RecordBitMap, field_buffer, RECORD_BITMAP_SIZE);
+          field_buffer += RECORD_BITMAP_SIZE;
+
+        dbm->ptrFieldRecord[fld_ctr].Clean = *field_buffer++;
+
+        if ( dbm->ptrFieldRecord[fld_ctr].FieldID NEQ INVALID_FIELD_ID )
+        {
+          /* 
+           * Trace out whether we consider the respective field as not clean.
+           */
+          if (!dbm->ptrFieldRecord[fld_ctr].Clean)
+          {
+            TRACE_EVENT_P1 ("Field %04X not clean in master file",
+                            dbm->ptrFieldRecord[fld_ctr].FieldID);
+          }
+
+          /* 
+           * Consistency check.
+           * Check whether the respective user field exists.
+           * If it does not exist set it to invalid.
+           * We are not taking care about possibly left over sort indexes.
+           * This inconsistency can happen when we got a hard power cycle 
+           * during some database updating operation.
+           */
+          sprintf (filename, "%s/UD_%04X", (char *)dbm->DBDirectory, 
+                   dbm->ptrFieldRecord[fld_ctr].FieldID);
+          ffs_ret_code = ffs_stat (filename, &ffs_status);
+          if (ffs_ret_code NEQ EFFS_OK)
+          {
+            TRACE_EVENT_P1 ("User data %s not existing in FFS", filename);
+            dbm->ptrFieldRecord[fld_ctr].FieldID = INVALID_FIELD_ID;
+            dbm->Clean = FALSE; /* Mark DB as not clean */
+          }
+
+          /* 
+           * Consistency check.
+           * Check that the respective user data does not exist twice.
+           * Normally it is expected that this inconsistency should not happen,
+           * if it happens we ignore all subsequent entries.
+           */
+          if ( dbm->ptrFieldRecord[fld_ctr].FieldID NEQ INVALID_FIELD_ID )
+          {
+            for (i = 0; i < fld_ctr; i++)
+            {
+              if (dbm->ptrFieldRecord[fld_ctr].FieldID EQ 
+                  dbm->ptrFieldRecord[i].FieldID)
+              {
+                TRACE_EVENT_P1 ("User data %04x existed twice", 
+                                dbm->ptrFieldRecord[fld_ctr].FieldID);
+                dbm->ptrFieldRecord[fld_ctr].FieldID = INVALID_FIELD_ID;
+                dbm->ptrFieldRecord[i].Clean = FALSE; /* Don't trust this field */
+                dbm->Clean = FALSE; /* Mark DB as not clean */
+                break;
+              }
+            }
+          }
+
+          /*
+           * Consistency check. 
+           * Check whether the sorted index really exists in the FFS.
+           * If it does not exist set it to invalid.
+           */
+          if ( dbm->ptrFieldRecord[fld_ctr].FieldID NEQ INVALID_FIELD_ID )
+          {
+            for( i = 0; i < MAX_NUM_OF_SORT_INDEXS; i++ )
+            {
+              if (dbm->ptrFieldRecord[fld_ctr].SortIndexList[i] NEQ INVALID_SORT_INDEX)
+              {
+                sprintf(filename, "%s/UD_%04X_sort_%d", 
+                         (char *)dbm->DBDirectory, 
+                         dbm->ptrFieldRecord[fld_ctr].FieldID,
+                         dbm->ptrFieldRecord[fld_ctr].SortIndexList[i]);
+                ffs_ret_code = ffs_stat (filename, &ffs_status);
+                if (ffs_ret_code NEQ EFFS_OK)
+                {
+                  TRACE_EVENT_P1 ("Sort index %s not existing in FFS", filename);
+                  dbm->ptrFieldRecord[fld_ctr].SortIndexList[i] = INVALID_SORT_INDEX;
+                  dbm->ptrFieldRecord[fld_ctr].Clean = FALSE; /* Don't trust this field */
+                }
+              }
+            }
+          }
+
+#ifndef FFS_CLOSE_BEFORE_OPEN
+          tmp_ptrFieldRecord -> FFSFileHandle = INVALID_FD; 
+#endif
+          /* we need to get size of user file <DBDirectory>/UD_<field_id> 
+             NextRecordNum = (size of user file) / record size */
+          dbm->ptrFieldRecord[fld_ctr].NextRecordNum = 
+                  cal_NextRecordNum ( (const char*)DbmMaster[db_ctr].DBDirectory, 
+                                      dbm->ptrFieldRecord[fld_ctr].FieldID,
+                                      dbm->ptrFieldRecord[fld_ctr].RecordSize );
+                                            
+          /* Update database records for UsedFiles, Clean, and UsedRecords */
+
+          dbm->UsedFiles++;
+
+          /* Mark DB as not clean if only one field is not clean */
+          if (!dbm->ptrFieldRecord[fld_ctr].Clean)
+            dbm->Clean = FALSE;
+
+          /* For calculating UsedRecords */
+          dbm->ptrFieldRecord[fld_ctr].UsedRecords = 0;
+          for (i = 1; i <= dbm->ptrFieldRecord[fld_ctr].NumOfRecords; i++)
+          {
+            if (db_get_bit_in_bitmap (dbm->ptrFieldRecord[fld_ctr].RecordBitMap, i))
+              dbm->ptrFieldRecord[fld_ctr].UsedRecords++;
+          }
+
+        } /* FieldID NEQ INVALID_FIELD_ID */
+
+      } /* for( fld_ctr ) ... all fields */
+
+      /* close the DD_<db_handle> file */
+      DB_FFS_CLOSE( ffs_dbm_fd );
+
+    } /* ffs_ret_code >= EFFS_OK */
+
+    DB_MFREE( remb_field_buffer );  /* freeing field buffer */
+
+    DBM_State = DBM_INITIALISED;
+
+    return DB_OK;
+
+  } /* if( ffs_ret_code >= EFFS_OK ) */
+
+  /* Directory not present */
+  if( ffs_ret_code EQ EFFS_NOTFOUND )
+  {
+    /* Create DBM directory */
+/* Implements Measure#32: Row 1184 */
+    ffs_ret_code = ffs_mkdir( db_dir ); 
+    
+    if( (ffs_ret_code EQ EFFS_NAMETOOLONG ) OR
+        (ffs_ret_code EQ EFFS_BADNAME     ) )
+    {
+      TRACE_EVENT_P1( "init_RAM_with_FFS:ffs_mkdir %d", ffs_ret_code );
+      return DB_FAIL;
+    }
+
+    if( ffs_ret_code < EFFS_OK )
+    {
+      TRACE_EVENT_P1( "init_RAM_with_FFS:ffs_mkdir %d", ffs_ret_code );
+      LastFFS_ReturnCode = ffs_ret_code;
+      return DB_FAIL_FS;
+    }
+
+    /* Create empty file DD_master
+       FFS_O_EXCL => Generate error if FFS_O_CREATE is also specified and 
+                     the file already exists. */
+
+    DB_FFS_OPEN( ffs_dbm_fd, dbm_file, FFS_O_CREATE | FFS_O_RDWR | FFS_O_EXCL );
+
+    if( (ffs_dbm_fd EQ EFFS_NAMETOOLONG ) OR
+        (ffs_dbm_fd EQ EFFS_BADNAME     ) )
+    {
+      TRACE_EVENT_P1( "init_RAM_with_FFS:DB_FFS_OPEN %d", ffs_dbm_fd );
+/* Implements Measure#32: Row 1184 */
+      ffs_ret_code = ffs_remove( db_dir ); /* undo creating of DBM directory */
+      return DB_FAIL;
+    }
+
+    if( ffs_dbm_fd < EFFS_OK )
+    {
+      TRACE_EVENT_P1( "init_RAM_with_FFS:DB_FFS_OPEN %d", ffs_dbm_fd );
+      LastFFS_ReturnCode = ffs_dbm_fd;
+/* Implements Measure#32: Row 1184 */
+      ffs_ret_code = ffs_remove( db_dir ); /* undo creating of DBM directory */
+      return DB_FAIL_FS;
+    }
+
+    DB_FFS_CLOSE( ffs_dbm_fd );
+
+    DBM_State = DBM_INITIALISED;
+
+    return DB_OK;
+  }
+
+  /* Unexpected error: Not a directory */
+  return DB_FAIL;
+
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: db_create            |
++--------------------------------------------------------------------+
+
+    PURPOSE : Create a new database in the given directory of the FFS. 
+              The directory must not to exist yet, it will be created.
+*/
+int db_create ( const char* directory,
+                UBYTE       num_of_fields,
+                BOOL        tracked )
+{
+  int         db_handle;
+  T_DB_CODE   db_ret_code;
+  UBYTE       fld_ctr;
+  S8          db_ctr;
+  T_FFS_SIZE  ffs_ret_code;
+  T_FFS_FD    ffs_fd;
+  char        field_file[FILENAME_LEN];
+  char*       field_file_ptr = field_file;
+  UBYTE*      dbm_data;
+  UBYTE*      remb_dbm_data;
+
+  TRACE_FUNCTION("db_create()");
+
+  /* If DBM is not in initialized state, call init_RAM_with_FFS (). */
+  if( DBM_State NEQ DBM_INITIALISED )
+  {
+    T_DB_CODE db_ret_code;
+
+    db_ret_code = init_RAM_with_FFS();
+
+    if( db_ret_code NEQ DB_OK )
+      DB_RETURN( db_ret_code );
+  }
+
+  /* See if you have reached the maximum number of DBs, ? 
+     (UsedDBs+1) > MAX_DBs */
+
+  if( UsedDBs EQ MAX_DBs )
+    DB_RETURN( DB_FULL );
+
+
+  /* Check DbmMaster if already database for "directory" exists. 
+     If yes, return error "DB_EXISTS" */
+
+  db_handle = -1;
+  for( db_ctr = (MAX_DBs - 1); db_ctr >= 0; --db_ctr )
+  {
+    if ( DbmMaster[db_ctr].DBState NEQ UNUSED_ENTRY )
+    {
+        if( memcmp( DbmMaster[db_ctr].DBDirectory, 
+                    directory, 
+                    strlen( directory )          ) EQ 0 )
+        DB_RETURN( DB_EXISTS )
+    }
+    else
+    {
+      db_handle = db_ctr;
+    }
+  }
+
+  /* sanity check */
+  if( num_of_fields <= 0 ) /*lint !e775 check for <= on non-negative*/
+    DB_RETURN( DB_FAIL );
+
+  if (db_handle EQ -1) 
+  {
+    /* No free slot found */
+    DB_RETURN ( DB_FAIL ) /* DB_FULL maybe better choice */
+  }
+
+  /* Create a directory, "<DBDirectory>" (DBDirectory = directory) */
+  ffs_ret_code = ffs_mkdir( directory ); 
+
+  if( ffs_ret_code < EFFS_OK ) 
+  {
+    TRACE_EVENT_P1( "db_create:ffs_mkdir %d", ffs_ret_code );
+    LastFFS_ReturnCode = ffs_ret_code;
+    DB_RETURN( DB_FAIL_FS )
+  }
+
+
+  /* Create a empty file, "~/dbm/DD_<position in DD_master = db_handle>"; 
+     if this FFS operation fails, we need to delete the directory 
+     before returning error. 
+  */
+/* Implements Measure#32: Row 1182, 1191 */
+  sprintf( field_file, format_sDDd_str, db_dir, db_handle);  
+
+  TRACE_EVENT_P1( "field_file %s", field_file );
+
+  /* FFS_O_EXCL => Generate error if FFS_O_CREATE is also specified and 
+                   the file already exists. */
+  DB_FFS_OPEN( ffs_fd, field_file_ptr, FFS_O_CREATE | FFS_O_RDWR | FFS_O_EXCL ); 
+
+  if( ( ffs_fd EQ EFFS_EXISTS )      OR
+      ( ffs_fd EQ EFFS_NAMETOOLONG ) OR
+      ( ffs_fd EQ EFFS_BADNAME )     OR
+      ( ffs_fd EQ EFFS_INVALID )     )
+  {
+    TRACE_EVENT_P1( "db_create:DB_FFS_OPEN %d", ffs_fd );
+    ffs_fd = ffs_remove( directory ); 
+    DB_RETURN( DB_FAIL )
+  }
+
+  if( ffs_fd < EFFS_OK )
+  {
+    TRACE_EVENT_P1( "db_create:DB_FFS_OPEN %d", ffs_fd );
+    LastFFS_ReturnCode = ffs_fd;
+    ffs_ret_code = ffs_remove( directory ); 
+    DB_RETURN( DB_FAIL_FS )
+  }
+
+  /* DB_FFS_CLOSE( ffs_fd ); we will close it in db_flush */
+
+#ifdef FFS_OPEN_PROBLEM_PATCH
+  DB_FFS_CLOSE( ffs_fd );
+  ffs_fd = INVALID_FD;
+#endif
+
+#ifdef FFS_CLOSE_BEFORE_OPEN
+  /* no we do not close it */
+#endif
+
+  /* Update FFS data i.e. file, "~/dbm/DD_master". */
+
+  /* prepare the dbm data and write */
+  DB_MALLOC( dbm_data, T_DB_MASTER_RECORD_SIZE );
+  memset( dbm_data, 0, T_DB_MASTER_RECORD_SIZE );
+  remb_dbm_data = dbm_data;
+
+  memcpy( dbm_data, directory, MAX_LEN_DIRECTORY );
+  dbm_data += MAX_LEN_DIRECTORY;
+  
+  *dbm_data++ = num_of_fields;
+
+  *dbm_data++ = ( tracked ) ? FFS_TRACKED : FFS_NOT_TRACKED;
+
+  dbm_data = remb_dbm_data;
+
+/* Implements Measure#32: Row 1188 */
+  db_ret_code = 
+    update_dbm_data_in_FFS ( db_master_file,
+                             (UBYTE) db_handle,   /* to supress warning */
+                             T_DB_MASTER_RECORD_SIZE,
+                             dbm_data,
+                             0,
+                             T_DB_MASTER_RECORD_SIZE );
+
+  if( db_ret_code NEQ DB_OK )
+  {
+    DB_MFREE( dbm_data );
+    ffs_ret_code = ffs_remove( directory );
+    DB_FFS_CLOSE( ffs_fd );
+    ffs_ret_code = ffs_remove( field_file );
+    DB_RETURN( db_ret_code )
+  }
+
+  DB_MFREE( dbm_data );
+  /* updation of DD_master done 
+     now update RAM structures  */
+
+  memcpy( DbmMaster[db_handle].DBDirectory, 
+          directory, 
+          strlen(directory) );
+
+  DbmMaster[db_handle].NumOfFiles    = num_of_fields;
+  DbmMaster[db_handle].UsedFiles     = 0;  
+  DbmMaster[db_handle].Clean = TRUE;
+  DbmMaster[db_handle].Tracked = tracked;
+  DbmMaster[db_handle].DBState       = OPEN;
+  DbmMaster[db_handle].FFSFileHandle = ffs_fd;
+
+#ifdef FFS_CLOSE_BEFORE_OPEN
+
+  /* No files corresponding to fields have been opened 
+     This initialization is already done in db_init */
+
+#endif
+  
+  /* Allocate memory for storing field information 
+     and initialize the memory with "FF" */
+
+  DB_MALLOC( DbmMaster[db_handle].ptrFieldRecord, 
+              num_of_fields * sizeof(T_DBM_FIELDRECORD) );
+
+  for( fld_ctr = 0; fld_ctr < num_of_fields; ++fld_ctr )
+  {
+    DbmMaster[db_handle].ptrFieldRecord[fld_ctr].FieldID = INVALID_FIELD_ID; 
+  }
+
+  UsedDBs++;
+
+  DB_RETURN( db_handle )
+
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: db_open              |
++--------------------------------------------------------------------+
+
+    PURPOSE : Open an existing database
+*/
+int db_open ( const char *directory )
+{
+  T_DB_CODE  db_ret_code;
+  UBYTE      db_ctr;
+
+  TRACE_FUNCTION("db_open()");
+
+  /* If DBM is not in initialized state, call init_RAM_with_FFS (). */
+  if( DBM_State NEQ DBM_INITIALISED )
+  {
+    db_ret_code = init_RAM_with_FFS();
+
+    if( db_ret_code NEQ DB_OK )
+      DB_RETURN( db_ret_code );
+  }
+
+  /* Search for "directory" in DbmMaster */
+  for( db_ctr = 0; db_ctr < MAX_DBs; ++db_ctr )
+  {
+    if( DbmMaster[db_ctr].DBState NEQ UNUSED_ENTRY )
+    {
+        if( memcmp( DbmMaster[db_ctr].DBDirectory, 
+                    directory, 
+                    strlen(directory)                     ) EQ 0 )
+          break;
+    } 
+  }
+
+  /* If "directory" not found, return DB_FAIL. */
+  if( db_ctr EQ MAX_DBs )
+    DB_RETURN( DB_INVALID_DB );
+
+  /* Update DBState as "OPEN". */
+  DbmMaster[db_ctr].DBState = OPEN;
+
+  /* Return corresponding DBHandle. */
+  DB_RETURN( db_ctr )
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: db_create_field      |
++--------------------------------------------------------------------+
+
+    PURPOSE : Create a new elementary file of a given type with a given 
+              numeric identifier and a given record size.
+*/
+T_DB_CODE db_create_field ( int         db_handle, 
+                            T_DB_TYPE   db_type, 
+                            USHORT      field_id, 
+                            USHORT      record_size, 
+                            USHORT      num_of_records )
+{
+  T_DB_CODE          db_ret_code;
+  char               user_field_file[FILENAME_LEN];
+  UBYTE              fld_ctr,
+                     sort_index_ctr;
+  T_FFS_FD           ffs_fd_user_field_file;
+  UBYTE*             field_data;
+  UBYTE*             remb_field_data;
+  T_DBM_FIELDRECORD* tmp_ptrFieldRecord;  
+
+
+  TRACE_FUNCTION("db_create_field()");
+
+  /* DBM_State check */
+  DBM_State_check;
+
+  /* db_handle check */
+  db_ret_code = db_handle_check( db_handle );
+  if( db_ret_code NEQ DB_OK )
+    DB_RETURN( db_ret_code );
+
+  /*	field id search; if field id found, return error DB_FIELD_EXISTS */
+  if( field_id_search( db_handle, field_id ) NEQ DbmMaster[db_handle].NumOfFiles )
+    DB_RETURN( DB_FIELD_EXISTS );
+
+  /* If limit for number of fields for this DB has been reached, return error DB_FULL. */
+  if( DbmMaster[db_handle].UsedFiles  EQ 
+      DbmMaster[db_handle].NumOfFiles )
+    DB_RETURN( DB_FULL );
+
+  /* Search for free field entry in field records corresponding to the database. */
+  for( fld_ctr = 0; fld_ctr < DbmMaster[db_handle].NumOfFiles; ++fld_ctr )
+  {
+    if( DbmMaster[db_handle].ptrFieldRecord[fld_ctr].FieldID EQ INVALID_FIELD_ID )
+      break;
+  }
+
+  if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles )
+  { /* this is "inconsistency"; should never happen */
+    DB_RETURN( DB_FAIL )
+  }
+
+  /* sanity check */
+  /*lint -e{775} check for <= on non-negative */
+  if ((num_of_records <= 0) OR
+      (record_size <= 0))
+  {
+    DB_RETURN( DB_FAIL )
+  }
+
+  /* Create file "<DBDirectory>/UD_<field_id>" */
+/* Implements Measure#32: Row 1189 */
+  sprintf( user_field_file, format_sUDd_str, (char *)DbmMaster[db_handle].DBDirectory, field_id );
+
+  /* FFS_O_EXCL => Generate error if FFS_O_CREATE is also specified and 
+                   the file already exists. */
+#ifndef FFS_CLOSE_BEFORE_OPEN
+
+  DB_FFS_OPEN( ffs_fd_user_field_file, user_field_file, FFS_O_CREATE | FFS_O_RDWR | FFS_O_EXCL ); 
+
+#else
+
+  ffs_fd_user_field_file = 
+    db_open_user_field_file( db_handle, 
+                             fld_ctr, 
+                             user_field_file, 
+                             FFS_O_CREATE | FFS_O_RDWR | FFS_O_EXCL );
+#endif
+
+  if( ( ffs_fd_user_field_file EQ EFFS_EXISTS )      OR
+      ( ffs_fd_user_field_file EQ EFFS_NAMETOOLONG ) OR
+      ( ffs_fd_user_field_file EQ EFFS_BADNAME )     OR
+      ( ffs_fd_user_field_file EQ EFFS_INVALID )     )
+  {
+    TRACE_EVENT_P1( "db_create_field:DB_FFS_OPEN %d", ffs_fd_user_field_file );
+    DB_RETURN( DB_FAIL )
+  }
+
+  if( ffs_fd_user_field_file < EFFS_OK )
+  {
+    TRACE_EVENT_P1( "db_create_field:DB_FFS_OPEN %d", ffs_fd_user_field_file );
+    LastFFS_ReturnCode = ffs_fd_user_field_file;
+    DB_RETURN( DB_FAIL_FS )
+  }
+
+  /* We will close this file in db_flush */
+
+#ifdef FFS_OPEN_PROBLEM_PATCH
+  DB_FFS_CLOSE( ffs_fd_user_field_file );
+  ffs_fd_user_field_file = INVALID_FD;
+#endif
+
+  
+  /* file "<DBDirectory>/UD_<field_id>" has been created 
+     Now, Add new field entry in "~/dbm/DD_<db_handle>" */
+
+  /* create the field data that needs to be written */
+
+  DB_MALLOC( field_data, T_DB_FIELD_RECORD_SIZE );
+  memset( field_data, 0, T_DB_FIELD_RECORD_SIZE );
+  remb_field_data = field_data;
+
+  *field_data = (UBYTE) ( (field_id & 0xFF00) >> 8 ); 
+  ++field_data;
+  *field_data = (UBYTE) (field_id & 0x00FF);
+  ++field_data;
+
+  *field_data = db_type; 
+  ++field_data;
+
+  *field_data = (UBYTE) ( (record_size & 0xFF00) >> 8 );
+  ++field_data;
+  *field_data = (UBYTE) (record_size & 0x00FF);
+  ++field_data;
+
+  *field_data = (UBYTE)num_of_records;
+  field_data++;
+  
+  memset( field_data, 0xFF, MAX_NUM_OF_SORT_INDEXS ); 
+  field_data += MAX_NUM_OF_SORT_INDEXS;
+
+  memset( field_data, 0, RECORD_BITMAP_SIZE );
+  field_data += RECORD_BITMAP_SIZE;
+
+  *field_data = FFS_CLEAN;
+  
+  field_data = remb_field_data;
+
+  db_ret_code = 
+    update_field_data_in_FFS ( &DbmMaster[db_handle].FFSFileHandle,
+                               db_handle,
+                               fld_ctr,
+                               field_data,
+                               0,
+                               T_DB_FIELD_RECORD_SIZE );
+
+  if( db_ret_code NEQ DB_OK )
+  {
+    DB_MFREE( field_data );
+    ffs_remove( user_field_file );
+    DB_RETURN( db_ret_code )
+  }
+
+  DB_MFREE( field_data );
+  /* updation of DD_<db_handle> is over */
+
+  /* Add new field entry in field records in RAM. */
+  tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord + fld_ctr;
+
+  tmp_ptrFieldRecord -> FieldID       = field_id;
+  tmp_ptrFieldRecord -> DBType        = db_type;
+  tmp_ptrFieldRecord -> RecordSize    = record_size;
+  tmp_ptrFieldRecord -> NumOfRecords  = (UBYTE)num_of_records;
+  tmp_ptrFieldRecord -> UsedRecords   = 0; 
+  tmp_ptrFieldRecord -> Clean         = TRUE;
+
+#ifndef FFS_CLOSE_BEFORE_OPEN
+  tmp_ptrFieldRecord -> FFSFileHandle = ffs_fd_user_field_file;
+#endif
+
+  tmp_ptrFieldRecord -> NextRecordNum = 1;
+
+  memset( tmp_ptrFieldRecord -> RecordBitMap, 0, RECORD_BITMAP_SIZE );
+
+  for( sort_index_ctr = 0; sort_index_ctr < MAX_NUM_OF_SORT_INDEXS; ++sort_index_ctr )
+  {
+    tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr]  = INVALID_SORT_INDEX;
+    tmp_ptrFieldRecord -> SortedLists[sort_index_ctr]    = NULL;
+  }
+
+  /* Increment UsedFiles for the particular database in RAM */
+  DbmMaster[db_handle].UsedFiles += 1;
+
+  /* everyting ok */
+  DB_RETURN( DB_OK )
+
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: db_write_record      |
++--------------------------------------------------------------------+
+
+    PURPOSE : Write length bytes at offset into the given record in 
+              (database, field)
+*/
+int db_write_record ( int          db_handle,	 
+                      USHORT       field_id, 
+                      USHORT       record_num, 
+                      USHORT       offset, 
+                      USHORT       length, 
+                      const UBYTE* buffer )
+{
+  T_DB_CODE  db_ret_code;
+  UBYTE fld_ctr,
+        rec_ctr;
+  char  user_field_file[FILENAME_LEN];
+  T_DBM_FIELDRECORD* tmp_ptrFieldRecord;
+  UBYTE*  record_buffer;
+  UBYTE*  field_data;
+  BOOL this_is_new_record = TRUE;
+
+  TRACE_FUNCTION("db_write_record()");
+
+  TRACE_EVENT_P1("field_id %04X", field_id);
+
+  /* DBM_State check */
+  DBM_State_check;
+
+  /* db_handle check */
+  db_ret_code = db_handle_check( db_handle );
+  if( db_ret_code NEQ DB_OK )
+    DB_RETURN( db_ret_code );
+
+  /*	field id search; if field not found, return error DB_INVALID_FIELD */
+  fld_ctr = field_id_search( db_handle, field_id );
+  if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles )
+    DB_RETURN( DB_INVALID_FIELD );
+
+  tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord + fld_ctr;
+
+  /* Check if record exceeds the record size (i.e. offset + length > record size); 
+     if it exceeds, return error DB_INVALID_SIZE */
+  if( (offset + length) > 
+      tmp_ptrFieldRecord -> RecordSize )
+    DB_RETURN( DB_INVALID_SIZE );
+
+  /* Check if FFS file is already opened using FFSFileHandle, part of field record. 
+     If it is not yet opened, open the FFS file and update FFSFileHandle. 
+     This is taken care in read_user_record_from_FFS */
+
+  /* User data file name is "<DBDirectory>/UD_<field_id>" 
+     This would be used below */
+
+/* Implements Measure#32: Row 1200 */
+  sprintf( user_field_file, 
+           format_sUDd_str, 
+           (char *)DbmMaster[db_handle].DBDirectory, 
+           tmp_ptrFieldRecord -> FieldID );
+
+  if( record_num EQ 0 )
+  {
+    /* If given record is equal to zero, 
+        o	Find a free record using RecordBitMap.
+        o	If free record not found, return DB_FULL */
+
+    record_num = db_search_bit_in_bitmap (tmp_ptrFieldRecord->RecordBitMap,
+                                          tmp_ptrFieldRecord->NumOfRecords,
+                                          FALSE);
+
+    if (record_num EQ 0)
+      DB_RETURN( DB_FULL );
+                                             
+
+  }
+  else
+  {
+    /* If given record is not equal to zero, 
+        o	Check if record exists using RecordBitMap; 
+          if not found, proceed to writing..
+        o	Read the record from "<DBDirectory>/UD_<field_id>" and 
+          compare it with given record (partially if offset > 0). Memcmp would be used.
+        o	If record match, return DB_OK. */
+
+    if (db_get_bit_in_bitmap (tmp_ptrFieldRecord->RecordBitMap, record_num))
+    {
+      /* record exists */
+      this_is_new_record = FALSE;
+
+      DB_MALLOC( record_buffer, length); 
+
+      /* Implements Measure # 211 */
+      db_ret_code = 
+        read_write_user_record_from_FFS ( user_field_file,
+
+#ifndef FFS_CLOSE_BEFORE_OPEN
+                                    &(tmp_ptrFieldRecord -> FFSFileHandle),
+#else
+                                    db_handle,
+                                    fld_ctr,
+                                    &Dummy_FFSFileHandle,
+#endif
+                                    (UBYTE)record_num,
+                                    tmp_ptrFieldRecord -> RecordSize,
+                                    offset,
+                                    length,
+                                          record_buffer,
+                                          FFS_O_RDONLY );
+
+
+      if( db_ret_code NEQ DB_OK )
+      {
+        DB_MFREE( record_buffer );
+        DB_RETURN( db_ret_code )
+      }
+
+      /* See if there is same data, if so, we need not overwrite */
+      if( memcmp( record_buffer, buffer, length) EQ 0 )
+      { /* matching data */
+        DB_MFREE( record_buffer );
+        DB_RETURN( DB_OK )
+      }
+
+      DB_MFREE( record_buffer );
+
+    } /* record exists */
+
+  } /* record_num EQ 0 ? */
+
+
+  /* As per the request, write record in FFS in "<DBDirectory>/UD_<field_id>" */
+
+  /* in case of new record, we need to create fill unfilled-data with FF */
+
+  if( this_is_new_record )
+  { /* new record */
+
+    DB_MALLOC( record_buffer, tmp_ptrFieldRecord -> RecordSize ); 
+    memset( record_buffer, 0xFF, tmp_ptrFieldRecord -> RecordSize ) ;
+
+    /* To take care of non-sequential write 
+       For example, initially when file is empty, and say user writes
+       3rd record, 1st and 2nd record should be addded as dummy and then
+       3rd record */
+
+    rec_ctr = tmp_ptrFieldRecord -> NextRecordNum;
+
+    while( rec_ctr < record_num   )
+    {
+      /* Implements Measure # 211 */
+      db_ret_code = 
+      read_write_user_record_from_FFS ( user_field_file,
+
+#ifndef FFS_CLOSE_BEFORE_OPEN
+                                   &(tmp_ptrFieldRecord -> FFSFileHandle),
+#else
+                                   db_handle,
+                                   fld_ctr,
+                                   &Dummy_FFSFileHandle,
+#endif
+                                   rec_ctr,
+                                   tmp_ptrFieldRecord -> RecordSize,
+                                   0,
+                                   tmp_ptrFieldRecord -> RecordSize,
+                                        record_buffer,
+                                        FFS_O_RDWR );
+
+      if( db_ret_code NEQ DB_OK )
+      {
+        DB_MFREE( record_buffer );
+        DB_RETURN( db_ret_code )
+      }
+
+      ++rec_ctr;
+    }
+
+    /* Add the new record */
+
+    memcpy( record_buffer + offset, buffer, length );
+
+      /* Implements Measure # 211 */
+      db_ret_code = 
+      read_write_user_record_from_FFS ( user_field_file,
+
+#ifndef FFS_CLOSE_BEFORE_OPEN
+                                 &(tmp_ptrFieldRecord -> FFSFileHandle),
+#else
+                                 db_handle,
+                                 fld_ctr,
+                                 &Dummy_FFSFileHandle,
+#endif
+                                 (UBYTE)record_num,
+                                 tmp_ptrFieldRecord -> RecordSize,
+                                 0,
+                                 tmp_ptrFieldRecord -> RecordSize,
+                                        record_buffer,
+                                        FFS_O_RDWR );
+
+
+    if( db_ret_code NEQ DB_OK )
+    {
+      DB_MFREE( record_buffer );
+      DB_RETURN( db_ret_code )
+    }
+
+    DB_MFREE( record_buffer );
+
+    /* writing of record is over, update DBState (as IN_USE). */
+    DbmMaster[db_handle].DBState = IN_USE;
+
+  } else {
+    /* overwritten record */ 
+
+      /* Implements Measure # 211 */
+      db_ret_code = 
+      read_write_user_record_from_FFS ( user_field_file,
+
+#ifndef FFS_CLOSE_BEFORE_OPEN
+                                 &(tmp_ptrFieldRecord -> FFSFileHandle),
+#else
+                                 db_handle,
+                                 fld_ctr,
+                                 &Dummy_FFSFileHandle,
+#endif
+                                 (UBYTE)record_num,
+                                 tmp_ptrFieldRecord -> RecordSize,
+                                 offset,
+                                 length,
+                                        (UBYTE*)buffer,
+                                        FFS_O_RDWR );
+
+    if( db_ret_code NEQ DB_OK )
+    {
+      DB_RETURN( db_ret_code )
+    }
+
+    /* writing of record is over, update DBState (as IN_USE). */
+    DbmMaster[db_handle].DBState = IN_USE;
+
+    /* get the sort lists in RAM from FFS */
+    get_sort_lists_from_FFS( (UBYTE)db_handle, fld_ctr );
+
+    /* this is updation of record, so need to be re-sorted */
+    update_in_sort_lists( (UBYTE)db_handle, fld_ctr, (UBYTE)record_num );
+
+    /* if database is not tracked, no need to go further for history log writing */
+    if (!DbmMaster[db_handle].Tracked)
+      DB_VALUE_RETURN( record_num );
+
+    /* if already Clean has been reset, only history updation */
+    if (!DbmMaster[db_handle].Clean)
+    {
+      db_ret_code = update_history_log( db_handle, field_id, record_num );
+
+      if( db_ret_code NEQ DB_OK )
+        DB_RETURN( db_ret_code );
+
+      DB_VALUE_RETURN( record_num )
+    }
+
+  } /* this_is_new_record */
+
+  /* Updating RecordBitMap and Clean in FFS, ~/dbm/DD_<db_handle> */
+
+  /* create the field data that is to be written */
+
+  DB_MALLOC( field_data, ( T_DB_FIELD_RECORD_SIZE - RecordBitMap_OFFSET ) );
+  memset( field_data, 0, ( T_DB_FIELD_RECORD_SIZE - RecordBitMap_OFFSET ) );
+  memcpy( field_data, tmp_ptrFieldRecord -> RecordBitMap, RECORD_BITMAP_SIZE );
+
+  if( this_is_new_record )
+  { /* RecordBitMap to be updated only for new records */
+    db_set_bit_in_bitmap (field_data, record_num, TRUE);
+  } 
+
+  /* clean is reset in memset, so no processing for it 
+     (in case of non-tracked database, anyway we ignore it ! */ 
+
+  db_ret_code = 
+    update_field_data_in_FFS ( &DbmMaster[db_handle].FFSFileHandle,
+                               db_handle,
+                               fld_ctr,
+                               field_data,
+                               RecordBitMap_OFFSET,
+                               ( T_DB_FIELD_RECORD_SIZE - RecordBitMap_OFFSET ) );
+
+
+  if( db_ret_code NEQ DB_OK )
+  {
+    DB_MFREE( field_data );
+    DB_RETURN( db_ret_code )
+  }
+
+  DB_MFREE( field_data );
+  /* updation of DD_<db_handle> is over */
+
+  /* Updating RAM (both DbmMaster and Field records) strctures */
+  tmp_ptrFieldRecord->Clean = FALSE;
+
+  if( this_is_new_record )
+  { /* RecordBitMap to be updated only for new records */
+    db_set_bit_in_bitmap (tmp_ptrFieldRecord->RecordBitMap,
+                          record_num,
+                          TRUE);
+
+    ++tmp_ptrFieldRecord -> UsedRecords;
+
+    tmp_ptrFieldRecord -> NextRecordNum =  
+        ( (record_num + 1) > tmp_ptrFieldRecord -> NextRecordNum ) ?
+          (record_num + 1) : tmp_ptrFieldRecord -> NextRecordNum ;
+
+    /* get the sort lists in RAM from FFS */
+    get_sort_lists_from_FFS( (UBYTE)db_handle, fld_ctr );
+
+    /* note the record number for sorting later 
+       yeah, we call it *after* updating UsedRecords */
+    new_in_sort_lists( (UBYTE)db_handle, fld_ctr, (UBYTE)record_num );
+
+  }
+
+  DbmMaster[db_handle].Clean = FALSE;
+
+  /* history log updation */
+
+  db_ret_code = update_history_log( db_handle, field_id, record_num );
+
+  if( db_ret_code NEQ DB_OK )
+    DB_RETURN( db_ret_code );
+
+  DB_VALUE_RETURN( record_num )
+
+}
+
+
+int db_update_ext_bitmap(int          db_handle, 
+                               USHORT       field_id, 
+                               USHORT       record_num,
+                               BOOL           flag)
+{
+T_DB_CODE  db_ret_code;
+  UBYTE fld_ctr;
+  T_DBM_FIELDRECORD* tmp_ptrFieldRecord;
+  UBYTE*  record_buffer;
+  UBYTE*  field_data;
+  BOOL this_is_new_record = TRUE;
+
+  TRACE_FUNCTION("db_update_ext_bimap()");
+
+ 
+  /* db_handle check */
+  db_ret_code = db_handle_check( db_handle );
+  if( db_ret_code NEQ DB_OK )
+    DB_RETURN( db_ret_code );
+
+  /*	field id search; if field not found, return error DB_INVALID_FIELD */
+  fld_ctr = field_id_search( db_handle, field_id );
+  if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles )
+    DB_RETURN( DB_INVALID_FIELD );
+
+  tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord + fld_ctr;
+
+  /* Updating RecordBitMap and Clean in FFS, DD_<db_handle> */
+
+  /* create the field data that is to be written */
+
+  DB_MALLOC( field_data, ( T_DB_FIELD_RECORD_SIZE - RecordBitMap_OFFSET ) );
+  memset( field_data, 0, ( T_DB_FIELD_RECORD_SIZE - RecordBitMap_OFFSET ) );
+  memcpy( field_data, tmp_ptrFieldRecord -> RecordBitMap, RECORD_BITMAP_SIZE );
+
+  /* RecordBitMap to be updated only for new records */
+   db_set_bit_in_bitmap (field_data, record_num, flag);
+
+  /* clean is reset in memset, so no processing for it 
+     (in case of non-tracked database, anyway we ignore it ! */ 
+
+  db_ret_code = 
+    update_field_data_in_FFS ( &DbmMaster[db_handle].FFSFileHandle,
+                               db_handle,
+                               fld_ctr,
+                               field_data,
+                               RecordBitMap_OFFSET,
+                               ( T_DB_FIELD_RECORD_SIZE - RecordBitMap_OFFSET ) );
+
+
+  if( db_ret_code NEQ DB_OK )
+  {
+    DB_MFREE( field_data );
+    DB_RETURN( db_ret_code )
+  }
+
+  DB_MFREE( field_data );
+ /* RecordBitMap to be updated only for new records */
+    db_set_bit_in_bitmap (tmp_ptrFieldRecord->RecordBitMap,
+                          record_num,
+                          flag);
+
+    ++tmp_ptrFieldRecord -> UsedRecords;
+
+    tmp_ptrFieldRecord -> NextRecordNum =  
+        ( (record_num + 1) > tmp_ptrFieldRecord -> NextRecordNum ) ?
+          (record_num + 1) : tmp_ptrFieldRecord -> NextRecordNum ; 
+	
+     DB_VALUE_RETURN( record_num )
+}
+
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+    PURPOSE : Creates or updates a sort index for a given (database, field)
+*/
+T_DB_CODE db_create_index ( int          db_handle, 
+                            USHORT       field_id, 
+                            UBYTE        sort_index, 
+                            T_COMP_FUNC  compare_function, 
+                            ULONG        flags )
+{
+
+  return internal_db_sort( db_handle,
+                           field_id,
+                           sort_index,
+                           compare_function,
+                           flags );
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: db_update_index      |
++--------------------------------------------------------------------+
+
+    PURPOSE : Sort the list for newly added/deleted records (uses incremental
+              sort i.e. add the element at the right place)
+*/
+T_DB_CODE db_update_index ( int          db_handle, 
+                            USHORT       field_id, 
+                            UBYTE        sort_index, 
+                            T_COMP_FUNC  compare_function, 
+                            ULONG        flags )
+{
+
+  return internal_db_sort( db_handle,
+                           field_id,
+                           sort_index,
+                           compare_function,
+                           flags );
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: db_get_phy_from_idx  |
++--------------------------------------------------------------------+
+
+    PURPOSE : Translates a logical entry within a given sort index to the 
+              physical record number
+*/
+T_DB_CODE db_get_phy_from_idx ( int    db_handle, 
+                                USHORT field_id, 
+                                UBYTE  sort_index, 
+                                USHORT order_num )
+{
+  T_DB_CODE          db_ret_code;
+  UBYTE              fld_ctr,
+                     sort_index_ctr;
+  T_DBM_FIELDRECORD* tmp_ptrFieldRecord;
+  char              sort_file[FILENAME_LEN];
+
+
+  TRACE_FUNCTION("db_get_phy_from_idx()");
+
+  /* DBM_State check */
+  DBM_State_check;
+
+  /* db_handle check */
+  db_ret_code = db_handle_check( db_handle );
+  if( db_ret_code NEQ DB_OK )
+    DB_RETURN( db_ret_code );
+
+  /*	field id search; if field not found, return error DB_INVALID_FIELD */
+  fld_ctr = field_id_search( db_handle, field_id );
+  if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles )
+    DB_RETURN( DB_INVALID_FIELD );
+
+  tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord + fld_ctr;
+
+  /* sanity check on order_num */
+  if( ( order_num > tmp_ptrFieldRecord -> NumOfRecords ) OR
+      ( order_num EQ 0 ) )
+    DB_RETURN( DB_FAIL );  /* may be we can return 0xFF => no record for it ! */
+
+  /* Search given sort_index in SortIndexList for above field_id; 
+     if not found, return DB_INVALID_INDEX. */
+  for( sort_index_ctr = 0; sort_index_ctr < MAX_NUM_OF_SORT_INDEXS; ++sort_index_ctr )
+  {
+    if( tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] EQ sort_index )
+      break;
+  }
+
+  if( sort_index_ctr EQ MAX_NUM_OF_SORT_INDEXS )
+    DB_RETURN( DB_INVALID_INDEX );
+
+  /* Check if we already have sorted list in RAM structure SortedLists */
+
+  if( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] EQ NULL )
+  { 
+    /* If no, populate the sorted list from file, 
+       "<DBDirectory>/UD_<field_id>_sort_<sort_index>". 
+       Sorted lists are freed in db_flush */
+
+/* Implements Measure#32: Row 1177 */
+    sprintf( sort_file, 
+             format_sUDd_sortd_str, 
+             (char *)DbmMaster[db_handle].DBDirectory, 
+             tmp_ptrFieldRecord -> FieldID,
+             sort_index );
+
+    db_ret_code = 
+      populate_sorted_list_from_FFS (  
+#ifdef FFS_CLOSE_BEFORE_OPEN
+                                      db_handle,
+#endif
+                                      sort_file,
+                                      tmp_ptrFieldRecord -> NumOfRecords,
+                                      &(tmp_ptrFieldRecord -> SortedLists[sort_index_ctr]) );
+    if( db_ret_code NEQ DB_OK )
+      DB_RETURN( db_ret_code );
+    
+  } /* if we have sort list */
+
+  /* Get (physical) record number for given order_num from sorted list. */
+  DB_VALUE_RETURN((T_DB_CODE)tmp_ptrFieldRecord -> SortedLists[sort_index_ctr][order_num - 1] )
+
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: db_flush             |
++--------------------------------------------------------------------+
+
+    PURPOSE : Flush all internal data structures of the database described by 
+              db_handle
+*/
+T_DB_CODE db_flush ( int db_handle)
+{
+  T_DB_CODE  db_ret_code;
+  UBYTE      clean_byte, /* Coded as in the FFS */
+        fld_ctr,
+        i;
+  T_DBM_FIELDRECORD* tmp_ptrFieldRecord;
+
+  char sort_file[FILENAME_LEN];
+
+  T_FFS_STAT ffs_file_stat;
+  T_FFS_SIZE ffs_ret_code;
+
+  TRACE_FUNCTION("db_flush()");
+
+  /* DBM_State check */
+  DBM_State_check;
+
+  /* db_handle check */
+  db_ret_code = db_handle_check( db_handle );
+  if( db_ret_code NEQ DB_OK )
+    DB_RETURN( db_ret_code );
+
+  /* Clear "clean" in "~/dbm/DD_<db_handle>" for fields. 
+     after ffs updation, update RAM data */
+
+  clean_byte = FFS_CLEAN;
+
+  /* Update the affected field records */
+
+#ifdef FFS_CLOSE_BEFORE_OPEN
+  db_close_user_field_files( db_handle );
+#endif
+
+  tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord;
+
+  for( fld_ctr = 0; fld_ctr < DbmMaster[db_handle].NumOfFiles; ++fld_ctr )
+  {
+    if( tmp_ptrFieldRecord -> FieldID EQ INVALID_FIELD_ID ) /* if not valid field id */
+    {
+      ++tmp_ptrFieldRecord;   /* next field */
+      continue;
+    }
+
+    /* Clear file handles */
+#ifndef FFS_CLOSE_BEFORE_OPEN
+
+    if (IS_FD_VALID(tmp_ptrFieldRecord->FFSFileHandle))
+    {
+      DB_FFS_CLOSE( tmp_ptrFieldRecord -> FFSFileHandle );
+      tmp_ptrFieldRecord -> FFSFileHandle = INVALID_FD;
+    }
+
+#else
+    /* Done it closing before for loop */
+#endif
+
+    /* Write sort lists to FFS and clear (free memory) sort lists */
+    for( i = 0; i < MAX_NUM_OF_SORT_INDEXS; ++i )
+    {
+      if( tmp_ptrFieldRecord -> SortedLists[i] NEQ NULL )
+      {
+        /* currently I am not removing unused entries in sort list */
+        /* Write sorted lists to "<DBDirectory>/UD_<field_id>_sort_<sort_index>". */
+
+/* Implements Measure#32: Row 1193 */
+        sprintf( sort_file, 
+                 format_sUDd_sortd_str, 
+                 (char *)DbmMaster[db_handle].DBDirectory, 
+                 tmp_ptrFieldRecord -> FieldID,
+                 tmp_ptrFieldRecord -> SortIndexList[i] );
+
+        /* writing sorted lists to FFS s required in two cases
+           1) the field is not clean and/or
+           2) sort file does not exist, but we have sort list (happen during 
+               bootup time with zero records)
+         */
+        
+        ffs_ret_code = ffs_stat( sort_file, &ffs_file_stat );
+
+        if( ( ffs_ret_code NEQ EFFS_OK )      AND
+            ( ffs_ret_code NEQ EFFS_NOTFOUND ) )
+        {
+          LastFFS_ReturnCode = ffs_ret_code;
+          DB_MFREE( tmp_ptrFieldRecord -> SortedLists[i] );
+          tmp_ptrFieldRecord -> SortedLists[i] = NULL;
+          DB_RETURN( DB_FAIL_FS )
+        }
+
+        if( ( NOT tmp_ptrFieldRecord -> Clean )  OR /* not clean (consistent) */
+            ( ffs_ret_code EQ EFFS_NOTFOUND )    )  /* file does not exist */
+        {
+          db_ret_code =
+            write_sorted_list_to_FFS ( 
+#ifdef FFS_CLOSE_BEFORE_OPEN
+                                       db_handle,
+#endif
+                                       sort_file,
+                                       tmp_ptrFieldRecord -> NumOfRecords,
+                                       tmp_ptrFieldRecord -> SortedLists[i] );
+
+          if( db_ret_code NEQ DB_OK )
+          {
+            DB_MFREE( tmp_ptrFieldRecord -> SortedLists[i] );
+            tmp_ptrFieldRecord -> SortedLists[i] = NULL;
+            DB_RETURN( db_ret_code )
+          }
+        }
+
+        /* writing in sort file is over */
+        DB_MFREE( tmp_ptrFieldRecord -> SortedLists[i] );
+        tmp_ptrFieldRecord -> SortedLists[i] = NULL;
+      }
+    }
+
+    if( tmp_ptrFieldRecord -> Clean ) /* is it clean (consistent) ? */
+    {
+      ++tmp_ptrFieldRecord;   /* next field */
+      continue;
+    }
+
+    /* Clear "clean" in "~/dbm/DD_<db_handle>" if not clean  */
+
+    db_ret_code = 
+      update_field_data_in_FFS ( &DbmMaster[db_handle].FFSFileHandle,
+                                 db_handle,
+                                 fld_ctr,
+                                 &clean_byte,
+                                 ( T_DB_FIELD_RECORD_SIZE - 1 ),
+                                 1 );       /* "Clean" contained in last one byte */
+
+    if( db_ret_code NEQ DB_OK )
+    {
+      /* this leaves out FFS and RAM in consistent state, 
+         this is ok since FFS is in correct state for some of fields ! */
+      DB_RETURN( db_ret_code )
+    }
+
+    tmp_ptrFieldRecord->Clean = TRUE;
+
+    ++tmp_ptrFieldRecord;   /* next field */
+
+  } /* for all field records */
+
+  if (IS_FD_VALID(DbmMaster[db_handle].FFSFileHandle))
+  {
+    DB_FFS_CLOSE( DbmMaster[db_handle].FFSFileHandle );
+    DbmMaster[db_handle].FFSFileHandle = INVALID_FD;
+  }
+
+  /* updation of FFS is over */
+
+  /* Update corresponding "clean" field for database in RAM data structures, 
+     also DBState = OPEN */
+  DbmMaster[db_handle].Clean = TRUE;
+  DbmMaster[db_handle].DBState = OPEN;
+
+  /* done */
+  DB_RETURN( DB_OK )
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: db_search            |
++--------------------------------------------------------------------+
+
+    PURPOSE : Searches for an entry within a given database and a given file
+*/
+int db_search ( int               db_handle, 
+                USHORT            field_id, 
+                UBYTE             sort_index, 
+                SHORT*            order_num,
+                T_SEARCH_FUNC     search_function, 
+                ULONG             flags, 
+                const UBYTE*      search_tag )
+{
+  T_DB_CODE  db_ret_code;
+  UBYTE fld_ctr,
+        sort_index_ctr;
+  T_DBM_FIELDRECORD* tmp_ptrFieldRecord;
+
+  char sort_file[FILENAME_LEN];              
+
+  int record_num = 0,
+      index_num ;
+
+  TRACE_FUNCTION("db_search()");
+
+  /* DBM_State check */
+  DBM_State_check;
+
+  /* db_handle check */
+  db_ret_code = db_handle_check( db_handle );
+  if( db_ret_code NEQ DB_OK )
+    DB_RETURN( db_ret_code );
+
+  /*	field id search; if field not found, return error DB_INVALID_FIELD */
+  fld_ctr = field_id_search( db_handle, field_id );
+  if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles )
+    DB_RETURN( DB_INVALID_FIELD );
+
+  tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord + fld_ctr;
+
+  if( sort_index EQ 0 )
+  {
+    /* If sort_index is zero, 
+        o	Do linear search using RecordBitMap, search/comparison function is given by caller.
+        o	If search is successful, return the record number.
+        o	Otherwise return DB_RECORD_NOT_FOUND. */
+
+    /* Sanity check */
+    if( (*order_num) > tmp_ptrFieldRecord -> NumOfRecords )
+      DB_RETURN( DB_FAIL );
+
+    /* search from next record,
+       search_node->top would be zero for fresh search */
+
+    for (record_num = *order_num + 1; 
+         record_num <= tmp_ptrFieldRecord->NumOfRecords; 
+         record_num++)
+    {
+      if (db_get_bit_in_bitmap (tmp_ptrFieldRecord->RecordBitMap, record_num))
+      {
+        /* ok, this is a valid record */
+
+        if( search_function( flags,
+                             search_tag, 
+                             db_handle, 
+                             field_id,
+                             (UBYTE)record_num ) 
+            EQ 0 )  /* yeah, "EQ 0" is success */
+        {
+          /* found it ! */
+          *order_num = record_num; /* for next search */
+          DB_VALUE_RETURN( record_num )
+        }
+      }
+    } /* for bytes in bitmap */
+
+    /* record not found */
+    DB_RETURN( DB_RECORD_NOT_FOUND )
+
+  } 
+
+  /* If sort_index is not zero, search using sorted list */
+ else 
+  {
+    /* Search given sort_index in SortIndexList for above field_id; 
+     if not found, return DB_INVALID_INDEX. */
+   for( sort_index_ctr = 0; sort_index_ctr < MAX_NUM_OF_SORT_INDEXS; ++sort_index_ctr )
+   {
+     if( tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] EQ sort_index )
+       break;
+   }
+
+   if( sort_index_ctr EQ MAX_NUM_OF_SORT_INDEXS )
+     DB_RETURN( DB_INVALID_INDEX );
+
+   if( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] EQ NULL )
+   { 
+     /* If no, populate the sorted list from file, 
+         "<DBDirectory>/UD_<field_id>_sort_<sort_index>". 
+         Sorted lists are freed in db_flush */
+
+/* Implements Measure#32: Row 1193 */
+     sprintf( sort_file, 
+               format_sUDd_sortd_str, 
+               (char *)DbmMaster[db_handle].DBDirectory, 
+               tmp_ptrFieldRecord -> FieldID,
+               sort_index );
+
+     db_ret_code = 
+       populate_sorted_list_from_FFS (  
+
+#ifdef FFS_CLOSE_BEFORE_OPEN
+                                        db_handle,
+#endif
+                                        sort_file,
+                                        tmp_ptrFieldRecord -> NumOfRecords,
+                                        &(tmp_ptrFieldRecord -> SortedLists[sort_index_ctr]) );
+
+     if( db_ret_code NEQ DB_OK )
+        DB_RETURN( db_ret_code );
+
+   }
+
+    /* (Binary) search the sorted list, search/compare function is given by caller. 
+       o	If search is successful, return the record number.
+       o	Otherwise return DB_RECORD_NOT_FOUND */
+
+
+   index_num = 
+            db_binary_search( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr],
+                   tmp_ptrFieldRecord -> UsedRecords,
+                   order_num,
+                   search_function, 
+                   flags, 
+                   search_tag,
+                   db_handle, 
+                   field_id );
+
+   if( index_num EQ SEARCH_FAILED )
+      DB_RETURN( DB_RECORD_NOT_FOUND );
+
+    DB_VALUE_RETURN( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr][index_num - 1] )
+                   
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: db_delete_record     |
++--------------------------------------------------------------------+
+
+    PURPOSE : Delete a record in the given field of the given database
+*/
+T_DB_CODE db_delete_record ( int    db_handle,
+                             USHORT field_id, 
+                             USHORT record_num )
+{
+  T_DB_CODE  db_ret_code;
+  UBYTE fld_ctr;
+  T_DBM_FIELDRECORD* tmp_ptrFieldRecord;
+  UBYTE*  field_data;
+
+  TRACE_FUNCTION("db_delete_record()");
+
+  /* DBM_State check */
+  DBM_State_check;
+
+  /* db_handle check */
+  db_ret_code = db_handle_check( db_handle );
+  if( db_ret_code NEQ DB_OK )
+    DB_RETURN( db_ret_code );
+
+  /*	field id search; if field not found, return error DB_INVALID_FIELD */
+  fld_ctr = field_id_search( db_handle, field_id );
+  if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles )
+    DB_RETURN( DB_INVALID_FIELD );
+
+  tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord + fld_ctr;
+
+  /* Using RecordBitMap, check whether record_num exists; 
+     if it does not exist, return DB_OK. */
+
+  if (!db_get_bit_in_bitmap (tmp_ptrFieldRecord->RecordBitMap, record_num))
+  {
+    /* if record does *not* exist */
+    DB_RETURN( DB_OK )
+  }
+
+  /* Update "Clean" and "RecordBitMap" fields in "~/dbm/DD_<db_handle>" */
+
+  /* create the field data that is to be written */
+
+  DB_MALLOC( field_data, ( T_DB_FIELD_RECORD_SIZE - RecordBitMap_OFFSET ) );
+  memset( field_data, 0, ( T_DB_FIELD_RECORD_SIZE - RecordBitMap_OFFSET ) );
+  memcpy( field_data, tmp_ptrFieldRecord -> RecordBitMap, RECORD_BITMAP_SIZE );
+
+  /* updating RecordBitMap */
+  db_set_bit_in_bitmap (field_data, record_num, FALSE);
+
+  /* clean is reset in memset, so no processing for it 
+     (in case of non-tracked database, anyway we ignore it ! */ 
+
+  db_ret_code = 
+    update_field_data_in_FFS ( &DbmMaster[db_handle].FFSFileHandle,
+                               db_handle,
+                               fld_ctr,
+                               field_data,
+                               RecordBitMap_OFFSET,
+                               ( T_DB_FIELD_RECORD_SIZE - RecordBitMap_OFFSET ) );
+
+  if( db_ret_code NEQ DB_OK )
+  {
+    DB_MFREE( field_data );
+    DB_RETURN( db_ret_code )
+  }
+
+  DB_MFREE( field_data );
+  /* updation of DD_<db_handle> is over */
+
+  /* Update corresponding "Clean" and "RecordBitMap" fields in RAM data structures, 
+     also update DBState (as IN_USE) and decrement UsedRecords. */
+
+  tmp_ptrFieldRecord->Clean = FALSE;
+
+  /* updating RecordBitMap */
+  db_set_bit_in_bitmap (tmp_ptrFieldRecord->RecordBitMap, record_num, FALSE);
+
+  /* get the sort lists in RAM from FFS */
+  get_sort_lists_from_FFS( (UBYTE)db_handle, fld_ctr );
+
+  /* delete in available sort lists
+     yeah, we call it *before* updating UsedRecords */
+  delete_in_sort_lists( (UBYTE)db_handle, fld_ctr, (UBYTE)record_num );
+
+  --tmp_ptrFieldRecord -> UsedRecords;
+
+  DbmMaster[db_handle].Clean = FALSE;
+  DbmMaster[db_handle].DBState = IN_USE;
+
+  /* history log updation */
+
+  return update_history_log( db_handle, field_id, record_num );
+
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: db_read_record       |
++--------------------------------------------------------------------+
+
+    PURPOSE : Read length bytes at offset from the record in given (database, field)
+*/
+int db_read_record ( int     db_handle, 
+                     USHORT  field_id, 
+                     USHORT  record_num, 
+                     USHORT  offset, 
+                     USHORT  length, 
+                     UBYTE*  record_buffer )
+{
+  T_DB_CODE  db_ret_code;
+  UBYTE fld_ctr;
+  char  user_field_file[FILENAME_LEN];
+  T_DBM_FIELDRECORD* tmp_ptrFieldRecord;
+
+  TRACE_FUNCTION("db_read_record()");
+
+  /* DBM_State check */
+  DBM_State_check;
+
+  /* db_handle check */
+  db_ret_code = db_handle_check( db_handle );
+  if( db_ret_code NEQ DB_OK )
+    DB_RETURN( db_ret_code );
+
+  /*	field id search; if field not found, return error DB_INVALID_FIELD */
+  fld_ctr = field_id_search( db_handle, field_id );
+  if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles )
+    DB_RETURN( DB_INVALID_FIELD );
+
+  /* Using RecordBitMap, check whether record_num exists; 
+     if it does not exist, return DB_EMPTY_RECORD. */
+
+  tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord + fld_ctr;
+
+  if (!db_get_bit_in_bitmap (tmp_ptrFieldRecord -> RecordBitMap, record_num))
+  {
+    /* if record does *not* exist */
+    DB_RETURN( DB_EMPTY_RECORD )
+  }
+
+  /* Check if record exceeds the record size (i.e. offset + length > record size); 
+     if it exceeds, return error DB_INVALID_SIZE */
+  if( (offset + length) > 
+      tmp_ptrFieldRecord -> RecordSize )
+    DB_RETURN( DB_INVALID_SIZE );
+
+  /* Check if FFS file is already opened using FFSFileHandle, part of field record. 
+     If it is not yet opened, open the FFS file and update FFSFileHandle. 
+     This is taken care in read_user_record_from_FFS below. */
+
+  /* Read record_num from "<DBDirectory>/UD_<field_id>"
+     Put "length" number of bytes from "offset" in buffer. (assuming that 
+     buffer contain enough memory i.e. caller should take care of allocating 
+     enough memory space for buffer) */
+
+  /* User data file name is "<DBDirectory>/UD_<field_id>" */
+
+/* Implements Measure#32: Row 1200 */
+  sprintf( user_field_file, 
+           format_sUDd_str, 
+           (char *)DbmMaster[db_handle].DBDirectory, 
+           tmp_ptrFieldRecord -> FieldID );
+
+      /* Implements Measure # 211 */
+      db_ret_code = 
+        read_write_user_record_from_FFS ( user_field_file,
+
+#ifndef FFS_CLOSE_BEFORE_OPEN
+                                &(tmp_ptrFieldRecord -> FFSFileHandle),
+#else
+                                db_handle,
+                                fld_ctr,
+                                &Dummy_FFSFileHandle,
+#endif
+                                (UBYTE)record_num,
+                                tmp_ptrFieldRecord -> RecordSize,
+                                offset,
+                                length,
+                                          record_buffer,
+                                          FFS_O_RDONLY );
+
+
+  if( db_ret_code NEQ DB_OK )
+    DB_RETURN( db_ret_code );
+
+  DB_VALUE_RETURN( record_num )
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: db_remove            |
++--------------------------------------------------------------------+
+
+    PURPOSE : Remove a database. The database must not be in use.
+*/
+T_DB_CODE db_remove ( const char* directory )
+{
+  int db_handle;
+
+  UBYTE db_ctr,
+        fld_ctr;
+
+  T_DB_CODE          db_ret_code;
+
+  UBYTE* dbm_data;
+  UBYTE field_file[FILENAME_LEN];
+
+
+ 
+  TRACE_FUNCTION("db_remove()");
+
+  /* DBM_State check */
+  DBM_State_check;
+
+  /* Search for "directory" in DbmMaster
+     If not found, return DB_INVALID_DB */
+
+  for( db_ctr = 0; db_ctr < MAX_DBs; ++db_ctr )
+  {
+    if ( DbmMaster[db_ctr].DBState NEQ UNUSED_ENTRY )
+    {
+        if( memcmp( DbmMaster[db_ctr].DBDirectory, 
+                    directory, 
+                    strlen(directory) ) EQ 0 )
+          break;
+    }
+  }
+
+  if( db_ctr EQ MAX_DBs )
+    DB_RETURN( DB_INVALID_DB );
+
+  db_handle = db_ctr;
+
+  /* If DBState for found database in DbmMaster is OPEN or IN_USE, return error DB_IN_USE */
+
+  if( ( DbmMaster[db_ctr].DBState EQ OPEN ) OR
+      ( DbmMaster[db_ctr].DBState EQ IN_USE ) )
+     DB_RETURN( DB_IN_USE );
+
+
+  /* Delete all files under directory "<DBDirectory>" (DBDirectory = directory) */
+
+  for( fld_ctr = 0; fld_ctr < DbmMaster[db_handle].NumOfFiles; ++fld_ctr )
+  {
+    db_ret_code = remove_field_from_FFS( (UBYTE)db_handle, fld_ctr );
+
+    if( db_ret_code NEQ DB_OK )
+      DB_RETURN( db_ret_code );
+  }
+
+  /* Delete the DBDirectory */
+  db_ret_code = delete_file_dir_from_FFS ( (const char*)DbmMaster[db_handle].DBDirectory );
+
+  if( db_ret_code NEQ DB_OK )
+    DB_RETURN( db_ret_code );
+  
+  /* Delete Field file = DD_<pos. in DD_master> */
+
+/* Implements Measure#32: Row 1195, 1203 */
+  sprintf( (char*)field_file, format_sDDd_str, db_dir, db_ctr);    
+
+  db_ret_code = delete_file_dir_from_FFS ( (const char*)field_file );
+
+  if( db_ret_code NEQ DB_OK )
+    DB_RETURN( db_ret_code );
+
+  /* Update FFS data i.e. file, "~/dbm/DD_master" */
+
+  /* prepare the dbm data and write */
+
+  DB_MALLOC( dbm_data, T_DB_MASTER_RECORD_SIZE );
+  memset( dbm_data, 0xFF, T_DB_MASTER_RECORD_SIZE );
+
+/* Implements Measure#32: Row 1201 */
+  db_ret_code = 
+    update_dbm_data_in_FFS ( db_master_file,
+                             (UBYTE) db_handle,   /* to supress warning */
+                             T_DB_MASTER_RECORD_SIZE,
+                             dbm_data,
+                             0,
+                             T_DB_MASTER_RECORD_SIZE );
+
+  if( db_ret_code NEQ DB_OK )
+  {
+    DB_MFREE( dbm_data );
+    DB_RETURN( db_ret_code )
+  }
+
+  DB_MFREE( dbm_data );
+
+  /* updation of DD_master done */
+
+  /* Free the memory for field records. 
+     Update this entry in DbmMaster as unused. (DBState = UNUSED_ENTRY). 
+     Also, decrement UsedDBs. */
+
+  DB_MFREE( DbmMaster[db_handle].ptrFieldRecord );
+
+  DbmMaster[db_handle].DBState = UNUSED_ENTRY;
+
+  --UsedDBs;
+
+  /* everything ok ! */
+  DB_RETURN( DB_OK )
+
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: db_close             |
++--------------------------------------------------------------------+
+
+    PURPOSE : Close a database; if in use, it flushes it before closing it.
+*/
+T_DB_CODE db_close ( int db_handle )
+{
+  TRACE_FUNCTION("db_close()");
+
+  /* DBM_State check */
+  DBM_State_check;
+
+  /* Check for db_handle range */
+  if( db_handle >= MAX_DBs )
+    DB_RETURN( DB_INVALID_DB );
+
+  /* If DBState for db_handleth position in DbmMaster is 
+      o	UNUSED_ENTRY, return error DB_INVALID_DB
+      o	CLOSED, return DB_OK.
+      o	OPEN, update DBState as CLOSED and return DB_OK.
+      o	IN_USE, call db_flush, update DBState as CLOSED and return DB_OK */
+
+  switch( DbmMaster[db_handle].DBState )
+  {
+    case UNUSED_ENTRY: DB_RETURN( DB_INVALID_DB )
+
+    case CLOSED: DB_RETURN( DB_OK )
+
+    case OPEN:  
+    case IN_USE:  {
+                    db_flush( db_handle );
+                    DbmMaster[db_handle].DBState = CLOSED; 
+                    DB_RETURN( DB_OK )
+                  }
+
+    default: break;
+  }
+  DB_RETURN( DB_FAIL )
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: db_exit              |
++--------------------------------------------------------------------+
+
+    PURPOSE : Shutdown the data base
+*/
+void db_exit ( void )
+{
+  /* It is assumed as "forced" exit and so no error would be 
+     raised even if database is in use. Also, here we will not 
+     delete the database, but just sync the database and free 
+     the RAM structures.
+
+    1)	Call db_flush for all databases present in DbmMaster.
+    2)	Free the memory for field records for all databases.
+    3)	Update all entries in DbmMaster as unused (this step is not required)
+    4)	Set DBM_State as DBM_NOT_INITIALISED. */
+
+  UBYTE db_ctr;
+
+  for ( db_ctr = 0; db_ctr < MAX_DBs; ++db_ctr )
+  {
+    if( DbmMaster[db_ctr].DBState EQ UNUSED_ENTRY )
+      continue;
+
+    db_close( db_ctr );
+
+    DB_MFREE( DbmMaster[db_ctr].ptrFieldRecord );
+
+    DbmMaster[db_ctr].DBState = UNUSED_ENTRY;
+
+  }
+
+  DBM_State = DBM_NOT_INITIALISED;
+
+  UsedDBs = 0;
+
+  return;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: db_remove_field      |
++--------------------------------------------------------------------+
+
+    PURPOSE : Delete field in given database
+*/
+T_DB_CODE db_remove_field ( int    db_handle, 
+                            USHORT field_id )
+{
+  UBYTE fld_ctr;
+  T_DB_CODE db_ret_code;
+  UBYTE* field_data;
+  T_DBM_FIELDRECORD* tmp_ptrFieldRecord;
+
+  TRACE_FUNCTION("db_remove_field()");
+
+  TRACE_EVENT_P1 ("Removing field %04X", field_id);
+
+  /* DBM_State check */
+  DBM_State_check;
+
+  /* db_handle check */
+  db_ret_code = db_handle_check( db_handle );
+  if( db_ret_code NEQ DB_OK )
+    DB_RETURN( db_ret_code );
+
+  /*	field id search; if field id not found, return error DB_INVALID_FIELD */
+  fld_ctr = field_id_search( db_handle, field_id );
+  if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles )
+    DB_RETURN( DB_INVALID_FIELD );
+
+  tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord + fld_ctr;
+
+  /* >>>HM 4-Sep-2006
+   It would be nice if we would close here only the file
+   which is opened and not everything, but such a solution is impossible
+   within the work environment at the customer.*/
+#ifdef FFS_CLOSE_BEFORE_OPEN
+  db_close_user_field_files( db_handle );
+#endif
+/*   <<< HM 4-Sep-2006 */
+
+#ifndef FFS_CLOSE_BEFORE_OPEN
+  /* Check if FFS file is open using FFSFileHandle, part of field record; 
+     if so, return error DB_IN_USE. */
+  if (IS_FD_VALID(tmp_ptrFieldRecord->FFSFileHandle)
+  {
+    TRACE_ERROR ("File handle in use");
+    DB_RETURN( DB_IN_USE );
+  }
+#else
+  if( db_status_user_field_file( db_handle, fld_ctr ) EQ OPENED_FOR_WRITE )
+  {
+    TRACE_ERROR ("File handle in use for writing");
+    DB_RETURN( DB_IN_USE )
+  }
+#endif
+
+  /* Remove file "<DBDirectory>/UD_<field_id>" */
+
+  db_ret_code = remove_field_from_FFS( (UBYTE)db_handle, fld_ctr );
+
+  if( db_ret_code NEQ DB_OK )
+  {
+    TRACE_ERROR ("Could not remove user field file");
+    DB_RETURN( db_ret_code )
+  }
+
+  /* Update "~/dbm/DD_<db_handle>" for removed field id. */
+
+  /* create the field data that is to be written */
+
+  DB_MALLOC( field_data, ( T_DB_FIELD_RECORD_SIZE - RecordBitMap_OFFSET ) );
+  memset( field_data, 0xFF, ( T_DB_FIELD_RECORD_SIZE - RecordBitMap_OFFSET ) );
+
+  db_ret_code = 
+    update_field_data_in_FFS ( &DbmMaster[db_handle].FFSFileHandle,
+                               db_handle,
+                               fld_ctr,
+                               field_data,
+                               RecordBitMap_OFFSET,
+                               ( T_DB_FIELD_RECORD_SIZE - RecordBitMap_OFFSET ) );
+
+  if( db_ret_code NEQ DB_OK )
+  {
+    TRACE_ERROR ("Could not update master file");
+    DB_MFREE( field_data );
+    DB_RETURN( db_ret_code )
+  }
+
+  DB_MFREE( field_data );
+  /* updation of DD_<db_handle> is over */
+
+  /* update in RAM */
+
+  tmp_ptrFieldRecord -> FieldID = INVALID_FIELD_ID;
+
+  /* One field less */
+  DbmMaster[db_handle].UsedFiles--; // HM 5-Sep-2006 Midnight patch ADN FDN switch
+
+  DB_RETURN( DB_OK )
+
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: db_read_change_log   |
++--------------------------------------------------------------------+
+
+    PURPOSE : Get an information about the changed records since the last 
+              call of this function
+*/
+T_DB_CODE db_read_change_log ( int           db_handle, 
+                               T_DB_CHANGED* changed)
+{
+  T_DB_CODE db_ret_code;
+  TRACE_FUNCTION("db_read_change_log()");
+
+  /* DBM_State check */
+  DBM_State_check;
+
+  /* db_handle check */
+  db_ret_code = db_handle_check( db_handle );
+  if( db_ret_code NEQ DB_OK )
+    DB_RETURN( db_ret_code );
+
+  /* Copy contents of internal history log to HistoryRecord */
+  *changed = DB_History_log;  /* This would work ?? */
+   
+  /* Clear internal history log. */
+  DB_History_log.entries = 0; /* this is enough for clearing history log ! */
+
+  /* done */
+  DB_RETURN( DB_OK )
+
+}
+
+#ifdef _SIMULATION_ /* HM 19-Oct-2006: Currently not used but to be kept */
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: db_remove_index      |
++--------------------------------------------------------------------+
+
+    PURPOSE : Removes a sort index
+*/
+T_DB_CODE db_remove_index ( int    db_handle,
+                            USHORT field_id,
+                            UBYTE  sort_index )
+{
+  T_DB_CODE db_ret_code;
+  UBYTE     fld_ctr,sort_index_ctr;
+  T_DBM_FIELDRECORD* tmp_ptrFieldRecord;
+  char sort_file[FILENAME_LEN];              
+  UBYTE* field_data;
+   
+  TRACE_FUNCTION("db_remove_index()");
+
+  /* DBM_State check */
+  DBM_State_check;
+
+  /* db_handle check */
+  db_ret_code = db_handle_check( db_handle );
+  if( db_ret_code NEQ DB_OK )
+    DB_RETURN( db_ret_code );
+
+  /*	field id search; if field not found, return error DB_INVALID_FIELD */
+  fld_ctr = field_id_search( db_handle, field_id );
+  if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles )
+    DB_RETURN( DB_INVALID_FIELD );
+
+  tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord + fld_ctr;
+
+  /* Search given sort_index in SortIndexList for above field_id; 
+     if not found, return DB_INVALID_INDEX. */
+  for( sort_index_ctr = 0; sort_index_ctr < MAX_NUM_OF_SORT_INDEXS; ++sort_index_ctr )
+  {
+    if( tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] EQ sort_index )
+      break;
+  }
+
+  if( sort_index_ctr EQ MAX_NUM_OF_SORT_INDEXS )
+    DB_RETURN( DB_INVALID_INDEX );
+
+  /* Remove file, "<DBDirectory>/UD_<field_id>_sort_<sort_index>" */
+
+/* Implements Measure#32: Row 1193 */
+  sprintf( sort_file, 
+           format_sUDd_sortd_str, 
+           DbmMaster[db_handle].DBDirectory, 
+           tmp_ptrFieldRecord -> FieldID,
+           tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] );
+
+  db_ret_code = delete_file_dir_from_FFS ( sort_file );
+
+  if( db_ret_code NEQ DB_OK )
+    DB_RETURN( db_ret_code );        
+
+  /* Update file , "~/dbm/DD_<db_handle>" for SortIndexes. */
+
+  /* create the field data that is to be written */
+
+  DB_MALLOC( field_data, MAX_NUM_OF_SORT_INDEXS );
+  memcpy( field_data, tmp_ptrFieldRecord -> SortIndexList, MAX_NUM_OF_SORT_INDEXS );
+
+  field_data[sort_index_ctr] = INVALID_SORT_INDEX;
+
+  db_ret_code = 
+    update_field_data_in_FFS ( &DbmMaster[db_handle].FFSFileHandle,
+                               db_handle,
+                               fld_ctr,
+                               field_data,
+                               SortIndexList_OFFSET,
+                               MAX_NUM_OF_SORT_INDEXS );
+  if( db_ret_code NEQ DB_OK )
+  {
+    DB_MFREE( field_data );
+    DB_RETURN( db_ret_code )
+  }
+
+  DB_MFREE( field_data );
+  /* updation of DD_<db_handle> is over */
+
+  /* Update corresponding RAM structure i.e. DbmFieldRecord 
+     Check if we have sort list corresponding to this sort index; if so, free it. */
+
+  tmp_ptrFieldRecord -> SortIndexList[sort_index_ctr] = INVALID_SORT_INDEX;
+  if( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] NEQ NULL )
+  {
+    DB_MFREE( tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] );
+    tmp_ptrFieldRecord -> SortedLists[sort_index_ctr] = NULL;
+  }
+
+  DB_RETURN( DB_OK )
+}
+#endif /* #ifdef _SIMULATION_ */
+
+#ifdef _SIMULATION_ /* HM 19-Oct-2006: Currently not used but to be kept */
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: db_field_changed     |
++--------------------------------------------------------------------+
+
+    PURPOSE : Check whether a database field has been changed since last 
+              db_flush().
+*/
+T_DB_CODE db_field_changed ( int    db_handle, 
+                             USHORT field_id,
+                             BOOL*  changed )
+{
+  UBYTE fld_ctr;
+  T_DB_CODE db_ret_code;
+
+  TRACE_FUNCTION("db_field_changed()");
+
+  /* DBM_State check */
+  DBM_State_check;
+
+  /* db_handle check */
+  db_ret_code = db_handle_check( db_handle );
+  if( db_ret_code NEQ DB_OK )
+    DB_RETURN( db_ret_code );
+
+  /*	field id search; if field not found, return error DB_INVALID_FIELD */
+  fld_ctr = field_id_search( db_handle, field_id );
+  if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles )
+    DB_RETURN( DB_INVALID_FIELD );
+
+  /* Check "Clean" field in field record; 
+     a) if (Clean = true), changed = false. */
+
+  *changed = NOT DbmMaster[db_handle].ptrFieldRecord[fld_ctr].Clean;
+
+  DB_RETURN( DB_OK )
+}
+#endif /* #ifdef _SIMULATION_ */
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: db_record_empty      |
++--------------------------------------------------------------------+
+
+    PURPOSE : Check whether a database field is empty. The result is 
+              given to the caller in the *empty variable
+*/
+T_DB_CODE db_record_empty ( int    db_handle,
+                            USHORT field_id,
+                            USHORT record_num,
+                            BOOL*  empty )
+{
+  UBYTE fld_ctr;
+  T_DB_CODE db_ret_code;
+  T_DBM_FIELDRECORD* tmp_ptrFieldRecord;
+
+  TRACE_FUNCTION("db_record_empty()");
+
+  *empty = TRUE;
+
+  /* DBM_State check */
+  DBM_State_check;
+
+  /* db_handle check */
+  db_ret_code = db_handle_check( db_handle );
+  if( db_ret_code NEQ DB_OK )
+    DB_RETURN( db_ret_code );
+
+  /*	field id search; if field not found, return error DB_INVALID_FIELD */
+  fld_ctr = field_id_search( db_handle, field_id );
+  if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles )
+    DB_RETURN( DB_INVALID_FIELD );
+
+  tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord + fld_ctr;
+
+  /* Using RecordBitMap, check whether record_num is free; 
+     if so, empty = true and false otherwise */
+
+  if (db_get_bit_in_bitmap (tmp_ptrFieldRecord -> RecordBitMap, record_num))
+  {
+    /* if record exist */
+    *empty = FALSE;
+  }
+
+  DB_RETURN( DB_OK )
+
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: db_find_free_record  |
++--------------------------------------------------------------------+
+
+    PURPOSE : Find an free record in given (database, field)
+*/
+int db_find_free_record	( int    db_handle,
+                          USHORT field_id )
+{
+  UBYTE fld_ctr;
+  T_DB_CODE  db_ret_code;
+
+  int record_num;
+
+  T_DBM_FIELDRECORD* tmp_ptrFieldRecord;
+
+
+  TRACE_FUNCTION("db_find_free_record()");
+
+  /* DBM_State check */
+  DBM_State_check;
+
+  /* db_handle check */
+  db_ret_code = db_handle_check( db_handle );
+  if( db_ret_code NEQ DB_OK )
+    DB_RETURN( db_ret_code );
+
+  /*	field id search; if field not found, return error DB_INVALID_FIELD */
+  fld_ctr = field_id_search( db_handle, field_id );
+  if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles )
+    DB_RETURN( DB_INVALID_FIELD );
+
+  tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord + fld_ctr;
+
+  /* Using RecordBitMap, search for free record.
+     If found , return the found record_num
+     Return DB_RECORD_NOT_FOUND */
+
+  record_num = db_search_bit_in_bitmap (tmp_ptrFieldRecord->RecordBitMap,
+                                        tmp_ptrFieldRecord->NumOfRecords,
+                                        FALSE);
+
+  if (record_num EQ 0)
+    DB_RETURN( DB_RECORD_NOT_FOUND );
+
+  DB_VALUE_RETURN( record_num )
+
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: db_info              |
++--------------------------------------------------------------------+
+
+    PURPOSE : Get information about an open database
+*/
+T_DB_CODE db_info ( int        db_handle, 
+                    T_DB_INFO* db_info )
+{
+  T_DB_CODE db_ret_code;
+
+  TRACE_FUNCTION("db_info()");
+
+  /* DBM_State check */
+  DBM_State_check;
+
+  /* db_handle check */
+  db_ret_code = db_handle_check( db_handle );
+  if( db_ret_code NEQ DB_OK )
+    DB_RETURN( db_ret_code );
+
+  (*db_info).clean   = DbmMaster[db_handle].Clean;
+  (*db_info).tracked = DbmMaster[db_handle].Tracked;
+
+  DB_RETURN( DB_OK )
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: db_info_field        |
++--------------------------------------------------------------------+
+
+    PURPOSE : Get general information about a field in an open database.
+*/
+T_DB_CODE db_info_field ( int              db_handle,	
+                          USHORT           field_id, 
+                          T_DB_INFO_FIELD* info_field )
+{
+  UBYTE fld_ctr;
+  T_DB_CODE db_ret_code;
+
+  T_DBM_FIELDRECORD* tmp_ptrFieldRecord;
+
+
+  TRACE_FUNCTION("db_info_field()");
+
+  /* DBM_State check */
+  DBM_State_check;
+
+  /* db_handle check */
+  db_ret_code = db_handle_check( db_handle );
+  if( db_ret_code NEQ DB_OK )
+    DB_RETURN( db_ret_code );
+
+  /*	field id search; if field not found, return error DB_INVALID_FIELD */
+  fld_ctr = field_id_search( db_handle, field_id );
+  if( fld_ctr EQ DbmMaster[db_handle].NumOfFiles )
+    DB_RETURN( DB_INVALID_FIELD );
+
+  tmp_ptrFieldRecord = DbmMaster[db_handle].ptrFieldRecord + fld_ctr;
+
+  /* Using data available in RAM in field record, fill up info_field 
+     (i.e. clean, db_type, num_of_records and used_records). */
+
+  (*info_field).clean        = tmp_ptrFieldRecord -> Clean;
+  (*info_field).entry_type   = tmp_ptrFieldRecord -> DBType;
+  (*info_field).record_size  = tmp_ptrFieldRecord -> RecordSize;
+  (*info_field).num_records  = tmp_ptrFieldRecord -> NumOfRecords;
+  (*info_field).used_records = tmp_ptrFieldRecord -> UsedRecords;
+
+  DB_RETURN( DB_OK )
+
+}
+
+#ifdef _SIMULATION_ /* HM 19-Oct-2006: Currently not used but to be kept */
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                          MODULE: DBM                  |
+|                                       ROUINE: db_get_last_fs_error |
++--------------------------------------------------------------------+
+
+    PURPOSE : Delivers the last error provided by the (flash) file system
+              that resulted in DB_FAIL_FS.
+*/
+int db_get_last_fs_error ( void )
+{
+   DB_VALUE_RETURN( LastFFS_ReturnCode )
+}
+#endif /* #ifdef _SIMULATION_ */
+
+/* Implements Measure # 83 */
+/*
++--------------------------------------------------------------------+
+| PROJECT: PHB                       MODULE: DBM                     |
+|                                    ROUTINE: db_close_for_read_write|
++--------------------------------------------------------------------+
+
+    PURPOSE : Close Read & write FFS Operations
+*/
+
+LOCAL void db_close_for_read_write ( FileHandleRecord  *tmp_open_fields,
+                                     UBYTE             *tmp_old,
+                                     UBYTE              max_per_db)
+{
+
+  TRACE_FUNCTION ("db_close_for_read_write ()");
+
+  if( *tmp_old >= max_per_db )
+  {
+    *tmp_old = 0;
+  }
+
+  DB_FFS_CLOSE( tmp_open_fields[*tmp_old].filehandle );
+  tmp_open_fields[*tmp_old].filehandle = INVALID_FD;
+  tmp_open_fields[*tmp_old].fld_ctr = INVALID_FLD_CTR;
+
+  ++(*tmp_old);
+} 
+
+/* Implements Measure # 211 */
+/*
++-------------------------------------------------------------------------------+
+| PROJECT: PHB                         MODULE:  DBM                             |
+|                                      ROUTINE: read_write_user_record_from_FFS |
++-------------------------------------------------------------------------------+
+
+    PURPOSE : Reads OR Writes user record into FFS
+*/
+LOCAL T_DB_CODE read_write_user_record_from_FFS ( const char      *user_field_file,
+
+#ifdef FFS_CLOSE_BEFORE_OPEN
+                                                  UBYTE            db_ctr,
+                                                  UBYTE            fld_ctr,
+#endif
+                                                  T_FFS_FD        *filehandle,
+                                                  UBYTE            record_num,
+                                                  USHORT           record_size,
+                                                  USHORT           offset,
+                                                  USHORT           length,
+                                                  UBYTE           *record_buffer,
+                                                  T_FFS_OPEN_FLAGS open_option)
+{
+  T_FFS_FD   ffs_fd = INVALID_FD;
+  T_FFS_SIZE ffs_ret_code;
+
+  T_DB_CODE db_code;
+
+  /* See if file already opened, 
+     if not open it and update the file handle */
+
+  TRACE_FUNCTION ("read_write_user_record_from_FFS ()");
+
+#ifndef FFS_CLOSE_BEFORE_OPEN
+  ffs_fd = *filehandle;
+
+  if( !IS_FD_VALID(ffs_fd) )
+  {
+    DB_FFS_OPEN( ffs_fd, user_field_file, open_option );
+
+    if (open_option EQ FFS_O_RDONLY )
+    {
+      TRACE_EVENT_P1( "read_user_record_from_FFS:DB_FFS_OPEN %d", ffs_fd );
+    }
+    else
+    {
+      TRACE_EVENT_P1( "write_user_record_to_FFS:DB_FFS_OPEN %d", ffs_fd );
+    }
+
+    if( (ffs_fd EQ EFFS_NOTFOUND)    OR
+        (ffs_fd EQ EFFS_NAMETOOLONG) OR
+        (ffs_fd EQ EFFS_BADNAME)     OR
+        (ffs_fd EQ EFFS_INVALID)     OR
+        (ffs_fd EQ EFFS_LOCKED)      )
+    {
+      return DB_FAIL;
+    }
+
+    if( ffs_fd < EFFS_OK )
+    {
+      LastFFS_ReturnCode = ffs_fd;
+      return DB_FAIL_FS;
+    }
+
+    *filehandle = ffs_fd;
+  }
+
+#else /* FFS_CLOSE_BEFORE_OPEN */
+
+  ffs_fd = db_open_user_field_file( db_ctr, fld_ctr, user_field_file, open_option );
+
+#endif /* FFS_CLOSE_BEFORE_OPEN */
+
+  ffs_ret_code = ffs_seek( ffs_fd, 
+                           ( (record_num - 1) * (record_size) + offset),
+                           FFS_SEEK_SET ); 
+
+  if (open_option EQ FFS_O_RDONLY )
+  {
+    TRACE_EVENT_P1( "read_user_record_from_FFS:ffs_seek %d", ffs_ret_code );
+  }
+  else
+  {
+    TRACE_EVENT_P1( "write_user_record_to_FFS:ffs_seek %d", ffs_ret_code );
+  }
+
+  db_code = check_ffs_ret_code (ffs_ret_code, filehandle, ffs_fd, TRUE);
+
+  if (db_code NEQ DB_OK)
+  {
+      return db_code;
+  }
+
+
+  if (open_option EQ FFS_O_RDONLY )
+  {
+    ffs_ret_code = ffs_read( ffs_fd, 
+                             record_buffer, 
+                             length ); 
+    TRACE_EVENT_P1( "read_user_record_from_FFS:ffs_read %d", ffs_ret_code );
+  }
+  else
+  {
+    ffs_ret_code = ffs_write( ffs_fd, 
+                              record_buffer, 
+                              length ); 
+    TRACE_EVENT_P1( "write_user_record_to_FFS:ffs_write %d", ffs_ret_code );
+  }
+
+  db_code = check_ffs_ret_code (ffs_ret_code, filehandle, ffs_fd, FALSE);
+
+  if (db_code NEQ DB_OK)
+  {
+      return db_code;
+  }
+
+  /* DB_FFS_CLOSE( ffs_fd ); we will do it in db_flush */
+
+#ifdef FFS_OPEN_PROBLEM_PATCH
+  DB_FFS_CLOSE( ffs_fd );
+  *filehandle = INVALID_FD;
+#endif
+
+  return DB_OK;
+}
+
+/* Implements Measure # 211 */
+/*
++-------------------------------------------------------------------------------+
+| PROJECT: PHB                         MODULE:  DBM                             |
+|                                      ROUTINE: check_ffs_ret_code              |
++-------------------------------------------------------------------------------+
+
+    PURPOSE : Checks ffs_ret_code
+*/
+LOCAL T_DB_CODE check_ffs_ret_code (T_FFS_SIZE ffs_ret_code,
+                                    T_FFS_FD  *filehandle,
+                                    T_FFS_FD   ffs_fd,
+                                    BOOL       check_invalid)
+{
+
+  TRACE_FUNCTION ("check_ffs_ret_code ()");
+
+  if( ( ffs_ret_code EQ EFFS_BADFD )   OR
+      ( (ffs_ret_code EQ EFFS_INVALID) AND check_invalid ) OR
+      ( ffs_ret_code EQ EFFS_BADOP )   )
+  {
+    DB_FFS_CLOSE( ffs_fd );
+    *filehandle = INVALID_FD;
+    return DB_FAIL;
+  }
+ 
+  if( ffs_ret_code < EFFS_OK )
+  {
+    LastFFS_ReturnCode = ffs_ret_code;
+    DB_FFS_CLOSE( ffs_fd );
+    *filehandle = INVALID_FD;
+    return DB_FAIL_FS;
+  }
+  return DB_OK;
+}
+
+
+#endif /* #ifdef TI_PS_FFS_PHB */
+