summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLudovic Pouzenc <ludovic@pouzenc.fr>2011-08-15 16:26:07 +0000
committerLudovic Pouzenc <ludovic@pouzenc.fr>2011-08-15 16:26:07 +0000
commite9ef70cefa571bb1ada1ec515a433ed9a643a171 (patch)
tree332b03015a7dec775e06d6443d48a20da49e6b5a
parent4ecf840e1ce10fe7a45ae69b5c54b1bba5ed5707 (diff)
download2011-ddhardrescue-e9ef70cefa571bb1ada1ec515a433ed9a643a171.tar.gz
2011-ddhardrescue-e9ef70cefa571bb1ada1ec515a433ed9a643a171.tar.bz2
2011-ddhardrescue-e9ef70cefa571bb1ada1ec515a433ed9a643a171.zip
Refactoring : Tout ce qui "ncurses" a été dégagé dans un "module" séparé. Le ddhardrescue.c est tout propre maintenant.
git-svn-id: file:///var/svn/2011-ddhardrescue/trunk@21 d3078510-dda0-49f1-841c-895ef4b7ec81
-rw-r--r--src/cursesview.c180
-rw-r--r--src/ddhardrescue.c116
-rw-r--r--src/recover.c20
-rw-r--r--src/slices.c15
-rw-r--r--src/slices_evt.c11
-rw-r--r--src/utils.c78
6 files changed, 220 insertions, 200 deletions
diff --git a/src/cursesview.c b/src/cursesview.c
new file mode 100644
index 0000000..b032356
--- /dev/null
+++ b/src/cursesview.c
@@ -0,0 +1,180 @@
+#include "cursesview.h"
+
+#include <pthread.h>
+#include <curses.h>
+#include <panel.h>
+#include <string.h>
+
+#define CURSESWIN_COUNT 3
+
+// Global variable shared by all threads to say "finish current operation and go away"
+extern int end;
+
+// window updated by cursesUpdateSliceDump callback from "worker" thread, with a mutex for prevent fuzzy concurrent updates
+WINDOW *winUpdateSliceDump=NULL;
+static pthread_mutex_t ncursesWriteMutex = PTHREAD_MUTEX_INITIALIZER;
+
+// Helpers declaration (below the interesting code of this file)
+int cursesInit(WINDOW *wins[], PANEL *panels[], int count);
+void cursesUnInit(WINDOW *wins[], PANEL *panels[], int count);
+void cursesUpdateSliceDump(slices_evt_t *slicesEvt, slice_t *modifiedSlice);
+void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color);
+void makeWin(WINDOW **win, PANEL **panel, int h, int w, int y, int x, char title[]);
+
+void cursesMainLoop(slices_evt_t *slicesEvt) {
+ WINDOW *wins[CURSESWIN_COUNT];
+ PANEL *panels[CURSESWIN_COUNT];
+ int ch, i;
+ char str[2];
+
+ cursesInit(wins, panels, CURSESWIN_COUNT);
+
+ wattron(wins[CURSESWIN_COUNT-1], COLOR_PAIR(4));
+ mvwprintw(wins[CURSESWIN_COUNT-1], 1, 0, "(F2 to Exit)");
+// wattroff(wins[CURSESWIN_COUNT-1], COLOR_PAIR(4));
+
+ update_panels();
+ doupdate();
+
+ /* Enable worker listener */
+ //FIXME : check pointers ?
+ winUpdateSliceDump=wins[1];
+ slicesEvt->eventListener=cursesUpdateSliceDump;
+
+ while((ch = getch()) != KEY_F(2)) {
+
+ pthread_mutex_lock(&ncursesWriteMutex);
+
+ switch(ch) {
+ case '1':
+ case '2':
+ case '3':
+ str[0]=ch; str[1]='\0'; // int (ascii value+flags) to string
+ i=strtol(str, (char **)NULL, 10); // string to real integer
+ if (i>0 && i<=CURSESWIN_COUNT) {
+ top_panel(panels[i-1]);
+ update_panels();
+ }
+ break;
+ }
+
+ doupdate();
+
+ pthread_mutex_unlock(&ncursesWriteMutex);
+ }
+
+ pthread_mutex_lock(&(slicesEvt->eventListenerMutex));
+ slicesEvt->eventListener=NULL;
+ pthread_mutex_unlock(&(slicesEvt->eventListenerMutex));
+
+ end=1;
+ cursesUnInit(wins, panels, CURSESWIN_COUNT);
+}
+
+int cursesInit(WINDOW *wins[], PANEL *panels[], int count) {
+ int screenH, screenW;
+
+ /* Initialize curses */
+ initscr();
+ start_color();
+ raw();
+ keypad(stdscr, TRUE);
+ noecho();
+
+ /* Initialize all the colors */
+ init_pair(1, COLOR_WHITE, COLOR_BLACK);
+ init_pair(2, COLOR_WHITE, COLOR_BLUE);
+ init_pair(3, COLOR_BLUE, COLOR_BLACK);
+ init_pair(4, COLOR_CYAN, COLOR_BLACK);
+
+ /* Initialize windows and panels */
+ getmaxyx(stdscr, screenH, screenW);
+ if ( screenH < 8 || screenW < 40 ) return 1;
+
+ makeWin(wins+0, panels+0, 3 , screenW, 0 , 0, "Menu");
+ makeWin(wins+1, panels+1, screenH-6 , screenW, 3 , 0, "Main Win");
+ makeWin(wins+2, panels+2, 2 , screenW, screenH-3 , 0, "Commands");
+
+ /* Set up the user pointers to the next panel
+ set_panel_userptr(panels[0], panels[1]);
+ set_panel_userptr(panels[1], panels[2]);
+ set_panel_userptr(panels[2], panels[0]);
+ */
+
+ /* Update the stacking order. 2nd panel will be on top */
+ update_panels();
+
+ return 0;
+}
+
+void cursesUnInit(WINDOW *wins[], PANEL *panels[], int count) {
+ int i;
+
+ for (i=0;i<count;i++) {
+ del_panel(panels[i]);
+ delwin(wins[i]);
+ }
+ endwin();
+}
+
+void cursesUpdateSliceDump(slices_evt_t *slicesEvt, slice_t *modifiedSlice) {
+// char *strProgress="|/-\\";
+// static int progress=0;
+ char *toPrint;
+ address_t blockSize=0;
+ unsigned int charCount=(getmaxx(winUpdateSliceDump)-getbegx(winUpdateSliceDump))*(getmaxy(winUpdateSliceDump)-getbegy(winUpdateSliceDump)+2);
+
+ //TODO : refesh only right parts of the representation
+ pthread_mutex_lock(&ncursesWriteMutex);
+
+ toPrint=slicesDump(slicesEvt->data, &blockSize, charCount, slicesEvt->data->min, slicesEvt->data->max);
+ if (toPrint != NULL) {
+ attron(COLOR_PAIR(4));
+ mvwprintw(winUpdateSliceDump, 1, 0, toPrint);
+// attroff(COLOR_PAIR(4));
+
+ update_panels();
+ doupdate();
+
+ free(toPrint);
+ }
+
+/* sprintf(toPrint, "%c - %p %p", strProgress[progress], slicesEvt, modifiedSlice);
+ progress=(progress+1)%strlen(strProgress);
+*/
+ pthread_mutex_unlock(&ncursesWriteMutex);
+}
+
+
+void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color)
+{ int length, x, y;
+ float temp;
+
+ if(win == NULL)
+ win = stdscr;
+ getyx(win, y, x);
+ if(startx != 0)
+ x = startx;
+ if(starty != 0)
+ y = starty;
+ if(width == 0)
+ width = 80;
+
+ length = strlen(string);
+ temp = (width - length)/ 2;
+ x = startx + (int)temp;
+ wattron(win, color);
+ mvwprintw(win, y, x, "%s", string);
+ wattroff(win, color);
+ refresh();
+}
+
+void makeWin(WINDOW **win, PANEL **panel, int h, int w, int y, int x, char title[]) {
+ int i;
+ *win = newwin(h, w, y, x);
+ mvwprintw(*win, 0, 0, "%s", title);
+ mvwchgat(*win, 0, 0, -1, A_BOLD, 2, NULL);
+ for(i=1;i<h;i++) mvwchgat(*win, i, 0, -1, A_STANDOUT, 1, NULL);
+ *panel = new_panel(*win);
+}
+
diff --git a/src/ddhardrescue.c b/src/ddhardrescue.c
index e10d323..67c061b 100644
--- a/src/ddhardrescue.c
+++ b/src/ddhardrescue.c
@@ -1,39 +1,34 @@
-#include <stdio.h>
-#include <stdlib.h>
#include <signal.h>
-#include <stdint.h>
-#include <string.h>
#include <pthread.h>
+#include <string.h> /* For memset() */
#include "slices_evt.h"
-#include "recover.h"
#include "utils.h"
+#include "recover.h"
+#include "cursesview.h"
// Global variable shared by all threads to say "finish current operation and go away"
int end=0;
-WINDOW *winUpdateSliceDump=NULL;
-static pthread_mutex_t ncursesWriteMutex = PTHREAD_MUTEX_INITIALIZER;
-
-struct threadArgs {
- struct progArgs *progArgs;
- slices_evt_t *slices;
-};
-
void sigHookAbrt() {
end=1;
}
-// Main procedures of each thread
+// Main thread procedures declaration and a struct for passing arguments in a clean way
void *procWorker(void *a);
void *procViewer(void *a);
+struct threadArgs {
+ struct progArgs *progArgs;
+ slices_evt_t *slices;
+};
+
int main(int argc, char **argv) {
// System structures
struct sigaction sa;
pthread_t tWorker;
- // Main data structures
+ // Main data structure
slices_evt_t slices;
// Progam and threads arguments
@@ -42,7 +37,6 @@ int main(int argc, char **argv) {
// Algorithmic needs
int res, i;
-
// Parse command-line arguments
res=parseArgs(argc, argv, &args);
@@ -62,8 +56,8 @@ int main(int argc, char **argv) {
//XXX Remove srand : only for simulation
srand(4);
- // Data structure initialization
- // TODO : provides a standard method to do that ?
+ // Initialize main data structure
+ //XXX provide a method to do that ?
memset(&slices, 0, sizeof(slices));
slices.data=slicesNewSingleton(args.beginSector, args.endSector, S_UNKNOWN);
if ( slices.data == NULL ) {
@@ -71,7 +65,6 @@ int main(int argc, char **argv) {
}
slices.data->min=args.beginSector;
slices.data->max=args.endSector;
-
res=pthread_mutex_init(&(slices.eventListenerMutex), NULL);
if (res!=0) {
return 4;
@@ -91,13 +84,13 @@ int main(int argc, char **argv) {
// Ncurses interface run in the main thread
(void) procViewer((void*)&tArgs);
- // Thread join point
+ // Thread join point (wait worker thread when viewer is done)
(void) pthread_join(tWorker, NULL);
//Final dump of datas
address_t blockSize=0;
char *dump;
- dump=slicesDump(slices.data, &blockSize, 1000, args.beginSector, args.endSector);
+ dump=slicesDump(slices.data, &blockSize, 10000, args.beginSector, args.endSector);
if (dump != NULL) {
puts(dump);
free(dump);
@@ -109,6 +102,7 @@ int main(int argc, char **argv) {
//Resources desallocation
(void) pthread_mutex_destroy(&(slices.eventListenerMutex));
+ //XXX Method for that
slice_t *curr, *toFree;
i=0; curr=slices.data->first;
while (curr!=NULL) {
@@ -125,6 +119,7 @@ int main(int argc, char **argv) {
void *procWorker(void *a) {
struct threadArgs *tArgs = (struct threadArgs *)a;
+ //XXX : We will need something more controlable than just a blocking call to the main algorithm
recover(
tArgs->slices,
tArgs->progArgs->src,
@@ -135,87 +130,14 @@ void *procWorker(void *a) {
return a;
}
-void cursesUpdateSliceDump(slices_evt_t *slicesEvt, slice_t *modifiedSlice) {
-// char *strProgress="|/-\\";
-// static int progress=0;
- char *toPrint;
- address_t blockSize=0;
- unsigned int charCount=(getmaxx(winUpdateSliceDump)-getbegx(winUpdateSliceDump))*(getmaxy(winUpdateSliceDump)-getbegy(winUpdateSliceDump)+2);
-
-//FIXME : do that realy
- pthread_mutex_lock(&ncursesWriteMutex);
- toPrint=slicesDump(slicesEvt->data, &blockSize, charCount, slicesEvt->data->min, slicesEvt->data->max);
- if (toPrint != NULL) {
- attron(COLOR_PAIR(4));
- mvwprintw(winUpdateSliceDump, 1, 0, toPrint);
-// attroff(COLOR_PAIR(4));
-
- update_panels();
- doupdate();
-
- free(toPrint);
- }
-
-/* sprintf(toPrint, "%c - %p %p", strProgress[progress], slicesEvt, modifiedSlice);
- progress=(progress+1)%strlen(strProgress);
-*/
- pthread_mutex_unlock(&ncursesWriteMutex);
-}
-
-#define CURSESWIN_COUNT 3
void *procViewer(void *a) {
- WINDOW *wins[CURSESWIN_COUNT];
- PANEL *panels[CURSESWIN_COUNT];
- int ch, i;
- char str[2];
struct threadArgs *tArgs = (struct threadArgs *)a;
-
-
- cursesInit(wins, panels, CURSESWIN_COUNT);
-
- wattron(wins[CURSESWIN_COUNT-1], COLOR_PAIR(4));
- mvwprintw(wins[CURSESWIN_COUNT-1], 1, 0, "(F2 to Exit)");
-// wattroff(wins[CURSESWIN_COUNT-1], COLOR_PAIR(4));
- update_panels();
- doupdate();
-
- /* Enable worker listener */
- //FIXME : check pointers ?
- winUpdateSliceDump=wins[1];
- tArgs->slices->eventListener=cursesUpdateSliceDump;
-
- while((ch = getch()) != KEY_F(2)) {
-
- pthread_mutex_lock(&ncursesWriteMutex);
-
- switch(ch) {
- case '1':
- case '2':
- case '3':
- str[0]=ch; str[1]='\0'; // int (ascii value+flags) to string
- i=strtol(str, (char **)NULL, 10); // string to real integer
- if (i>0 && i<=CURSESWIN_COUNT) {
- top_panel(panels[i-1]);
- update_panels();
- }
- break;
- }
-
- doupdate();
-
- pthread_mutex_unlock(&ncursesWriteMutex);
- }
-
- pthread_mutex_lock(&(tArgs->slices->eventListenerMutex));
- tArgs->slices->eventListener=NULL;
- pthread_mutex_unlock(&(tArgs->slices->eventListenerMutex));
-
- end=1;
- cursesUnInit(wins, panels, CURSESWIN_COUNT);
+ cursesMainLoop(
+ tArgs->slices
+ );
return a;
}
-
diff --git a/src/recover.c b/src/recover.c
index e6e574a..2131542 100644
--- a/src/recover.c
+++ b/src/recover.c
@@ -1,10 +1,10 @@
-#include <errno.h>
-#include <stdio.h>
#include "recover.h"
-// Just for sleep
-#include <unistd.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;
@@ -62,21 +62,24 @@ void recover(slices_evt_t *slicesEvt, char *src, char *dst, char *ddOpts) {
break;
case 3:
// Internal error of sliceSlpit because this set of parameters prevent split by 3
- exit(5); // TODO
+ exit(6); // TODO
break;
case -1:
// Memory error
- exit(4); //TODO
+ exit(5); //TODO
break;
default:
// API error, all necessary cases are already listed
- exit(6); // TODO
+ 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;
@@ -117,7 +120,8 @@ int tryRecoverUntilError(slice_t *sliceToRead, address_t *firstError, char *src,
*firstError=error;
}
- usleep(10000);
+ // Keep things humanly understandable (to be removed when real reads will be done)
+ //usleep(10000);
return res;
}
diff --git a/src/slices.c b/src/slices.c
index d077454..e84facf 100644
--- a/src/slices.c
+++ b/src/slices.c
@@ -1,13 +1,10 @@
-#include <string.h>
#include "slices.h"
-//for perror
-#include <stdio.h>
-
-//FIXME : avoir une méthode destroy pour les slices qui free le mutex
+#include <string.h>
+#include <stdio.h> /* For perror() */
-inline int min(int a, int b) { return (a<b)?a:b; }
-inline int max(int a, int b) { return (a>b)?a:b; }
+#define MIN(a, b) (((a) < (b)) ? (a) : (b))
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
slice_t *sliceNew(address_t begin, address_t end, sliceStatus_t status, slice_t *next) {
slice_t *s;
@@ -221,8 +218,8 @@ char *slicesDump(slices_t *slices, address_t *blockSize, unsigned int charCount,
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);
+ sb=MAX(0, (curr->begin - begin) / *blockSize);
+ se=MIN((curr->end - begin) / *blockSize, charCount-1);
// Debug assertion
if (sb >= charCount || se >= charCount) {
diff --git a/src/slices_evt.c b/src/slices_evt.c
index 9174903..4ed07c6 100644
--- a/src/slices_evt.c
+++ b/src/slices_evt.c
@@ -1,9 +1,9 @@
-//XXX Suprress that when event queue is terminated
+#include "slices_evt.h"
+
#include <stdio.h>
#include <pthread.h>
-#include "slices_evt.h"
-
+// Event-aware version of sliceSplit (reusing it, of course)
int sliceEvtSplit(slices_evt_t *slicesEvt, slice_t *initialSlice, address_t splitAt, sliceStatus_t statusBefore, sliceStatus_t statusAt, sliceStatus_t statusAfter) {
int res;
res=sliceSplit(slicesEvt->data, initialSlice, splitAt, statusBefore, statusAt, statusAfter);
@@ -27,8 +27,3 @@ int sliceEvtSplit(slices_evt_t *slicesEvt, slice_t *initialSlice, address_t spli
return res;
}
-/*
-void sliceEvtPutEvent(slices_evt_t *slicesEvt, slice_t *modifiedSlice) {
- printf("sliceEvtPutEvent %p %p\n", slicesEvt, modifiedSlice);
-}
-*/
diff --git a/src/utils.c b/src/utils.c
index 86917ae..7305b22 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -25,81 +25,3 @@ void usage(char *progname) {
", progname);
}
-void print_in_middle(WINDOW *win, int starty, int startx, int width, char *string, chtype color)
-{ int length, x, y;
- float temp;
-
- if(win == NULL)
- win = stdscr;
- getyx(win, y, x);
- if(startx != 0)
- x = startx;
- if(starty != 0)
- y = starty;
- if(width == 0)
- width = 80;
-
- length = strlen(string);
- temp = (width - length)/ 2;
- x = startx + (int)temp;
- wattron(win, color);
- mvwprintw(win, y, x, "%s", string);
- wattroff(win, color);
- refresh();
-}
-
-void makeWin(WINDOW **win, PANEL **panel, int h, int w, int y, int x, char title[]) {
- int i;
- *win = newwin(h, w, y, x);
- mvwprintw(*win, 0, 0, "%s", title);
- mvwchgat(*win, 0, 0, -1, A_BOLD, 2, NULL);
- for(i=1;i<h;i++) mvwchgat(*win, i, 0, -1, A_STANDOUT, 1, NULL);
- *panel = new_panel(*win);
-}
-
-
-int cursesInit(WINDOW *wins[], PANEL *panels[], int count) {
- int screenH, screenW;
-
- /* Initialize curses */
- initscr();
- start_color();
- raw();
- keypad(stdscr, TRUE);
- noecho();
-
- /* Initialize all the colors */
- init_pair(1, COLOR_WHITE, COLOR_BLACK);
- init_pair(2, COLOR_WHITE, COLOR_BLUE);
- init_pair(3, COLOR_BLUE, COLOR_BLACK);
- init_pair(4, COLOR_CYAN, COLOR_BLACK);
-
- /* Initialize windows and panels */
- getmaxyx(stdscr, screenH, screenW);
- if ( screenH < 8 || screenW < 40 ) return 1;
-
- makeWin(wins+0, panels+0, 3 , screenW, 0 , 0, "Menu");
- makeWin(wins+1, panels+1, screenH-6 , screenW, 3 , 0, "Main Win");
- makeWin(wins+2, panels+2, 2 , screenW, screenH-3 , 0, "Commands");
-
- /* Set up the user pointers to the next panel
- set_panel_userptr(panels[0], panels[1]);
- set_panel_userptr(panels[1], panels[2]);
- set_panel_userptr(panels[2], panels[0]);
- */
-
- /* Update the stacking order. 2nd panel will be on top */
- update_panels();
-
- return 0;
-}
-
-void cursesUnInit(WINDOW *wins[], PANEL *panels[], int count) {
- int i;
-
- for (i=0;i<count;i++) {
- del_panel(panels[i]);
- delwin(wins[i]);
- }
- endwin();
-}