void
gdbDestroyBlock(GdbBlock *block)
{
	blocktype_t typeIndex;
	
	if (block == NULL)
		return;

	if (gdbCacheRemoveBlock(block->db, block) > 0)
		return;

	typeIndex = block->type - 1;
	
	if (block->detail != NULL)
	{
		if (blockTypeInfo[typeIndex].destroy != NULL)
			blockTypeInfo[typeIndex].destroy(block->detail);
		else
			free(block->detail);
	}

	if (GDB_IS_DIRTY(block))
	{
		pmError(PM_ERROR_WARNING,
				_("GNUpdate DB: Dirty node at offset %ld has not been "
				  "written to disk.\n"),
				block->offset);
	}

	if (block->chain != NULL)
		free(block->chain);

	free(block);
}
void
gdbWriteBlockHeader(GdbBlock *block)
{
	GDatabase *db;
	char header[GDB_BLOCK_HEADER_SIZE];
	int   counter = 0;

	if (block == NULL || !GDB_IS_DIRTY(block))
		return;

	db = block->db;

	if (block->offset == 0)
		return;

	/* Write the header to a buffer. */
	gdbPut8(header,  &counter, block->type);
	gdbPut32(header, &counter, block->dataSize);
	gdbPut16(header, &counter, block->flags);
	gdbPut32(header, &counter, block->next);
	gdbPut32(header, &counter, block->listNext);

	/* Write the header to disk. */
	fseek(db->fp, block->offset, SEEK_SET);

	fwrite(header, GDB_BLOCK_HEADER_SIZE, 1, db->fp);

	fflush(db->fp);

	GDB_CLEAR_DIRTY(block);

	if (block->inList == 0)
		gdbCacheAddBlock(block->db, block);
}
Beispiel #3
0
void
btreeDestroyNodeBlock(void *data)
{
    BTreeNode *node = (BTreeNode *)data;
    uint8_t i;

    if (node == NULL)
    {
        return;
    }
    for (i = 0; i < node->keyCount; i++)
    {
        if (node->keys[i] != NULL)
        {
        /*
            dbg_log(SEC_0130_BTREE, 9)(LOGSTDOUT,"[DEBUG]btreeDestroyNodeBlock: %d# size %d, addr %lx, %.*s\n", i,
                    node->keySizes[i], node->keys[i],
                    node->keySizes[i], node->keys[i]);
        */
            keyFree(node->keys[i], LOC_BTREE_0170);
        }
    }

    if (GDB_IS_DIRTY(node->block))
    {
        dbg_log(SEC_0130_BTREE, 0)(LOGSTDOUT, "error:btreeDestroyNodeBlock: Dirty node at offset %d has not been written to disk.\n",
                            node->block->offset);
    }

    SAFE_FREE(node->children, LOC_BTREE_0171);
    SAFE_FREE(node->keySizes, LOC_BTREE_0172);
    SAFE_FREE(node->keys, LOC_BTREE_0173);

    SAFE_FREE(node, LOC_BTREE_0174);
}
void
gdbWriteBlock(GdbBlock *block)
{
	GDatabase    *db;
	char         *buffer;
	offset_t     *oldChain;
	blocktype_t   typeIndex;
	unsigned int  oldChainCount, oldDataSize;
	unsigned int  i, pos;
	
	if (block == NULL || !GDB_IS_DIRTY(block))
		return;

	/* Set a couple of vars we'll be using. */
	db        = block->db;
	typeIndex = block->type - 1;

	/* Save the old data. */
	oldDataSize   = block->dataSize;
	oldChainCount = block->chainCount;
	oldChain      = block->chain;

	/* See if there is a write function assigned. */
	if (blockTypeInfo[typeIndex].writeBlock != NULL)
	{
		/* Write the block info to a buffer. */
		blockTypeInfo[typeIndex].writeBlock(block, &buffer, &block->dataSize);
	}
	else
	{
		buffer = (char *)block->detail;
	}

	if (buffer == NULL)
	{
		pmError(PM_ERROR_FATAL,
				_("GNUpdate DB: buffer == NULL in %s, line %d\n"),
				__FILE__, __LINE__);
		exit(1);
	}

	/* Get the number of needed blocks. */
	block->chainCount = gdbGetNeededBlockCount(block->dataSize,
											   block->multiple);

	if (oldChainCount == 0)
	{
		/* Reserve new blocks. */
		block->chain = gdbReserveBlockChain(db, block->chainCount,
											block->type);
	}
	else if (block->chainCount < oldChainCount)
	{
		/* The number of needed blocks is shorter than before. */
		MEM_CHECK(block->chain = (offset_t *)malloc(block->chainCount *
													sizeof(offset_t)));
		memcpy(block->chain, oldChain, block->chainCount * sizeof(offset_t));
	}
	else if (block->chainCount > oldChainCount)
	{
		offset_t *newChain;
		int j;
		
		/* The number of needed blocks is longer than before. */
		MEM_CHECK(block->chain = (offset_t *)malloc(block->chainCount *
													sizeof(offset_t)));
			
		newChain = gdbReserveBlockChain(db, block->chainCount - oldChainCount,
										block->type);
		
		memcpy(block->chain, oldChain, oldChainCount * sizeof(offset_t));
		
		for (i = oldChainCount, j = 0; i < block->chainCount; i++, j++)
			block->chain[i] = newChain[j];

		free(newChain);
	}

	/*
	 * Set the offset and next block, if this spills over into
	 * additional blocks.
	 */
	block->offset = block->chain[0];

	if (block->chainCount > 1)
		block->next = block->chain[1];
	else
		block->next = 0;
	
	/* Write the first block header */
	gdbWriteBlockHeader(block);

	/* Write the first block. */
	fwrite(buffer, 1,
		   (block->dataSize < block->multiple - GDB_BLOCK_HEADER_SIZE ?
			block->dataSize : block->multiple - GDB_BLOCK_HEADER_SIZE),
		   db->fp);

	if (block->dataSize < block->multiple - GDB_BLOCK_HEADER_SIZE)
	{
		gdbPad(db->fp, block->multiple - GDB_BLOCK_HEADER_SIZE -
			   block->dataSize);
	}
	else
	{
		char *blockBuffer;
		
		MEM_CHECK(blockBuffer = (char *)malloc(block->multiple));

		pos = block->multiple - GDB_BLOCK_HEADER_SIZE;
		
		/* Write any overflow blocks. */
		for (i = 1; i < block->chainCount; i++)
		{
			offset_t nextOffset;
			unsigned long relPos;
			
			nextOffset = ((i + 1 < block->chainCount) ?
						  block->chain[i + 1] : 0);

			relPos = block->dataSize - pos;
			
			/* Reset the block buffer. */
			memset(blockBuffer, 0, block->multiple);

			/* Write to it. */
			nextOffset = htonl(nextOffset);

			memcpy(blockBuffer, &nextOffset, sizeof(offset_t));
			memcpy(blockBuffer + sizeof(offset_t), buffer + pos,
				   (relPos < block->multiple - sizeof(offset_t) ?
					relPos : block->multiple - sizeof(offset_t)));
			
			/* Write the block buffer. */
			if (block->chain[i - 1] + block->multiple != block->chain[i])
				fseek(db->fp, block->chain[i], SEEK_SET);

			fwrite(blockBuffer, 1, block->multiple, db->fp);

			pos += block->multiple - sizeof(offset_t);
		}

		free(blockBuffer);
	}

	if (oldChainCount != 0)
	{
		/* If the chain shrunk, free up the discarded blocks. */
		if (block->chainCount < oldChainCount)
		{
			gdbFreeBlockChain(db, &oldChain[block->chainCount],
							  oldChainCount - block->chainCount, block->type);
		}
		
		if (oldChainCount != block->chainCount)
			free(oldChain);
	}

	fflush(db->fp);

	if (buffer != block->detail)
		free(buffer);
}