Bug #1319 » undo.patch
| undo/undo.c 2009-03-23 00:59:58 +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, oi; 
   | 
||
| 
     	int flags; 
   | 
||
| 
     	bzero(&ts1, sizeof(ts1)); 
   | 
||
| ... | ... | |
| 
     	cmd = CMD_DUMP; 
   | 
||
| 
     	type = TYPE_FILE; 
   | 
||
| 
     	flags = 0; 
   | 
||
| 
     	while ((c = getopt(ac, av, "adDiuvo:t:")) != -1) { 
   | 
||
| 
     	i = -1; 
   | 
||
| 
     	oi = optind; 
   | 
||
| 
     	while ((c = getopt(ac, av, "adDiuvo:t:0123456789")) != -1) { 
   | 
||
| 
     		if (c >= '0' && c <= '9') { 
   | 
||
| 
     			c -= '0'; 
   | 
||
| 
     			i = (i >= 0) ? i*10 + c : c; 
   | 
||
| 
     			if (oi != optind) { 
   | 
||
| 
     				c = 0; 
   | 
||
| 
     				goto INDEX_ARG; 
   | 
||
| 
     			} 
   | 
||
| 
     			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; 
   | 
||
| 
     			oi = optind; 
   | 
||
| 
     			if (c == 0) 
   | 
||
| 
     				continue; 
   | 
||
| 
     			if (c == -1) 
   | 
||
| 
     				/* got here after loop */ 
   | 
||
| 
     				break; 
   | 
||
| 
     		} else 
   | 
||
| 
     			oi = optind; 
   | 
||
| 
     		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) { 
   | 
||