mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 19:01:57 -04:00
Adds preliminary support to store additional information for each offset.
This commit is contained in:
parent
02506a7669
commit
8fc805c272
5 changed files with 137 additions and 40 deletions
16
elem.h
16
elem.h
|
|
@ -65,8 +65,6 @@ struct snapraid_filter {
|
|||
tommy_node node; /**< Next node in the list. */
|
||||
};
|
||||
|
||||
struct snapraid_file;
|
||||
|
||||
/**
|
||||
* The block has both the hash and the parity computed.
|
||||
* This is the normal state of a saved block.
|
||||
|
|
@ -312,6 +310,11 @@ struct snapraid_map {
|
|||
tommy_node node;
|
||||
};
|
||||
|
||||
/**
|
||||
* Info.
|
||||
*/
|
||||
typedef unsigned snapraid_info;
|
||||
|
||||
/**
|
||||
* Allocates a content.
|
||||
*/
|
||||
|
|
@ -675,5 +678,14 @@ struct snapraid_map* map_alloc(const char* name, unsigned position, const char*
|
|||
*/
|
||||
void map_free(struct snapraid_map* map);
|
||||
|
||||
/**
|
||||
* Make an info.
|
||||
*/
|
||||
static inline snapraid_info info_make(time_t last_access)
|
||||
{
|
||||
/* clear the low bit to keep some free bits */
|
||||
return last_access & ~0xFF;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -1067,6 +1067,10 @@ for which the parity is computed using the previous value.
|
|||
.PP
|
||||
This field is used only when you interrupt manually the \(a"sync\(a"
|
||||
command.
|
||||
.SS inf BLOCK TIME
|
||||
Information shared by all the block at the specified offset.
|
||||
TIME is the last time of the hash/parity verification done at this
|
||||
block.
|
||||
.SS symlink DISK PATH
|
||||
Defines a symbolic link in the specified DISK.
|
||||
.SS hardlink DISK PATH
|
||||
|
|
|
|||
|
|
@ -793,6 +793,11 @@ Content
|
|||
This field is used only when you interrupt manually the "sync"
|
||||
command.
|
||||
|
||||
inf BLOCK TIME
|
||||
Information shared by all the block at the specified offset.
|
||||
TIME is the last time of the hash/parity verification done at this
|
||||
block.
|
||||
|
||||
symlink DISK PATH
|
||||
Defines a symbolic link in the specified DISK.
|
||||
|
||||
|
|
|
|||
151
state.c
151
state.c
|
|
@ -54,6 +54,7 @@ void state_init(struct snapraid_state* state)
|
|||
tommy_list_init(&state->filterlist);
|
||||
tommy_list_init(&state->importlist);
|
||||
tommy_hashdyn_init(&state->importset);
|
||||
tommy_array_init(&state->infoarr);
|
||||
state->loaded_blockmax = 0;
|
||||
}
|
||||
|
||||
|
|
@ -65,6 +66,7 @@ void state_done(struct snapraid_state* state)
|
|||
tommy_list_foreach(&state->filterlist, (tommy_foreach_func*)filter_free);
|
||||
tommy_list_foreach(&state->importlist, (tommy_foreach_func*)import_file_free);
|
||||
tommy_hashdyn_done(&state->importset);
|
||||
tommy_array_done(&state->infoarr);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1007,6 +1009,39 @@ void state_read(struct snapraid_state* state)
|
|||
|
||||
/* stat */
|
||||
++count_block;
|
||||
} else if (strcmp(tag, "inf") == 0) {
|
||||
/* "inf" command */
|
||||
block_off_t v_pos;
|
||||
snapraid_info info;
|
||||
uint32_t t;
|
||||
|
||||
hash = oathash8(hash, 'i');
|
||||
|
||||
ret = sgetu32(f, &v_pos);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Invalid 'inf' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
hash = oathash32(hash, v_pos);
|
||||
|
||||
c = sgetc(f);
|
||||
if (c != ' ') {
|
||||
fprintf(stderr, "Invalid 'inf' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
ret = sgetu32(f, &t);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Invalid 'inf' specification in '%s' at line %u\n", path, line);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
hash = oathash32(hash, t);
|
||||
|
||||
info = info_make(t);
|
||||
|
||||
/* insert the block in the block array */
|
||||
tommy_array_grow(&state->infoarr, v_pos + 1);
|
||||
tommy_array_set(&state->infoarr, v_pos, (void*)info);
|
||||
} else if (strcmp(tag, "off") == 0) {
|
||||
/* "off" command */
|
||||
block_off_t v_pos;
|
||||
|
|
@ -1623,6 +1658,8 @@ void state_write(struct snapraid_state* state)
|
|||
unsigned count_dir;
|
||||
unsigned count_content;
|
||||
tommy_node* i;
|
||||
block_off_t b;
|
||||
block_off_t infomax;
|
||||
unsigned k;
|
||||
oathash_t hash;
|
||||
|
||||
|
|
@ -1632,6 +1669,7 @@ void state_write(struct snapraid_state* state)
|
|||
count_symlink = 0;
|
||||
count_dir = 0;
|
||||
hash = 0;
|
||||
infomax = 0; /* index of the maximum info saved from all the disks */
|
||||
|
||||
/* count the content files */
|
||||
count_content = 0;
|
||||
|
|
@ -1734,11 +1772,12 @@ void state_write(struct snapraid_state* state)
|
|||
for(i=state->disklist;i!=0;i=i->next) {
|
||||
tommy_node* j;
|
||||
struct snapraid_disk* disk = i->data;
|
||||
block_off_t blockmax;
|
||||
int first_deleted;
|
||||
|
||||
/* for each file */
|
||||
for(j=disk->filelist;j!=0;j=j->next) {
|
||||
struct snapraid_file* file = j->data;
|
||||
block_off_t k;
|
||||
uint64_t size;
|
||||
uint64_t mtime_sec;
|
||||
int32_t mtime_nsec;
|
||||
|
|
@ -1777,8 +1816,8 @@ void state_write(struct snapraid_state* state)
|
|||
}
|
||||
|
||||
/* for each block in the file */
|
||||
for(k=0;k<file->blockmax;++k) {
|
||||
struct snapraid_block* block = &file->blockvec[k];
|
||||
for(b=0;b<file->blockmax;++b) {
|
||||
struct snapraid_block* block = &file->blockvec[b];
|
||||
unsigned block_state;
|
||||
|
||||
block_state = block_state_get(block);
|
||||
|
|
@ -1800,6 +1839,10 @@ void state_write(struct snapraid_state* state)
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* keep track of the maximum block */
|
||||
if (block->parity_pos > infomax)
|
||||
infomax = block->parity_pos;
|
||||
|
||||
sputu32(block->parity_pos, f);
|
||||
hash = oathash32(hash, block->parity_pos);
|
||||
|
||||
|
|
@ -1874,49 +1917,81 @@ void state_write(struct snapraid_state* state)
|
|||
++count_dir;
|
||||
}
|
||||
|
||||
/* save all the delete blocks */
|
||||
{
|
||||
block_off_t k;
|
||||
block_off_t blockmax;
|
||||
int first_deleted;
|
||||
|
||||
first_deleted = 1;
|
||||
blockmax = tommy_array_size(&disk->blockarr);
|
||||
/* maximum block */
|
||||
blockmax = tommy_array_size(&disk->blockarr);
|
||||
|
||||
/* for each deleted block in the disk */
|
||||
for(k=0;k<blockmax;++k) {
|
||||
struct snapraid_block* block = tommy_array_get(&disk->blockarr, k);
|
||||
if (block_state_get(block) == BLOCK_STATE_DELETED) {
|
||||
if (first_deleted) {
|
||||
first_deleted = 0;
|
||||
|
||||
sputsl("hole ", f);
|
||||
hash = oathash8(hash, 'h');
|
||||
sputs(disk->name, f);
|
||||
hash = oathashs(hash, disk->name);
|
||||
sputeol(f);
|
||||
if (serror(f)) {
|
||||
fprintf(stderr, "Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
sputsl("off ", f);
|
||||
hash = oathash8(hash, 'o');
|
||||
|
||||
sputu32(k, f);
|
||||
hash = oathash32(hash, k);
|
||||
|
||||
sputc(' ', f);
|
||||
sputhex(block->hash, HASH_SIZE, f);
|
||||
hash = oathashm(hash, block->hash, HASH_SIZE);
|
||||
/* for each deleted block in the disk */
|
||||
first_deleted = 1;
|
||||
for(b=0;b<blockmax;++b) {
|
||||
struct snapraid_block* block = tommy_array_get(&disk->blockarr, b);
|
||||
if (block_state_get(block) == BLOCK_STATE_DELETED) {
|
||||
if (first_deleted) {
|
||||
first_deleted = 0;
|
||||
|
||||
sputsl("hole ", f);
|
||||
hash = oathash8(hash, 'h');
|
||||
sputs(disk->name, f);
|
||||
hash = oathashs(hash, disk->name);
|
||||
sputeol(f);
|
||||
if (serror(f)) {
|
||||
fprintf(stderr, "Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
sputsl("off ", f);
|
||||
hash = oathash8(hash, 'o');
|
||||
|
||||
/* keep track of the maximum block */
|
||||
if (b > infomax)
|
||||
infomax = b;
|
||||
|
||||
sputu32(b, f);
|
||||
hash = oathash32(hash, b);
|
||||
|
||||
sputc(' ', f);
|
||||
sputhex(block->hash, HASH_SIZE, f);
|
||||
hash = oathashm(hash, block->hash, HASH_SIZE);
|
||||
|
||||
sputeol(f);
|
||||
if (serror(f)) {
|
||||
fprintf(stderr, "Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* note that here infomax contains the maximum block for which we wrote something */
|
||||
/* tha could be smaller than of blocks we have in memory, in case of deleted blocks */
|
||||
|
||||
/* don't try to write more info than stored */
|
||||
if (infomax > tommy_array_size(&state->infoarr))
|
||||
infomax = tommy_array_size(&state->infoarr);
|
||||
|
||||
/* for each block */
|
||||
for(b=0;b<infomax;++b) {
|
||||
snapraid_info info;
|
||||
|
||||
info = (snapraid_info)tommy_array_get(&state->infoarr, b);
|
||||
|
||||
/* save only stuff different than 0 */
|
||||
if (info != 0) {
|
||||
sputsl("inf ", f);
|
||||
hash = oathash8(hash, 'i');
|
||||
|
||||
sputu32(b, f);
|
||||
hash = oathash32(hash, b);
|
||||
|
||||
sputc(' ', f);
|
||||
|
||||
sputu32(info, f);
|
||||
hash = oathash32(hash, info);
|
||||
|
||||
sputeol(f);
|
||||
if (serror(f)) {
|
||||
fprintf(stderr, "Error writing the content file '%s'. %s.\n", serrorfile(f), strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
state.h
1
state.h
|
|
@ -62,6 +62,7 @@ struct snapraid_state {
|
|||
tommy_list filterlist; /**< List of inclusion/exclusion. */
|
||||
tommy_list importlist; /**< List of import file. */
|
||||
tommy_hashdyn importset; /**< Hashtable by hash of all the import blocks. */
|
||||
tommy_array infoarr; /**< Block information array. */
|
||||
block_off_t loaded_blockmax; /**< Previous size of the parity file, computed from the loaded state. */
|
||||
time_t progress_start; /**< Start of processing for progress visualization. */
|
||||
time_t progress_last; /**< Last update of progress visualization. */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue