tdb_len_t recovery_size = 0;
int i;
- recovery_size = sizeof(tdb_len_t);
+ recovery_size = 0;
for (i=0;i<tdb->transaction->num_blocks;i++) {
if (i * PAGESIZE >= tdb->transaction->old_map_size) {
break;
tdb->stats.frees++;
ecode = add_free_record(tdb, recovery_head,
sizeof(rec) + rec.max_len,
- TDB_LOCK_WAIT);
+ TDB_LOCK_WAIT, true);
if (ecode != TDB_SUCCESS) {
return tdb_logerr(tdb, ecode, TDB_LOG_ERROR,
"tdb_recovery_allocate:"
const struct tdb_methods *methods = tdb->transaction->io_methods;
struct tdb_recovery_record *rec;
tdb_off_t old_map_size = tdb->transaction->old_map_size;
- uint64_t magic, tailer;
+ uint64_t magic;
int i;
enum TDB_ERROR ecode;
if (offset >= old_map_size) {
continue;
}
+
if (offset + length > tdb->file->map_size) {
free(data);
return tdb_logerr(tdb, TDB_ERR_CORRUPT, TDB_LOG_ERROR,
/* the recovery area contains the old data, not the
new data, so we have to call the original tdb_read
method to get it */
- ecode = methods->tread(tdb, offset,
- p + sizeof(offset) + sizeof(length),
- length);
+ if (offset + length > old_map_size) {
+ /* Short read at EOF, and zero fill. */
+ unsigned int len = old_map_size - offset;
+ ecode = methods->tread(tdb, offset,
+ p + sizeof(offset) + sizeof(length),
+ len);
+ memset(p + sizeof(offset) + sizeof(length) + len, 0,
+ length - len);
+ } else {
+ ecode = methods->tread(tdb, offset,
+ p + sizeof(offset) + sizeof(length),
+ length);
+ }
if (ecode != TDB_SUCCESS) {
free(data);
return ecode;
p += sizeof(offset) + sizeof(length) + length;
}
- /* and the tailer */
- tailer = sizeof(*rec) + recovery_max_size;
- memcpy(p, &tailer, sizeof(tailer));
- tdb_convert(tdb, p, sizeof(tailer));
-
/* write the recovery data to the recovery area */
ecode = methods->twrite(tdb, recovery_offset, data,
sizeof(*rec) + recovery_size);