Insert a key/object pair into the ISAM file. Note it is permissable for the object to be blank but not the key. This involves the following steps:- - Identify the target data block for the new key from the index. We then have both the target block address and the available space. - Read in target data block, assemble new version of it including the new key. - If the target has enough space - Write out target block. - Advice the index map of a new higher key, if applicable. - Else - Write out half the target to the original location - Write out upper half to a new location - Advice the index map. Note that no attempt is made to move elements into adjacent data blocks. Disk space is cheap but disk operations are expensive.

Return TypeFunction nameArguments
hzEcodehdbIsamfile::Insert(hzString&,hzString&,)

Declared in file: hzDatabase.h
Defined in file : hdbIsamfile.cpp

Function Logic:

0:START 1:unknown 2:Return E_NOINIT 3:unknown 4:Return E_NOTOPEN 5:unknown 6:Return E_NODATA 7:items nSpace k 8:unknown 9:unknown 10:items 11:Return E_BADVALUE 12:unknown 13:nC items items items 14:unknown 15:items 16:Return E_WRITEFAIL 17:items items 18:unknown 19:items 20:Return E_WRITEFAIL 21:items m_nBlocks items 22:Return E_OK 23:nLo strA 24:unknown 25:m_Index 26:nLo items 27:strA>newKey 28:items items 29:items 30:strA addr items items 31:unknown 32:items 33:Return E_READFAIL 34:items 35:unknown 36:items 37:Return E_READFAIL 38:unknown 39:unknown 40:* 41:unknown 42:strA i j 43:unknown 44:strB i 45:j 46:unknown 47:items strB strA 48:items items 49:unknown 50:items 51:Return E_WRITEFAIL 52:items items 53:unknown 54:strA strB strB strA Zout nSpace 55:unknown 56:items 57:unknown 58:* 59:items 60:unknown 61:items 62:Return E_WRITEFAIL 63:items items items items items items items items items 64:unknown 65:items 66:Return E_WRITEFAIL 67:items items 68:unknown 69:items 70:items 71:unknown 72:items 73:unknown 74:* 75:items 76:unknown 77:items 78:Return E_WRITEFAIL 79:items 80:Return rc

Function body:

