summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xinc/slices.h3
-rw-r--r--src/ddhardrescue.c14
-rw-r--r--src/slices.c111
3 files changed, 94 insertions, 34 deletions
diff --git a/inc/slices.h b/inc/slices.h
index 78fb4c7..1ed7775 100755
--- a/inc/slices.h
+++ b/inc/slices.h
@@ -3,6 +3,7 @@
#include <stdint.h>
#include <stdlib.h>
+#include <pthread.h>
/* IMPORTANT NOTES
Slice are inclusive intervals. Let say sliceNew(1,2,S_UNKNOWN,NULL) return a [1;2] interval,
@@ -21,6 +22,8 @@ typedef struct _slice {
typedef struct {
int count;
slice_t *first, *last;
+ address_t min, max;
+ pthread_mutex_t writeOrConsistentReadMutex;
} slices_t;
slice_t *sliceNew(address_t begin, address_t end, sliceStatus_t status, slice_t *next);
diff --git a/src/ddhardrescue.c b/src/ddhardrescue.c
index ba6781e..691bf09 100644
--- a/src/ddhardrescue.c
+++ b/src/ddhardrescue.c
@@ -63,11 +63,18 @@ int main(int argc, char **argv) {
srand(4);
// Data structure initialization
+ // TODO : provides a standard method to do that ?
memset(&slices, 0, sizeof(slices));
slices.data=slicesNewSingleton(args.beginSector, args.endSector, S_UNKNOWN);
+ if ( slices.data == NULL ) {
+ return 3;
+ }
+ slices.data->min=args.beginSector;
+ slices.data->max=args.endSector;
+
res=pthread_mutex_init(&(slices.eventListenerMutex), NULL);
if (res!=0) {
- return 3;
+ return 4;
}
// Threads preparation, creation and start
@@ -78,7 +85,7 @@ int main(int argc, char **argv) {
res=pthread_create(&tWorker, NULL, procWorker, &tArgs);
if (res!=0) {
- return 4;
+ return 5;
}
// Ncurses interface run in the main thread
@@ -137,8 +144,7 @@ void cursesUpdateSliceDump(slices_evt_t *slicesEvt, slice_t *modifiedSlice) {
//FIXME : do that realy
pthread_mutex_lock(&ncursesWriteMutex);
-
- toPrint=slicesDump(slicesEvt->data, &blockSize, 1000, 0, 1000);
+ toPrint=slicesDump(slicesEvt->data, &blockSize, 1000, slicesEvt->data->min, slicesEvt->data->max);
if (toPrint != NULL) {
attron(COLOR_PAIR(4));
mvwprintw(winUpdateSliceDump, 1, 0, toPrint);
diff --git a/src/slices.c b/src/slices.c
index 21fdd3b..d077454 100644
--- a/src/slices.c
+++ b/src/slices.c
@@ -1,7 +1,13 @@
#include <string.h>
#include "slices.h"
-int min(int a, int b) { return (a<b)?a:b; }
+//for perror
+#include <stdio.h>
+
+//FIXME : avoir une méthode destroy pour les slices qui free le mutex
+
+inline int min(int a, int b) { return (a<b)?a:b; }
+inline int max(int a, int b) { return (a>b)?a:b; }
slice_t *sliceNew(address_t begin, address_t end, sliceStatus_t status, slice_t *next) {
slice_t *s;
@@ -35,8 +41,12 @@ int sliceSplit(slices_t *slices, slice_t *initialSlice, address_t splitAt, slice
For pratical reasons with pointer mess-up, the first action is to split between the second and the last slice
and then between he first and second if needed.
*/
+ pthread_mutex_lock(&(slices->writeOrConsistentReadMutex));
- if ( splitAt < initialSlice->begin || splitAt > initialSlice->end ) return -2;
+ if ( splitAt < initialSlice->begin || splitAt > initialSlice->end ) {
+ pthread_mutex_unlock(&(slices->writeOrConsistentReadMutex));
+ return -2;
+ }
// Test before act because we'll change values of the initialSlice because
// it would become the firstSlice or even the second one if the first is zero-lenght
@@ -45,7 +55,10 @@ int sliceSplit(slices_t *slices, slice_t *initialSlice, address_t splitAt, slice
if ( splitAfterSingularity ) {
thirdSlice = sliceNew(splitAt+1, initialSlice->end, statusAfter, initialSlice->next);
- if ( thirdSlice == NULL ) return -1;
+ if ( thirdSlice == NULL ) {
+ pthread_mutex_unlock(&(slices->writeOrConsistentReadMutex));
+ return -1;
+ }
initialSlice->end = splitAt;
// No status change because we'll split again in 2 parts or not
@@ -60,7 +73,10 @@ int sliceSplit(slices_t *slices, slice_t *initialSlice, address_t splitAt, slice
if ( splitBeforeSingularity ) {
secondSlice = sliceNew(splitAt, splitAt, statusAt, rightSlice);
- if ( secondSlice == NULL ) return -1;
+ if ( secondSlice == NULL ) {
+ pthread_mutex_unlock(&(slices->writeOrConsistentReadMutex));
+ return -1;
+ }
initialSlice->end = splitAt-1;
initialSlice->status=statusBefore;
@@ -71,17 +87,25 @@ int sliceSplit(slices_t *slices, slice_t *initialSlice, address_t splitAt, slice
initialSlice->status=statusAt; // Two cases : a==splitAt or statusAt==statusBefore
}
-
+ pthread_mutex_unlock(&(slices->writeOrConsistentReadMutex));
return 1 + (splitBeforeSingularity?1:0) + (splitAfterSingularity?1:0);
}
slices_t *slicesNewEmpty() {
+ int res;
slices_t *ss = malloc(1*sizeof(slices_t));
+
if (ss==NULL) {
return NULL;
}
memset(ss, 0, sizeof(slices_t));
+ res=pthread_mutex_init(&(ss->writeOrConsistentReadMutex), NULL);
+ if (res!=0) {
+ free(ss);
+ return NULL;
+ }
+
return ss;
}
@@ -102,6 +126,8 @@ slices_t *slicesNewSingleton(address_t begin, address_t end, sliceStatus_t statu
}
void slicesAppend(slices_t *slices, slice_t *slice) {
+ pthread_mutex_lock(&(slices->writeOrConsistentReadMutex));
+
slice->next=NULL; //XXX Could be generalized
if (slices->first==NULL || slices->last==NULL) {
slices->first = slice;
@@ -110,12 +136,16 @@ void slicesAppend(slices_t *slices, slice_t *slice) {
}
slices->last=slice;
(slices->count)++;
+
+ pthread_mutex_unlock(&(slices->writeOrConsistentReadMutex));
}
slice_t *slicesFindLargest(slices_t *slices, sliceStatus_t status) {
slice_t *curr, *sMax = NULL;
address_t i, iMax = 0;
+ pthread_mutex_lock(&(slices->writeOrConsistentReadMutex));
+
curr = slices->first;
while (curr != NULL) {
i=curr->end - curr->begin + 1;
@@ -125,6 +155,8 @@ slice_t *slicesFindLargest(slices_t *slices, sliceStatus_t status) {
}
curr=curr->next;
}
+
+ pthread_mutex_unlock(&(slices->writeOrConsistentReadMutex));
return sMax;
}
@@ -132,6 +164,7 @@ slice_t *slicesFindLargestFast(slices_t *slices, address_t *foundMax, sliceStatu
slice_t *curr, *sMax = NULL;
address_t i, iMax = 0;
+//FIXME : pthread_lock à faire avant l'appel là :-s (car argument firstToTry peut pointer vers n'importe quoi si autre thread modifie
curr = firstToTry;
while (curr != NULL) {
i=curr->end - curr->begin + 1;
@@ -158,10 +191,18 @@ slice_t *slicesFindLargestFast(slices_t *slices, address_t *foundMax, sliceStatu
}
char *slicesDump(slices_t *slices, address_t *blockSize, unsigned int charCount, address_t begin, address_t end) {
- slice_t *curr = slices->first;
+ int res;
+ slice_t *curr;
address_t sb,se,i;
char *dump, ci;
+
+ res=pthread_mutex_lock(&(slices->writeOrConsistentReadMutex));
+ if (res!=0) {
+ perror("slicesDump, pb lock mutex");
+ exit(42);
+ }
+ curr = slices->first;
// If blockSize is 0, try to autodetect to display entire slice chain
if (*blockSize == 0) {
*blockSize=(end-begin+1)/(charCount-1);
@@ -174,37 +215,47 @@ char *slicesDump(slices_t *slices, address_t *blockSize, unsigned int charCount,
memset(dump, ' ', charCount);
dump[charCount]=0;
+ //For each slice
while (curr != NULL) {
- sb=curr->begin / *blockSize; //FIXME : gérer le max également !
-/*
-if ( curr->end / *blockSize > charCount -1 ) {
- printf("\nBUG : end/blkSze==%lli, charCount==%i\n", curr->end / *blockSize,charCount-1);
-}
-*/
- se=min(curr->end / *blockSize,charCount-1);
-
- switch (curr->status) {
- case S_UNKNOWN: ci='_'; break;
- case S_UNREADABLE: ci='!'; break;
- case S_RECOVERED: ci='.'; break;
- default: ci='~'; break;
- }
+ // If is (partially) contained in the [begin,end] interval
+ if ( (curr->begin >= begin && curr->begin <=end) || ( curr->end >= end && curr->end <= end ) ) {
+
+ // Draw the slice on the right number of characters
+ sb=max(0, (curr->begin - begin) / *blockSize);
+ se=min((curr->end - begin) / *blockSize, charCount-1);
- for (i=sb;i<=se;i++) {
- if (dump[i] == ' ' ) {
- // This is a new information
- dump[i]=ci;
- } else if ( dump[i] == ci || dump[i] == '!' ) {
- // Already the right information or error, don't modify
- } else {
- // Multiple information on the same character
- dump[i]='#';
+ // Debug assertion
+ if (sb >= charCount || se >= charCount) {
+ printf("BUG : sb==%lli, se=%lli, charCount==%i\n", sb, se, charCount);
+ pthread_mutex_unlock(&(slices->writeOrConsistentReadMutex));
+ exit(42);
+ }
+
+ // Choose from the current slice status the right char to draw
+ switch (curr->status) {
+ case S_UNKNOWN: ci='_'; break;
+ case S_UNREADABLE: ci='!'; break;
+ case S_RECOVERED: ci='.'; break;
+ default: ci='~'; break;
}
- }
+ // Draw on the right number of characters, paying attention with information collision
+ for (i=sb;i<=se;i++) {
+ if (dump[i] == ' ' ) {
+ // This is a new information
+ dump[i]=ci;
+ } else if ( dump[i] == ci || dump[i] == '!' ) {
+ // Already the right information or error, don't modify
+ } else {
+ // Multiple information on the same character
+ dump[i]='#';
+ }
+ }
+ }
curr=curr->next;
}
+ pthread_mutex_unlock(&(slices->writeOrConsistentReadMutex));
return dump;
}