mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 19:01:57 -04:00
Speed up the status command
Some checks failed
Some checks failed
This commit is contained in:
parent
4da11411f1
commit
025816d151
9 changed files with 139 additions and 28 deletions
|
|
@ -2009,19 +2009,18 @@ static int state_diffscan(struct snapraid_state* state, int is_diff)
|
|||
no_difference = !total.count_move && !total.count_copy && !total.count_restore
|
||||
&& !total.count_change && !total.count_remove && !total.count_insert;
|
||||
|
||||
int parity_invalid = state->parity_is_invalid;
|
||||
if (is_diff) {
|
||||
if (!no_difference) {
|
||||
msg_status("There are differences!\n");
|
||||
} else {
|
||||
msg_status("No differences\n");
|
||||
}
|
||||
if (parity_invalid)
|
||||
if (state->unsynced_blocks != 0)
|
||||
log_error(EUSER, "The last sync was interrupted. Run it again!\n");
|
||||
}
|
||||
|
||||
if (parity_invalid) {
|
||||
log_tag("summary:exit:incomplete_sync\n");
|
||||
if (state->unsynced_blocks != 0) {
|
||||
log_tag("summary:exit:unsynced\n");
|
||||
} else if (!no_difference) {
|
||||
log_tag("summary:exit:diff\n");
|
||||
} else {
|
||||
|
|
@ -2040,7 +2039,7 @@ static int state_diffscan(struct snapraid_state* state, int is_diff)
|
|||
return 1;
|
||||
|
||||
/* check also for incomplete "sync" */
|
||||
if (parity_invalid)
|
||||
if (state->unsynced_blocks != 0)
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -181,7 +181,7 @@ void state_init(struct snapraid_state* state)
|
|||
state->no_conf = 0;
|
||||
for (i = 0; i < SMART_IGNORE_MAX; ++i)
|
||||
state->smartignore[i] = 0;
|
||||
state->parity_is_invalid = 0;
|
||||
state->unsynced_blocks = 0;
|
||||
state->thermal_stop_gathering = 0;
|
||||
state->thermal_ambient_temperature = 0;
|
||||
state->thermal_highest_temperature = 0;
|
||||
|
|
@ -3129,8 +3129,8 @@ static void state_read_content(struct snapraid_state* state, const char* path, S
|
|||
log_tag("content_info:block_unsynced:%u\n", count_unsynced);
|
||||
log_tag("content_info:block_unscrubbed:%u\n", count_unscrubbed);
|
||||
|
||||
/* set the parity validity */
|
||||
state->parity_is_invalid = count_unsynced != 0;
|
||||
/* store the unsynced_blocks */
|
||||
state->unsynced_blocks = count_unsynced;
|
||||
}
|
||||
|
||||
struct state_write_thread_context {
|
||||
|
|
@ -4020,8 +4020,8 @@ static void state_write_content(struct snapraid_state* state, uint32_t* out_crc)
|
|||
log_tag("content_info:block_unsynced:%u\n", count_unsynced);
|
||||
log_tag("content_info:block_unscrubbed:%u\n", count_unscrubbed);
|
||||
|
||||
/* set the parity validity */
|
||||
state->parity_is_invalid = count_unsynced != 0;
|
||||
/* store the unsynced_blocks */
|
||||
state->unsynced_blocks = count_unsynced;
|
||||
|
||||
*out_crc = crc;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ struct snapraid_state {
|
|||
unsigned besthash; /**< Best hash suggested. */
|
||||
const char* command; /**< Command running. */
|
||||
int smartignore[SMART_IGNORE_MAX]; /**< Smart attributes to ignore for all devices. */
|
||||
int parity_is_invalid; /**< If the parity is invalid, and a sync is needed. */
|
||||
uint32_t unsynced_blocks; /**< If the parity is invalid, and a sync is needed. */
|
||||
|
||||
tommy_list contentlist; /**< List of content files. */
|
||||
tommy_list disklist; /**< List of all the disks. */
|
||||
|
|
|
|||
|
|
@ -72,7 +72,6 @@ int state_status(struct snapraid_state* state)
|
|||
uint64_t file_block_count;
|
||||
uint64_t file_block_free;
|
||||
block_off_t parity_block_free;
|
||||
unsigned unsynced_blocks;
|
||||
unsigned unscrubbed_blocks;
|
||||
uint64_t all_wasted;
|
||||
int free_not_zero;
|
||||
|
|
@ -297,7 +296,6 @@ int state_status(struct snapraid_state* state)
|
|||
bad_last = 0;
|
||||
count = 0;
|
||||
rehash = 0;
|
||||
unsynced_blocks = 0;
|
||||
unscrubbed_blocks = 0;
|
||||
log_tag("block_count:%u\n", blockmax);
|
||||
for (i = 0; i < blockmax; ++i) {
|
||||
|
|
@ -309,19 +307,17 @@ int state_status(struct snapraid_state* state)
|
|||
/* for each disk */
|
||||
one_invalid = 0;
|
||||
one_valid = 0;
|
||||
for (node_disk = state->disklist; node_disk != 0; node_disk = node_disk->next) {
|
||||
struct snapraid_disk* disk = node_disk->data;
|
||||
struct snapraid_block* block = fs_par2block_find(disk, i);
|
||||
|
||||
if (block_has_file(block))
|
||||
one_valid = 1;
|
||||
if (block_has_invalid_parity(block))
|
||||
one_invalid = 1;
|
||||
}
|
||||
if (state->opt.gui_verbose) { /* avoid this time consuming operation if not needed */
|
||||
for (node_disk = state->disklist; node_disk != 0; node_disk = node_disk->next) {
|
||||
struct snapraid_disk* disk = node_disk->data;
|
||||
struct snapraid_block* block = fs_par2block_find(disk, i);
|
||||
|
||||
/* if both valid and invalid, we need to update */
|
||||
if (one_invalid && one_valid) {
|
||||
++unsynced_blocks;
|
||||
if (block_has_file(block))
|
||||
one_valid = 1;
|
||||
if (block_has_invalid_parity(block))
|
||||
one_invalid = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* skip unused blocks */
|
||||
|
|
@ -367,7 +363,7 @@ int state_status(struct snapraid_state* state)
|
|||
}
|
||||
|
||||
/* sort the info to get the time info */
|
||||
qsort(timemap, count, sizeof(time_t), time_compare);
|
||||
sort_time(timemap, count);
|
||||
|
||||
/* output the info map */
|
||||
i = 0;
|
||||
|
|
@ -477,9 +473,9 @@ int state_status(struct snapraid_state* state)
|
|||
printf("WARNING! You have scrub dates in the future! The next sync/scrub will truncate them!\n");
|
||||
}
|
||||
|
||||
if (unsynced_blocks) {
|
||||
if (state->unsynced_blocks) {
|
||||
printf("WARNING! The array is NOT fully synced.\n");
|
||||
printf("You have a sync in progress at %u%%.\n", muldiv(blockmax - unsynced_blocks, 100, blockmax));
|
||||
printf("You have a sync in progress at %u%%.\n", muldiv(blockmax - state->unsynced_blocks, 100, blockmax));
|
||||
} else {
|
||||
printf("No sync is in progress.\n");
|
||||
}
|
||||
|
|
@ -573,7 +569,7 @@ int state_status(struct snapraid_state* state)
|
|||
|
||||
if (bad)
|
||||
log_tag("summary:exit:bad\n");
|
||||
else if (unsynced_blocks)
|
||||
else if (state->unsynced_blocks != 0)
|
||||
log_tag("summary:exit:unsynced\n");
|
||||
else
|
||||
log_tag("summary:exit:ok\n");
|
||||
|
|
|
|||
|
|
@ -854,3 +854,99 @@ unsigned muldiv_upper(uint64_t v, uint64_t mul, uint64_t div)
|
|||
return (uint32_t)((v * mul + div - 1) / div);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
/* sort */
|
||||
|
||||
/**
|
||||
* Three-way partition for quicksort
|
||||
* Partitions array into three parts: < pivot, == pivot, > pivot
|
||||
* Returns the boundaries of the equal section via lt and gt pointers
|
||||
*/
|
||||
static void partition3way(time_t *arr, size_t left, size_t right, size_t *lt, size_t *gt)
|
||||
{
|
||||
/* choose median-of-three as pivot to avoid worst case on sorted data */
|
||||
size_t mid = left + (right - left) / 2;
|
||||
time_t pivot;
|
||||
|
||||
/* sort left, mid, right and use median as pivot */
|
||||
if (arr[left] > arr[mid]) {
|
||||
uint64_t tmp = arr[left]; arr[left] = arr[mid]; arr[mid] = tmp;
|
||||
}
|
||||
if (arr[mid] > arr[right]) {
|
||||
uint64_t tmp = arr[mid]; arr[mid] = arr[right]; arr[right] = tmp;
|
||||
if (arr[left] > arr[mid]) {
|
||||
tmp = arr[left]; arr[left] = arr[mid]; arr[mid] = tmp;
|
||||
}
|
||||
}
|
||||
pivot = arr[mid];
|
||||
|
||||
// Dutch National Flag partition
|
||||
size_t i = left;
|
||||
size_t lt_idx = left;
|
||||
size_t gt_idx = right;
|
||||
|
||||
while (i <= gt_idx) {
|
||||
if (arr[i] < pivot) {
|
||||
uint64_t tmp = arr[lt_idx];
|
||||
arr[lt_idx] = arr[i];
|
||||
arr[i] = tmp;
|
||||
lt_idx++;
|
||||
i++;
|
||||
} else if (arr[i] > pivot) {
|
||||
uint64_t tmp = arr[i];
|
||||
arr[i] = arr[gt_idx];
|
||||
arr[gt_idx] = tmp;
|
||||
gt_idx--;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
*lt = lt_idx;
|
||||
*gt = gt_idx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursive three-way quicksort
|
||||
*/
|
||||
static void quicksort3way_recursive(time_t *arr, size_t left, size_t right)
|
||||
{
|
||||
if (left >= right)
|
||||
return;
|
||||
|
||||
/* use insertion sort for small subarrays (optimization) */
|
||||
if (right - left < 16) {
|
||||
for (size_t i = left + 1; i <= right; i++) {
|
||||
time_t key = arr[i];
|
||||
size_t j = i;
|
||||
while (j > left && arr[j - 1] > key) {
|
||||
arr[j] = arr[j - 1];
|
||||
j--;
|
||||
}
|
||||
arr[j] = key;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
size_t lt, gt;
|
||||
partition3way(arr, left, right, <, >);
|
||||
|
||||
/*
|
||||
* Recursively sort elements less than and greater than pivot
|
||||
* Elements equal to pivot are already in correct position
|
||||
*/
|
||||
if (lt > left) {
|
||||
quicksort3way_recursive(arr, left, lt - 1);
|
||||
}
|
||||
if (gt < right) {
|
||||
quicksort3way_recursive(arr, gt + 1, right);
|
||||
}
|
||||
}
|
||||
|
||||
void sort_time(time_t *arr, size_t n)
|
||||
{
|
||||
if (n <= 1)
|
||||
return;
|
||||
quicksort3way_recursive(arr, 0, n - 1);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -273,5 +273,17 @@ static inline int bit_vect_test(bit_vect_t* bit_vect, size_t off)
|
|||
unsigned muldiv(uint64_t v, uint64_t mul, uint64_t div);
|
||||
unsigned muldiv_upper(uint64_t v, uint64_t mul, uint64_t div);
|
||||
|
||||
/****************************************************************************/
|
||||
/* sort */
|
||||
|
||||
/**
|
||||
* Sort an array of uint64_t integers in-place
|
||||
* Optimized for arrays with many duplicate values
|
||||
*
|
||||
* @param arr Pointer to array of uint64_t
|
||||
* @param n Number of elements in the array
|
||||
*/
|
||||
void sort_time(time_t* arr, size_t n);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -484,6 +484,10 @@ The array is already synchronized.
|
|||
.I diff
|
||||
Indicates that differences were found.
|
||||
The array needs a \`sync\` operation.
|
||||
.HP 4
|
||||
.I unsynced
|
||||
The array has an interrupted sync.
|
||||
The array needs another \`sync\` operation.
|
||||
.PD
|
||||
.RE
|
||||
.SH GENERAL PROGRESS AND EXECUTION TAGS
|
||||
|
|
|
|||
|
|
@ -330,6 +330,8 @@ Scan Tags
|
|||
The array is already synchronized.
|
||||
diff - Indicates that differences were found.
|
||||
The array needs a `sync` operation.
|
||||
unsynced - The array has an interrupted sync.
|
||||
The array needs another `sync` operation.
|
||||
|
||||
General Progress and Execution Tags
|
||||
These tags are used to report the runtime processing of the commands
|
||||
|
|
|
|||
|
|
@ -346,6 +346,8 @@ These tags provide a final count of all detected changes.
|
|||
The array is already synchronized.
|
||||
diff - Indicates that differences were found.
|
||||
The array needs a `sync` operation.
|
||||
unsynced - The array has an interrupted sync.
|
||||
The array needs another `sync` operation.
|
||||
|
||||
|
||||
6 GENERAL PROGRESS AND EXECUTION TAGS
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue