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 Type | Function name | Arguments |
|---|---|---|
| hzEcode | hdbIsamfile::Insert | (hzString&,hzString&,) |
Declared in file: hzDatabase.h
Defined in file : hdbIsamfile.cpp
Function Logic:
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 ;
}