Bug #1319 » undo.patch
undo/undo.c 2009-03-29 03:19:33 +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);
|
||
static void doiterate(const char *filename, const char *outFileName,
|
||
const char *outFilePostfix, int flags,
|
||
struct hammer_ioc_hist_entry ts1,
|
||
struct hammer_ioc_hist_entry ts2,
|
||
enum undo_cmd cmd, enum undo_type type);
|
||
static void dogenerate(const char *filename, const char *outFileName,
|
||
const char *outFilePostfix,
|
||
... | ... | |
static void collect_dir_history(const char *filename, int *error,
|
||
struct undo_hist_entry_rb_tree *dir_tree);
|
||
static void clean_tree(struct undo_hist_entry_rb_tree *tree);
|
||
static hammer_tid_t parse_delta_time(const char *timeStr);
|
||
static hammer_tid_t parse_delta_time(const char *timeStr, int *flags,
|
||
int ind_flag);
|
||
static void runcmd(int fd, const char *cmd, ...);
|
||
static char *timestamp(hammer_ioc_hist_entry_t hen);
|
||
static void usage(void);
|
||
... | ... | |
struct hammer_ioc_hist_entry ts1;
|
||
struct hammer_ioc_hist_entry ts2;
|
||
int c;
|
||
int count_t;
|
||
int flags;
|
||
bzero(&ts1, sizeof(ts1));
|
||
... | ... | |
cmd = CMD_DUMP;
|
||
type = TYPE_FILE;
|
||
count_t = 0;
|
||
flags = 0;
|
||
while ((c = getopt(ac, av, "adDiuvo:t:")) != -1) {
|
||
switch(c) {
|
||
... | ... | |
outFileName = optarg;
|
||
break;
|
||
case 't':
|
||
if (ts1.tid && ts2.tid)
|
||
usage();
|
||
else if (ts1.tid == 0)
|
||
ts1.tid = parse_delta_time(optarg);
|
||
++count_t;
|
||
if (count_t == 1)
|
||
ts1.tid = parse_delta_time(optarg, &flags,
|
||
UNDO_FLAG_SETTID1);
|
||
else if (count_t == 2)
|
||
ts2.tid = parse_delta_time(optarg, &flags,
|
||
UNDO_FLAG_SETTID2);
|
||
else
|
||
ts2.tid = parse_delta_time(optarg);
|
||
usage();
|
||
break;
|
||
default:
|
||
usage();
|
||
... | ... | |
ac -= optind;
|
||
av += optind;
|
||
flags = 0;
|
||
if (ac > 1)
|
||
flags |= UNDO_FLAG_MULT;
|
||
... | ... | |
while (ac) {
|
||
doiterate(*av, outFileName, outFilePostfix,
|
||
flags, ts1, cmd, type);
|
||
flags, ts1, ts2, cmd, type);
|
||
++av;
|
||
--ac;
|
||
}
|
||
... | ... | |
/*
|
||
* 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.
|
||
... | ... | |
doiterate(const char *filename, const char *outFileName,
|
||
const char *outFilePostfix, int flags,
|
||
struct hammer_ioc_hist_entry ts1,
|
||
struct hammer_ioc_hist_entry ts2,
|
||
enum undo_cmd cmd, enum undo_type type)
|
||
{
|
||
struct undo_hist_entry_rb_tree dir_tree;
|
||
struct undo_hist_entry_rb_tree tse_tree;
|
||
struct undo_hist_entry *tse1;
|
||
struct undo_hist_entry *tse2;
|
||
struct hammer_ioc_hist_entry ts2, tid_max;
|
||
struct hammer_ioc_hist_entry tid_max;
|
||
char *path = NULL;
|
||
int i;
|
||
int fd;
|
||
... | ... | |
}
|
||
}
|
||
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) {
|
||
... | ... | |
static
|
||
hammer_tid_t
|
||
parse_delta_time(const char *timeStr)
|
||
parse_delta_time(const char *timeStr, int *flags, int ind_flag)
|
||
{
|
||
hammer_tid_t tid;
|
||
tid = strtoull(timeStr, NULL, 0);
|
||
if (timeStr[0] == '+')
|
||
++timeStr;
|
||
if (timeStr[0] >= '0' && timeStr[0] <= '9' && timeStr[1] != 'x')
|
||
*flags |= ind_flag;
|
||
return(tid);
|
||
}
|
||