hzEcode hdbIsamfile::Insert (hzString& newKey)hzString& newObj, 
{
   //  Insert a key/object pair into the ISAM file. Note it is permissable for the object to be blank but not the key.
   //  
   //  This involves the following steps:-
   //  
   //   - Identify the target data block for the new key from the index. We then have both the target block address and the available space.
   //   - Read in target data block, assemble new version of it including the new key.
   //   - If the target has enough space
   //    - Write out target block.
   //    - Advice the index map of a new higher key, if applicable.
   //   - Else
   //    - Write out half the target to the original location
   //    - Write out upper half to a new location
   //    - Advice the index map.
   //  
   //  Note that no attempt is made to move elements into adjacent data blocks. Disk space is cheap but disk operations are expensive.
   //  
   //  Arguments: 1) key The key
   //     2) obj The object
   //  
   //  Returns: E_NOINIT If this hdbIsamfile instance has not been initialized
   //     E_NODATA If the supplied datum is of zero size
   //     E_WRITEFAIL If the data could not be written to disk.
   //     E_OK  If operation successful
   _hzfunc("hdbIsamfile::Insert") ;
   hzMapM<hzString,hzString>   tmp ;   //  Temp map of key/object pairs found in target data area
   hzChain     Zout ;          //  For writing out the temp map to a block
   hzChain     Xind ;          //  For writing out index entries
   chIter      zi ;            //  Chain iterator
   char*       i ;             //  Buffer iterator
   char*       j ;             //  Buffer iterator
   const char* k ;             //  Key iterator
   hzString    strA ;          //  Key string
   hzString    strB ;          //  Object string
   uint32_t    addr = 0;       //  Address of target data block
   uint32_t    nSpace = 0; //  Space consumed
   uint32_t    nC ;            //  Counter
   int32_t     nLo ;           //  Position of target within m_Index map
   hzEcode     rc = E_OK ;     //  Return code
   //  Check init state
   if (m_nInitState < 1)   return E_NOINIT ;
   if (m_nInitState < 2)   return E_NOTOPEN ;
   //  Check validity of supplied key (must contain no newlines)
   if (!newKey)
       return E_NODATA ;
   m_Error.Clear() ;
   nSpace = newKey.Length() ;
   k = *newKey ;
   for (nC = 0; nC < nSpace ; nC++)
   {
       if (k[nC] == 0|| k[nC] == CHAR_NL)
           { m_Error.Printf("Illegal value %c (%d) found in key [%s]\n", k[nC], k[nC], *newKey) ; return E_BADVALUE ; }
   }
   //  If virgin ISAM
   if (!m_Index.Count())
   {
       nC = newKey.Length() ;
       memset(m_Buf, 0,HZ_BLOCKSIZE) ;
       sprintf(m_Buf, "%s\n%s\n", *newKey, *newObj) ;
       m_WrD.write(m_Buf, HZ_BLOCKSIZE) ;
       if (m_WrD.fail())
           { m_Error.Printf("Could not write to virgin data file\n") ; return E_WRITEFAIL ; }
       m_WrD.flush() ;
       m_WrI << "00000000," << "\n" ;
       if (m_WrI.fail())
           { m_Error.Printf("Could not write to virgin index file\n") ; return E_WRITEFAIL ; }
       m_Index.Insert(_hzGlobal_nullString, 0);
       m_nBlocks = 1;
       m_WrI.flush() ;
       return E_OK ;
   }
   //  Identify target data block
   nLo = m_Index.Target(newKey) ;
   strA = m_Index.GetKey(nLo) ;
   if (nLo >&eq; (int32_t) m_Index.Count())
       { nLo = m_Index.Count() -1; m_Error.Printf("%s: Case 0: identified index posn %d\n", *_fn, nLo) ; }
   else if (strA > newKey)
       { nLo-- ; m_Error.Printf("%s: Case 1: identified index posn %d\n", *_fn, nLo) ; }
   else
       m_Error.Printf("%s: Case 2: identified index posn %d\n", *_fn, nLo) ;
   strA = (char*) 0;
   addr = m_Index.GetObj(nLo) ;
       m_Error.Printf("%s: Case 2: identified block %d\n", *_fn, nLo) ;
   //  Read in target data block
   m_RdD.seekg(addr * m_nBlkSize) ;
   if (m_RdD.fail())
       { m_Error.Printf("%s: Failed to seek to block %d (position %d) in data block\n", *_fn, addr, addr * m_nBlkSize) ; return E_READFAIL ; }
   m_RdD.read(m_Buf, HZ_BLOCKSIZE) ;
   if (m_RdD.fail())
       { m_Error.Printf("%s: Failed to read block %d (position %d) in data block\n", *_fn, addr, addr * m_nBlkSize) ; return E_READFAIL ; }
   for (i = j = m_Buf, nC = 0; nC < HZ_BLOCKSIZE ; i++, nC++)
   {
       if (m_Buf[nC] == CHAR_NL)
       {
           *i = 0;
           if (!strA)
               { strA = j ; j = i + 1; continue ; }
           if (*j)
               strB = j ;
           j = i + 1;
           if (!strA)
               break ;
           tmp.Insert(strA, strB) ;
           strA = strB = (char*) 0;
       }
   }
   //  Insert the new key
   tmp.Insert(newKey, newObj) ;
   //  Seek to the original block
   m_WrD.seekp(addr * m_nBlkSize) ;
   if (m_WrD.fail())
       { m_Error.Printf("Could not seek to posn %u in data file\n", addr * m_nBlkSize) ; return E_WRITEFAIL ; }
   m_Error.Printf("Seeked to posn %u in data file\n", m_WrD.tellp()) ;
   //  Write out map, add block if necessary
   Zout.Clear() ;
   for (nC = 0; nC < tmp.Count() ; nC++)
   {
       strA = tmp.GetKey(nC) ;
       strB = tmp.GetObj(nC) ;
       nSpace = Zout.Size() + strA.Length() + strB.Length() + 2;
       if (nSpace > m_nBlkSize)
       {
           memset(m_Buf, 0,HZ_BLOCKSIZE) ;
           for (i = m_Buf, zi = Zout ; !zi.eof() ; i++, zi++)
               *i = *zi ;
           m_WrD.write(m_Buf, HZ_BLOCKSIZE) ;
           if (m_WrD.fail())
               { m_Error.Printf("Could not write to data file\n") ; return E_WRITEFAIL ; }
           Zout.Clear() ;
           m_WrD.flush() ;
           //  Create new block
           Xind.Printf("%08x,%s\n", m_nBlocks, *strA) ; m_WrI << Xind ; m_WrI.flush() ; Xind.Clear() ;
           m_Index.Insert(strA, m_nBlocks) ;
           m_nBlocks++ ;
           //  Allocate new block
           m_WrD.seekp(0,ios_base::end) ;
           if (m_WrD.fail())
               { m_Error.Printf("Alloc - Could not seek to end in data file\n") ; return E_WRITEFAIL ; }
       }
       Zout << strA ;
       Zout.AddByte(CHAR_NL) ;
       if (strB)
           Zout << strB ;
       Zout.AddByte(CHAR_NL) ;
   }
   if (Zout.Size())
   {
       memset(m_Buf, 0,HZ_BLOCKSIZE) ;
       for (i = m_Buf, zi = Zout ; !zi.eof() ; i++, zi++)
           *i = *zi ;
       m_WrD.write(m_Buf, HZ_BLOCKSIZE) ;
       if (m_WrD.fail())
           { m_Error.Printf("Could not write to posn %u in data file\n", m_WrD.tellp()) ; return E_WRITEFAIL ; }
       m_WrD.flush() ;
   }
   return rc ;
}