mail-cache-transaction.c revision 4b058f90f9e8a2c6b2eed275de4eb8cc5195a71d
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen uint32_t reserved_space_offset, reserved_space;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int mail_cache_link_unlocked(struct mail_cache *cache,
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainenmail_cache_get_transaction(struct mail_cache_view *view,
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen ctx = i_new(struct mail_cache_transaction_ctx, 1);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen ctx->reservations = buffer_create_dynamic(system_pool, 256);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->cache_file_seq = ctx->cache->hdr->file_seq;
f7d43647acc6dc80064c8c4cacf5bf86f754c530Timo Sirainenstatic void mail_cache_transaction_reset(struct mail_cache_transaction_ctx *ctx)
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen ctx->cache_file_seq = ctx->cache->hdr->file_seq;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainenstatic void mail_cache_transaction_free(struct mail_cache_transaction_ctx *ctx)
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen ctx->view->trans_seq1 = ctx->view->trans_seq2 = 0;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainenstatic int mail_cache_transaction_lock(struct mail_cache_transaction_ctx *ctx)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (ctx->cache_file_seq != ctx->cache->hdr->file_seq)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int mail_cache_grow_file(struct mail_cache *cache, size_t size)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen /* grow the file */
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen new_fsize = cache->hdr_copy.used_file_size + size;
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen grow_size = new_fsize / 100 * MAIL_CACHE_GROW_PERCENTAGE;
c3412ddeb9abc13f99d3caf50faf76cd99f7e9d2Timo Sirainen mail_cache_set_syscall_error(cache, "fstat()");
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen if (file_set_size(cache->fd, new_fsize) < 0) {
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_cache_set_syscall_error(cache, "file_set_size()");
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainenstatic int mail_cache_unlink_hole(struct mail_cache *cache, size_t size,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct mail_cache_header *hdr = &cache->hdr_copy;
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen while (offset != 0) {
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen if (pread_full(cache->fd, &hole, sizeof(hole), offset) <= 0) {
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen mail_cache_set_syscall_error(cache, "pread_full()");
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen if (hole.magic != MAIL_CACHE_HOLE_HEADER_MAGIC) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen "Invalid magic in hole header");
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mail_cache_set_syscall_error(cache, "pwrite_full()");
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenmail_cache_transaction_add_reservation(struct mail_cache_transaction_ctx *ctx)
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen buffer_append(ctx->reservations, &ctx->reserved_space_offset,
36e2fa21c22452470c1509cc63de20f7415c7b5eTimo Sirainen buffer_append(ctx->reservations, &ctx->reserved_space,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenmail_cache_transaction_reserve_more(struct mail_cache_transaction_ctx *ctx,
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen struct mail_cache_header *hdr = &cache->hdr_copy;
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen if (mail_cache_unlink_hole(cache, size, &hole)) {
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen /* found a large enough hole. */
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen ctx->reserved_space_offset = hole.next_offset;
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen /* mail_cache_unlink_hole() could have noticed corruption */
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen if ((uoff_t)hdr->used_file_size + size > (uint32_t)-1) {
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen mail_index_set_error(cache->index, "Cache file too large: %s",
43d504fb5b23e14878e9777cdebff9c623f0b52cTimo Sirainen /* allocate some more space than we need */
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen size_t new_size = (size + ctx->last_grow_size) * 2;
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen if ((uoff_t)hdr->used_file_size + new_size > (uint32_t)-1)
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen if (new_size > MAIL_CACHE_MAX_RESERVED_BLOCK_SIZE) {
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen new_size = size > MAIL_CACHE_MAX_RESERVED_BLOCK_SIZE ?
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mail_cache_grow_file(ctx->cache, size) < 0)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (ctx->reserved_space_offset + ctx->reserved_space ==
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen /* we can simply grow it */
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ctx->reserved_space = size - ctx->reserved_space;
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen /* grow reservation. it's probably the last one in the buffer,
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen but it's not guarateed because we might have used holes
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen buf = buffer_get_modifyable_data(ctx->reservations, &size);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (buf[size] == ctx->reserved_space_offset) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen ctx->reserved_space_offset = hdr->used_file_size;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen hdr->used_file_size = ctx->reserved_space_offset + ctx->reserved_space;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenmail_cache_free_space(struct mail_cache *cache, uint32_t offset, uint32_t size)
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen if (offset + size == cache->hdr_copy.used_file_size) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen /* we can just set used_file_size back */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen } else if (size >= MAIL_CACHE_MIN_HOLE_SIZE) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* set it up as a hole */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen hole.next_offset = cache->hdr_copy.hole_offset;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (pwrite_full(cache->fd, &hole, sizeof(hole), offset) < 0) {
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen mail_cache_set_syscall_error(cache, "pwrite_full()");
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenmail_cache_transaction_free_space(struct mail_cache_transaction_ctx *ctx)
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen /* check again - locking might have reopened the cache file */
2bf7bb14894faf721518e2122a14a2389ef94078Timo Sirainen i_assert(ctx->cache_file_seq == ctx->cache->hdr->file_seq);
2bf7bb14894faf721518e2122a14a2389ef94078Timo Sirainen mail_cache_free_space(ctx->cache, ctx->reserved_space_offset,
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainenmail_cache_transaction_get_space(struct mail_cache_transaction_ctx *ctx,
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen ret = mail_cache_transaction_reserve_more(ctx, max_size,
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen /* final commit - see if we can free the rest of the
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen reserved space */
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainenmail_cache_transaction_flush(struct mail_cache_transaction_ctx *ctx)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen const struct mail_cache_record *rec, *tmp_rec;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uint32_t write_offset, old_offset, rec_pos, cache_file_seq;
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen size_t size, max_size, seq_idx, seq_limit, seq_count;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen /* committing, remove the last dummy record */
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen buffer_set_used_size(ctx->cache_data, ctx->prev_pos);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (ctx->cache_file_seq != ctx->cache->hdr->file_seq) {
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen /* cache file reopened - need to abort */
8af07808ba203f8709e2ff9eaf2291e1c4a4d53dTimo Sirainen rec = buffer_get_data(ctx->cache_data, &size);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen seq = buffer_get_data(ctx->cache_data_seq, &seq_count);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen for (seq_idx = 0, rec_pos = 0; rec_pos < ctx->prev_pos;) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen write_offset = mail_cache_transaction_get_space(ctx, rec->size,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen /* cache file reopened - need to abort */
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen /* nothing to write / error */
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen /* see how much we can really write there */
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen for (size = 0; size + tmp_rec->size <= max_size; ) {
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen /* write it to file */
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen i_assert(ctx->cache_file_seq == cache->hdr->file_seq);
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen if (pwrite_full(cache->fd, rec, max_size, write_offset) < 0) {
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen mail_cache_set_syscall_error(cache, "pwrite_full()");
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen /* write the cache_offsets to index file. records' prev_offset
33d63688ed8b26dc333e3c2edbfb2fe6e412604dTimo Sirainen is updated to point to old cache record when index is being
d0d7fcf3ce44f26fdf34c1542a25cec644c5c4c7Timo Sirainen mail_index_update_cache(ctx->trans, seq[seq_idx],
d0d7fcf3ce44f26fdf34c1542a25cec644c5c4c7Timo Sirainen /* we added records for this message multiple
d0d7fcf3ce44f26fdf34c1542a25cec644c5c4c7Timo Sirainen times in this same uncommitted transaction.
d0d7fcf3ce44f26fdf34c1542a25cec644c5c4c7Timo Sirainen only the new one will be written to
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen transaction log, we need to do the linking
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ourself here. */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mail_cache_link_unlocked(cache, old_offset,
d0d7fcf3ce44f26fdf34c1542a25cec644c5c4c7Timo Sirainen /* drop the written data from buffer */
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenmail_cache_transaction_switch_seq(struct mail_cache_transaction_ctx *ctx)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen /* fix record size */
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen data = buffer_get_modifyable_data(ctx->cache_data, &size);
3f26c5aced2e71efc783f26bb8a7ac53f7504622Timo Sirainen buffer_append(ctx->cache_data_seq, &ctx->prev_seq,
844adc2ea94a10ef81d1ceac9a87b877c20de623Timo Sirainen ctx->cache_data = buffer_create_dynamic(system_pool, 32768);
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen ctx->cache_data_seq = buffer_create_dynamic(system_pool, 256);
3f26c5aced2e71efc783f26bb8a7ac53f7504622Timo Sirainen buffer_append(ctx->cache_data, &new_rec, sizeof(new_rec));
3f26c5aced2e71efc783f26bb8a7ac53f7504622Timo Sirainenint mail_cache_transaction_commit(struct mail_cache_transaction_ctx *ctx)
3f26c5aced2e71efc783f26bb8a7ac53f7504622Timo Sirainen if (!ctx->changes || MAIL_CACHE_IS_UNUSABLE(cache)) {
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen /* make sure everything's written before updating offsets */
bb26f09873c18f342cd1ab2d0ee0b9018e6546d9Timo Sirainen mail_cache_set_syscall_error(cache, "fdatasync()");
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainenvoid mail_cache_transaction_rollback(struct mail_cache_transaction_ctx *ctx)
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if ((ctx->reserved_space > 0 || ctx->reservations->used > 0) &&
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen buf = buffer_get_data(ctx->reservations, &size);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* free flushed data as well. do it from end to
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen beginning so we have a better chance of
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen updating used_file_size instead of adding
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen } while (size > 0);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainenstatic int mail_cache_header_add_field(struct mail_cache_transaction_ctx *ctx,
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen unsigned int field)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen /* re-read header to make sure we don't lose any fields. */
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (mail_cache_header_fields_read(cache) < 0) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (ctx->cache->field_file_map[field] != (uint32_t)-1) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen /* it was already added */
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen buffer = buffer_create_dynamic(pool_datastack_create(), 256);
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen offset = mail_cache_transaction_get_space(ctx, size, size, &size, TRUE);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen else if (pwrite_full(cache->fd, data, size, offset) < 0) {
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen mail_cache_set_syscall_error(cache, "pwrite_full()");
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen mail_cache_set_syscall_error(cache, "fdatasync()");
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen } else if (mail_cache_header_fields_get_next_offset(cache,
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen /* after it's guaranteed to be in disk, update header offset */
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (pwrite_full(cache->fd, &offset, sizeof(offset),
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mail_cache_set_syscall_error(cache, "pwrite_full()");
8153fdec343e40e2a78f5c12353e89b994b28f74Timo Sirainen /* we'll need to fix mappings. */
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainenvoid mail_cache_add(struct mail_cache_transaction_ctx *ctx, uint32_t seq,
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen unsigned int field, const void *data, size_t data_size)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (ctx->cache->fields[field].field.decision ==
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen (MAIL_CACHE_DECISION_NO | MAIL_CACHE_DECISION_FORCED))
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen file_field = ctx->cache->field_file_map[field];
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen /* we'll have to add this field to headers */
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (mail_cache_header_add_field(ctx, field) < 0)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen file_field = ctx->cache->field_file_map[field];
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen mail_cache_decision_add(ctx->view, seq, field);
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen fixed_size = ctx->cache->fields[field].field.field_size;
ab3c1eab9ca13916358a9e8b12df8212fefb7dbfTimo Sirainen i_assert(fixed_size == (unsigned int)-1 || fixed_size == data_size);
e5c08648676d1989f6e70b95e5990c26b3e8b96bTimo Sirainen /* remember roughly what we have modified, so cache lookups can
e5c08648676d1989f6e70b95e5990c26b3e8b96bTimo Sirainen look into transactions to see changes. */
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen if (seq < ctx->view->trans_seq1 || ctx->view->trans_seq1 == 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (buffer_get_used_size(ctx->cache_data) + full_size >
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* time to flush our buffer */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen buffer_append(ctx->cache_data, &file_field, sizeof(file_field));
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen buffer_append(ctx->cache_data, data, data_size);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen buffer_append(ctx->cache_data, null4, 4 - (data_size & 3));
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenint mail_cache_transaction_lookup(struct mail_cache_transaction_ctx *ctx,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return mail_index_update_cache_lookup(ctx->trans, seq, offset_r);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int mail_cache_link_unlocked(struct mail_cache *cache,
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen new_offset += offsetof(struct mail_cache_record, prev_offset);
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen mail_cache_set_syscall_error(cache, "pwrite_full()");
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenint mail_cache_link(struct mail_cache *cache, uint32_t old_offset,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (new_offset + sizeof(struct mail_cache_record) >
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen "Cache record offset %u points outside file",
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen if (mail_cache_link_unlocked(cache, old_offset, new_offset) < 0)
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainenint mail_cache_delete(struct mail_cache *cache, uint32_t offset)
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen cache_rec = mail_cache_get_record(cache, offset);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* we'll only update the deleted_space in header. we can't really
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen do any actual deleting as other processes might still be using
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen the data. also it's actually useful as some index views are still
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen able to ask cached data from messages that have already been
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen cache->hdr_copy.deleted_space += cache_rec->size;