int cdc_data_flush(cdc_t *cdc)
{
int rc;
rc = 0;
if (cdc->data.cluster.dirty)
{
unsigned long bat_entry;
unsigned long bat_entry_next;
const char *ptr;
unsigned long count;
size_t zsize;
unsigned long compress_flag;
cdc->data.cluster.dirty = 0;
count = cdc->data.blocks;
ptr = cdc->data.cluster.buffer;
compress_flag = 0;
zsize = cdc->data.size;
rc = cdc->env->deflate.fn(
cdc->env->deflate.arg,
cdc->data.zbuffer,
&zsize,
cdc->data.cluster.buffer,
cdc->data.size
);
if (0 == rc)
{
/*
* success! but if we don't save at least 1 block,
* don't bother
*/
count = (zsize + cdc->blk.size - 1) / cdc->blk.size;
if (count < cdc->data.blocks)
{
compress_flag = MAP_FLAG_COMPRESSED;
ptr = cdc->data.zbuffer;
}
}
rc = cdc_map_entry_get(cdc, cdc->data.cluster.cluster,
&bat_entry);
if (0 == rc)
{
if (BAT_ENTRY_EOL == bat_entry)
{
/* get a free bat entry */
rc = cdc_bat_entry_alloc(cdc, &bat_entry);
if (0 == rc)
{
rc = cdc_map_entry_set(
cdc,
cdc->data.cluster.cluster,
bat_entry | compress_flag
);
}
} else
{
unsigned long map_entry;
map_entry = bat_entry;
if (compress_flag)
{
map_entry |= MAP_FLAG_COMPRESSED;
} else
{
map_entry &= ~MAP_FLAG_COMPRESSED;
}
if (bat_entry != map_entry)
{
rc = cdc_map_entry_set(cdc, cdc->data.cluster.cluster,
map_entry);
}
bat_entry &= ~MAP_FLAG_COMPRESSED;
}
}
while ((0 == rc) && count)
{
rc = data_block_write(cdc, bat_entry, ptr);
if (0 == rc)
{
rc = cdc_bat_entry_get(cdc, bat_entry, &bat_entry_next);
}
if (0 == rc)
{
count--;
if (count)
{
ptr += cdc->blk.size;
if (0 == rc)
{
if (BAT_ENTRY_EOL == bat_entry_next)
{
rc = cdc_bat_entry_alloc(cdc, &bat_entry_next);
if (0 == rc)
{
rc = cdc_bat_entry_set(cdc, bat_entry,
bat_entry_next);
}
}
bat_entry = bat_entry_next;
}
}
}
}
/*
* free up any remaining entries
* --- occurs if the current cluster compresses to less than
* the previous one
*/
if ((0 == rc) && (BAT_ENTRY_EOL != bat_entry_next))
{
/* mark the end */
cdc_bat_entry_set(cdc, bat_entry, BAT_ENTRY_EOL);
do
{
bat_entry = bat_entry_next;
rc = cdc_bat_entry_get(cdc, bat_entry, &bat_entry_next);
if (0 == rc)
{
rc = cdc_bat_entry_free(cdc, bat_entry);
}
} while ((0 == rc) && (BAT_ENTRY_EOL != bat_entry_next));
}
}
return rc;
}
End of Listing