Example #1
0
    def redo(self, dryrun):
        cur_pn = kutil.iget("/mnt/retro/trunk", self.ob.ret.inode.ino)

        if not dryrun:
            if self.ob.args["flags"] & os.O_TRUNC:
                dbg.syscall("%d: %s" % (self.ob.ticket, self.ob))
                dbg.syscall("creating empty file, %s" % cur_pn)

                open(cur_pn, "w").close()
Example #2
0
    def rollback(self, c):
        assert (isinstance(c, FileCheckpoint))

        # XXX. hack to ignore /proc entries
        if any(c.d_pn.startswith(d) for d in ["/proc", "/dev"]):
            return

        cp_ino = None  # ino of the directory _entry_

        cpn = c.pn()
        if cpn:
            cp_ino = self._get_inode(cpn, self.name_in_dir)

        dev_pn = kutil.fsget(self.dev)
        dir_pn = kutil.iget(dev_pn, self.ino)

        cur_ino = self._get_inode(dir_pn, self.name_in_dir)

        if cp_ino == cur_ino:
            return

        if cur_ino is not None:
            # backup
            src = os.path.join(dir_pn, self.name_in_dir)
            dst = os.path.join(dev_pn, ".inodes", str(cur_ino))

            dbg.infom("!", "#R<rename#>: %s -> %s" % (src, dst))
            dbg.infom("readers %s" % str(self.readers))
            dbg.infom("writers %s" % str(self.writers))

            if not runopts.dryrun:
                os.rename(src, dst)

        if cp_ino is not None:
            src = kutil.iget(dev_pn, cp_ino)
            dst = os.path.join(dir_pn, self.name_in_dir)

            dbg.infom("!", "#R<link#>: %s -> %s" % (src, dst))

            if not runopts.dryrun:
                os.link(src, dst)

        kutil.dcache_flush()
Example #3
0
    def get_file_dev_ino(self):
        """Get the (dev, ino) that this directory entry currently points
    to.

    Should be the same (dev, ino) pair that os.stat() would return
    when called on the pathname of this file."""

        dev_pn = kutil.fsget(self.dev)
        dir_pn = kutil.iget(dev_pn, self.ino)

        cur_ino = self._get_inode(dir_pn, self.name_in_dir)
        return (self.dev, cur_ino)
Example #4
0
    def __init__(self, tic, tac, dev, ino):
        fs = kutil.fsget(dev)
        src = kutil.iget(fs, ino)
        dst = os.path.join(fs, ".inodes", str(ino) + "-" + str(tic[0]))

        shutil.copy(src, dst)

        self.name = ('File', dev, ino, dst)
        self.dev = dev
        self.ino = ino
        self.snap = dst

        super(FileContentCheckpoint, self).__init__(tic, tac)
Example #5
0
    def rollback(self, c):
        assert (isinstance(c, FileCheckpoint))

        # XXX. hack to ignore /proc and /dev entries
        if any(c.d_pn.startswith(d) for d in ["/proc", "/dev"]):
            return None

        cpn = c.pn()

        try:
            dev_pn = kutil.fsget(self.dev)
            ino_pn = kutil.iget(dev_pn, self.ino)
        except kutil.MissingInode:
            if cpn is None:
                return

        dbg.infom("!", "#R<rollback#> %s(%s) -> %s" % (self.ino, ino_pn, cpn))
        dbg.infom("readers %s" % str(self.readers))
        dbg.infom("writers %s" % str(self.writers))

        if runopts.dryrun:
            return

        cstat = os.lstat(cpn) if cpn else None
        istat = os.lstat(ino_pn)

        if (cstat
                and stat.S_IFMT(istat.st_mode) != stat.S_IFMT(cstat.st_mode)):
            raise Exception('inode changed types', cpn, ino_pn, cstat, istat)

        if stat.S_ISREG(istat.st_mode):
            if cpn:
                with open(cpn, 'r') as f1:
                    f1data = f1.read()
            else:
                f1data = ''
            with open(ino_pn, 'r') as f2:
                f2data = f2.read()
            if f1data != f2data:
                with open(ino_pn, 'w') as f2:
                    f2.write(f1data)
        elif stat.S_ISLNK(istat.st_mode):
            pass  ## no way to change existing symlink
        elif stat.S_ISDIR(istat.st_mode):
            # XXX.
            pass
        else:
            raise Exception('cannot handle inode type',
                            stat.S_IFMT(istat.st_mode))
Example #6
0
    def redo(self, dryrun):
        cur_pn = kutil.iget("/mnt/retro/trunk", self.ob.args["fd"].inode.ino)

        dbg.syscall("%d: %s" % (self.ob.ticket, self.ob))
        dbg.syscall("re-writing to fd:%s" % cur_pn)

        if not dryrun:
            offset = self.ob.args["fd"].offset

            f = open(cur_pn, "r+")
            # append
            if offset == -1:
                f.seek(0, os.SEEK_END)
            else:
                f.seek(offset)
            f.write(self.ob.args["buf"])
            f.close()
Example #7
0
 def pn(self):
     """Get the pathname to the snapshot of the file."""
     try:
         return kutil.iget(self.d_pn, self.ino)
     except kutil.MissingInode:
         return None
Example #8
0
def find_snapshot(ticket, inode, conn):
    logging.info("finding %s@%d" % (inode, ticket))

    # fetch from the snapshot archive
    try:
        os.mkdir(path.join(snaproot, ".snap"))
    except:
        pass
    snapfile = path.join(snaproot, ".snap", "%s.%d" % (inode.ino, ticket))
    if path.exists(snapfile):
        return snapfile

    t = ticket
    while t >= 0:
        # fetch from the fresh root (initial check point)
        if t == 0:
            return kutil.iget(freshroot, inode.ino)

        # search history
        t = t - 1

        # apply current system calls
        r = record_by_ticket(t, conn)

        # filtering
        if r.name == "open" and r.ret.inode == inode:
            if r.args["flags"] & os.O_TRUNC:
                logging.info("@%d <- empty %s@%d" % (ticket, inode, r.ticket))
                open(snapfile, "w").close()
            else:
                logging.info("@%d <- %s@%d" % (ticket, inode, r.ticket))
                logging.info("	by %s" % r)

                parent = find_snapshot(r.ticket, inode, conn)
                copyfile(parent, snapfile)

        elif r.name == "write" and r.args["fd"].inode == inode:
            logging.info("@%d <- %s@%d" % (ticket, inode, r.ticket))
            logging.info("	by %s" % r)

            parent = find_snapshot(r.ticket, inode, conn)
            copyfile(parent, snapfile)

            offset = r.args["fd"].offset

            f = open(snapfile, "r+")
            # append
            if offset == -1:
                f.seek(0, os.SEEK_END)
            else:
                f.seek(offset)
            f.write(r.args["buf"])
            f.close()

        elif r.name == "unlink":
            # TODO restore the file from the .inodes
            pass
        else:
            continue

        return snapfile