summaryrefslogtreecommitdiff
path: root/src/recover.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/recover.c')
-rw-r--r--src/recover.c128
1 files changed, 128 insertions, 0 deletions
diff --git a/src/recover.c b/src/recover.c
new file mode 100644
index 0000000..2131542
--- /dev/null
+++ b/src/recover.c
@@ -0,0 +1,128 @@
+#include "recover.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <unistd.h> /* for usleep - to be removed */
+
+// Main algorithm for recover datas
+void recover(slices_evt_t *slicesEvt, char *src, char *dst, char *ddOpts) {
+ slice_t *sliceToRead;
+ address_t firstError=0, median, foundMax=0;
+ int res;
+
+ //sliceToRead=slicesEvt->data->first;
+ sliceToRead=slicesFindLargest(slicesEvt->data, S_UNKNOWN);
+ while (!end) {
+ // try to recover sliceToRead and split it if read error
+ switch ( tryRecoverUntilError(sliceToRead, &firstError, src, dst, ddOpts) ) {
+ case 0:
+ // slice recovery has been executed without read error
+ sliceToRead->status=S_RECOVERED;
+ break;
+ case EIO:
+ // slice recovery has encountered a readerror
+ res=sliceEvtSplit(slicesEvt, sliceToRead, firstError, S_RECOVERED, S_UNREADABLE, S_UNKNOWN);
+ if (res<1) {
+ //TODO
+ printf("sliceEvtSplit return %d\n", res);
+ exit(5);
+ }
+ break;
+ default:
+ exit(2); //TODO
+ }
+
+ /* Now, search the largest S_UNKNOWN zone
+ split it in two parts */
+ //sliceToRead=slicesFindLargest(slices, S_UNKNOWN);
+ sliceToRead=slicesFindLargestFast(slicesEvt->data, &foundMax, S_UNKNOWN, foundMax, sliceToRead->next);
+ if ( sliceToRead == NULL ) {
+ // There is nothing more to recover, bailout
+ end=1;
+ continue;
+ }
+
+
+ median=(sliceToRead->begin+sliceToRead->end)/2;
+ res=sliceEvtSplit(slicesEvt, sliceToRead, median, S_UNKNOWN, S_UNKNOWN, S_UNKNOWN);
+ switch (res) {
+ case 1:
+ // No split, try analyse this zone
+ // Should be a slice of length 1
+ break;
+ case 2:
+ /* After splitting an S_UNKNOWN zone in two parts
+ take the second for further analysis.
+ We already now that this first one is just preceded by
+ a read error, and errors are frequently grouped in zones,
+ so trying to read a sector just after a faulty sector is
+ most likely a waste of time.
+ */
+ sliceToRead=sliceToRead->next;
+ break;
+ case 3:
+ // Internal error of sliceSlpit because this set of parameters prevent split by 3
+ exit(6); // TODO
+ break;
+ case -1:
+ // Memory error
+ exit(5); //TODO
+ break;
+ default:
+ // API error, all necessary cases are already listed
+ exit(7); // TODO
+ }
+ }
+}
+
+// Method tha read source (and clone to dest) until the first read error
+int tryRecoverUntilError(slice_t *sliceToRead, address_t *firstError, char *src, char *dst, char*ddOpts) {
+ //TODO : implement realy that
+ //TODO : bail out hardly if WRITE error (on dest)
+
+// char ddinvocation[256];
+ int res;
+ address_t seek, count;
+
+ seek=sliceToRead->begin;
+ count=sliceToRead->end - seek + 1;
+// res=snprintf(ddinvocation, 255, "dd %s %s %s seek=%lld skip=%lld count=%lld", src, dst, ddOpts, seek, seek, count);
+//TODO : listener to put that info on the interface puts(ddinvocation);
+
+/*
+ // Simulate that we have systematically a read error at first sector
+ *firstError=sliceToRead->begin;
+ res=EIO;
+*/
+/*
+ // Simulate that we have systematically a read error at last sector
+ *firstError=sliceToRead->end;
+ res=EIO;
+*/
+/*
+ // Simulate that we have systematically a read error at first sector
+ // Simulate for each read, tha we have an error just in the middle if read for mor than one sector
+ if ( sliceToRead->begin == sliceToRead->end ) {
+ res=0;
+ } else {
+ *firstError=(sliceToRead->begin + sliceToRead->end)/2;
+ res=EIO;
+ }
+*/
+
+ // Simulate for each read a pseudo random error position and generate some cases of full read without error
+ //address_t error=sliceToRead->begin + rand()%(count);
+ address_t error=sliceToRead->begin + rand()%(count/3);
+ if ( error % 42 == 0 ) {
+ res=0;
+ } else {
+ res=EIO;
+ *firstError=error;
+ }
+
+ // Keep things humanly understandable (to be removed when real reads will be done)
+ //usleep(10000);
+
+ return res;
+}
+