Bug #1319 » undo.patch
undo/undo.c 2009-03-22 18:33:21 +0000 | ||
---|---|---|
#define UNDO_FLAG_MULT 0x0001
|
||
#define UNDO_FLAG_INOCHG 0x0002
|
||
#define UNDO_FLAG_SETTID1 0x0004
|
||
#define UNDO_FLAG_SETTID2 0x0008
|
||
static int undo_hist_entry_compare(struct undo_hist_entry *he1,
|
||
struct undo_hist_entry *he2);
|
||
... | ... | |
enum undo_type type;
|
||
struct hammer_ioc_hist_entry ts1;
|
||
struct hammer_ioc_hist_entry ts2;
|
||
int c;
|
||
int c, i;
|
||
int flags;
|
||
bzero(&ts1, sizeof(ts1));
|
||
... | ... | |
cmd = CMD_DUMP;
|
||
type = TYPE_FILE;
|
||
flags = 0;
|
||
while ((c = getopt(ac, av, "adDiuvo:t:")) != -1) {
|
||
i = -1;
|
||
while ((c = getopt(ac, av, "adDiuvo:t:0123456789")) != -1) {
|
||
if (c >= '0' && c <= '9') {
|
||
c -= '0';
|
||
i = (i >= 0) ? i*10 + c : c;
|
||
continue;
|
||
} else if (i >= 0) INDEX_ARG: {
|
||
/* set placeholder IDs for later lookup */
|
||
if (ts1.tid == 0 && !(flags & UNDO_FLAG_SETTID1))
|
||
ts1.tid = i, flags |= UNDO_FLAG_SETTID1;
|
||
else if (ts2.tid == 0 && !(flags & UNDO_FLAG_SETTID2))
|
||
ts2.tid = i, flags |= UNDO_FLAG_SETTID2;
|
||
else
|
||
usage();
|
||
i = -1;
|
||
if (c == -1)
|
||
/* got here after loop */
|
||
break;
|
||
}
|
||
switch(c) {
|
||
case 'd':
|
||
if (type != TYPE_FILE)
|
||
... | ... | |
outFileName = optarg;
|
||
break;
|
||
case 't':
|
||
if (ts1.tid && ts2.tid)
|
||
usage();
|
||
else if (ts1.tid == 0)
|
||
if (ts1.tid == 0 && !(flags & UNDO_FLAG_SETTID1))
|
||
ts1.tid = parse_delta_time(optarg);
|
||
else
|
||
else if (ts2.tid == 0 && !(flags & UNDO_FLAG_SETTID2))
|
||
ts2.tid = parse_delta_time(optarg);
|
||
else
|
||
usage();
|
||
break;
|
||
default:
|
||
usage();
|
||
... | ... | |
break;
|
||
}
|
||
}
|
||
if (i >= 0)
|
||
/* last argument numerical index */
|
||
goto INDEX_ARG;
|
||
/*
|
||
* Option validation
|
||
... | ... | |
ac -= optind;
|
||
av += optind;
|
||
flags = 0;
|
||
if (ac > 1)
|
||
flags |= UNDO_FLAG_MULT;
|
||
... | ... | |
/*
|
||
* Iterate through a file's history. If cmd == CMD_DUMP we take the
|
||
* next-to-last transaction id. Otherwise if cmd == CMD_ITERATEALL
|
||
* we scan all transaction ids.
|
||
* next-to-last transaction id unless another given. Otherwise if
|
||
* cmd == CMD_ITERATEALL we scan all transaction ids.
|
||
*
|
||
* Also iterate through the directory's history to locate other inodes that
|
||
* used the particular file name.
|
||
... | ... | |
}
|
||
}
|
||
if (cmd == CMD_DUMP) {
|
||
/*
|
||
* Single entry, most recent prior to current
|
||
*/
|
||
if (ts1.tid == 0 && RB_EMPTY(&tse_tree)) {
|
||
if ((ts1.tid == 0 ||
|
||
flags & (UNDO_FLAG_SETTID1|UNDO_FLAG_SETTID2)) &&
|
||
RB_EMPTY(&tse_tree)) {
|
||
if ((fd = open(filename, O_RDONLY)) > 0) {
|
||
collect_history(fd, &error, &tse_tree);
|
||
close(fd);
|
||
}
|
||
}
|
||
/*
|
||
* Find entry if tid set to placeholder index
|
||
*/
|
||
if (flags & UNDO_FLAG_SETTID1){
|
||
tse1 = RB_MAX(undo_hist_entry_rb_tree, &tse_tree);
|
||
while (tse1 && ts1.tid--)
|
||
tse1 = RB_PREV(undo_hist_entry_rb_tree,
|
||
&tse_tree, tse1);
|
||
if (tse1)
|
||
ts1 = tse1->tse;
|
||
else
|
||
ts1.tid = 0;
|
||
}
|
||
if (flags & UNDO_FLAG_SETTID2){
|
||
tse2 = RB_MAX(undo_hist_entry_rb_tree, &tse_tree);
|
||
while (tse2 && ts2.tid--)
|
||
tse2 = RB_PREV(undo_hist_entry_rb_tree,
|
||
&tse_tree, tse2);
|
||
if (tse2)
|
||
ts2 = tse2->tse;
|
||
else
|
||
ts2.tid = 0;
|
||
}
|
||
/*
|
||
* Single entry, most recent prior to current
|
||
*/
|
||
if (ts1.tid == 0) {
|
||
tse2 = RB_MAX(undo_hist_entry_rb_tree, &tse_tree);
|
||
if (tse2) {
|