From c908d810330edba56b476229aba081997f251da7 Mon Sep 17 00:00:00 2001 From: Ludovic Pouzenc Date: Sun, 14 Aug 2011 20:31:22 +0000 Subject: Bug hunting : la visualisation marche dans la fenêtre ncurses. Avec un mutex et la fin de l'algo de dump, ça marche mieux qu'avant (segfaults...) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: file:///var/svn/2011-ddhardrescue/trunk@18 d3078510-dda0-49f1-841c-895ef4b7ec81 --- inc/slices.h | 3 ++ src/ddhardrescue.c | 14 +++++-- src/slices.c | 111 ++++++++++++++++++++++++++++++++++++++--------------- 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 #include +#include /* 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 #include "slices.h" -int min(int a, int b) { return (a + +//FIXME : avoir une méthode destroy pour les slices qui free le mutex + +inline int min(int a, int b) { return (ab)?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; } -- cgit v1.2.3