bool HDBNode::remove(HDBHandle& hdl) { // If node hasn't been written yet, don't do anything. if (m_pdata->m_offset <= 0) { return false; } File file = hdl.getFile(); HDB* pdb = hdl.getHDB(); HDBBlock fblk; // Remove all children Int32 coffset = m_pdata->m_blk.lastChild; Int32 toffset; while (coffset > 0) { HDB::readBlock(fblk, file, coffset); toffset = coffset; // Save offset for deletion class coffset = fblk.prevSib; // Save offset for next read // Remove node and all of its children. This call will modify fblk. removeBlock(hdl, fblk, toffset); } // Set pointer on next sibling if it exists if (m_pdata->m_blk.nextSib > 0) { HDB::readBlock(fblk, file, m_pdata->m_blk.nextSib); fblk.prevSib = m_pdata->m_blk.prevSib; HDB::writeBlock(fblk, file, m_pdata->m_blk.nextSib); } // Set pointer on prev sibling if it exists if (m_pdata->m_blk.prevSib > 0) { HDB::readBlock(fblk, file, m_pdata->m_blk.prevSib); fblk.nextSib = m_pdata->m_blk.nextSib; HDB::writeBlock(fblk, file, m_pdata->m_blk.prevSib); } // If it has a parent, insure parent doesn't contain it's offset if (m_pdata->m_blk.parent > 0) { // Read parent block HDB::readBlock(fblk, file, m_pdata->m_blk.parent); bool changed = false; // If this was the first child in the list, then update the // first child pointer in the parent block if (fblk.firstChild == m_pdata->m_offset) { changed = true; fblk.firstChild = m_pdata->m_blk.nextSib; } // If this was the last child in the list, then update the // last child pointer in the parent block if (fblk.lastChild == m_pdata->m_offset) { changed = true; fblk.lastChild = m_pdata->m_blk.prevSib; } // If any offsets changed in the parent block, then update the parent if (changed) { HDB::writeBlock(fblk, file, m_pdata->m_blk.parent); } } else { // Must be a root node if (pdb->getFirstRootOffSet() == m_pdata->m_offset) { pdb->setFirstRootOffSet(file, m_pdata->m_blk.nextSib); } if (pdb->getLastRootOffset() == m_pdata->m_offset) { pdb->setLastRootOffset(file, m_pdata->m_blk.prevSib); } } // Add block to free list pdb->addBlockToFreeList(file, m_pdata->m_blk, m_pdata->m_offset); // Remove the index entry for this node hdl.removeIndexEntry(m_pdata->m_key.c_str()); m_pdata->m_offset = -1; m_pdata->m_blk.isFree = true; m_pdata->m_blk.parent = -1; m_pdata->m_blk.firstChild = -1; m_pdata->m_blk.lastChild = -1; m_pdata->m_blk.prevSib = -1; m_pdata->m_blk.nextSib = -1; m_pdata->m_blk.size = 0; hdl.registerWrite(); return true; }
Int32 HDBNode::write(HDBHandle& hdl, EWriteHeaderFlag onlyHeader) { if (!m_pdata) { OW_THROW(HDBException, "Internal error: Cannot write null node"); } bool newRecord = false; m_pdata->m_blk.keyLength = m_pdata->m_key.length() + 1; m_pdata->m_blk.dataLength = m_pdata->m_bfrLen + m_pdata->m_key.length() + 1; File file = hdl.getFile(); HDB* phdb = hdl.getHDB(); int totalSize = m_pdata->m_blk.dataLength + sizeof(m_pdata->m_blk); m_pdata->m_blk.isFree = false; if (m_pdata->m_offset <= 0) // Is this a new node? { newRecord = true; m_pdata->m_blk.size = totalSize; m_pdata->m_offset = phdb->findBlock(file, totalSize); if (m_pdata->m_blk.parent <= 0) { phdb->addRootNode(file, m_pdata->m_blk, m_pdata->m_offset); } else { HDB::writeBlock(m_pdata->m_blk, file, m_pdata->m_offset); } // Add this entry to the index if (!hdl.addIndexEntry(m_pdata->m_key.c_str(), m_pdata->m_offset)) { OW_THROW(HDBException, "Failed to write index entry"); } } else { // If the size required to hold this node has increased, // then delete the old block and add a new one. if (totalSize > int(m_pdata->m_blk.size)) { HDBBlock node = m_pdata->m_blk; phdb->addBlockToFreeList(file, node, m_pdata->m_offset); // delete old m_pdata->m_blk.size = totalSize; updateOffsets(hdl, phdb->findBlock(file, totalSize)); } HDB::writeBlock(m_pdata->m_blk, file, m_pdata->m_offset); } if (onlyHeader == false || newRecord == true) { // Now write key and data for node if (file.write(m_pdata->m_key.c_str(), m_pdata->m_key.length()+1) != m_pdata->m_key.length()+1) { OW_THROW_ERRNO_MSG(HDBException, "Failed to write node key"); } if (file.write(m_pdata->m_bfr, m_pdata->m_bfrLen) != size_t(m_pdata->m_bfrLen)) { OW_THROW_ERRNO_MSG(HDBException, "Failed to write node data"); } } m_pdata->m_version = hdl.registerWrite(); return m_pdata->m_offset; }