예제 #1
0
    def fetch(self):

        self.logger.debug("redis_ns_entry.fetch %s" % self.path)

        path = self.path

        try:
            self.node = self.cache.get(NODE + ':' + path)
            self.data = self.cache.get(DATA + ':' + path)

            if self.node[TYPE] == DIR:
                self.kids = self.cache.get(KIDS + ':' + path)

            self.valid = True
            return

        except Exception:
            # some cache ops failed, so we need to properly fetch data.  We
            # simply fetch all of it
            pass

        try:
            p = self.r.pipeline()
            p.hgetall(NODE + ':' + path)
            p.hgetall(DATA + ':' + path)
            p.smembers(KIDS + ':' + path)
            values = p.execute()

            if len(values) != 3:
                self.valid = False
                return

            self.valid = True

            # FIXME: check val types
            self.node = values[0]
            self.data = values[1]
            self.kids = values[2]  # will be 'None' for non-DIR entries

            if len(self.node) == 0:
                self.valid = False
                raise rse.IncorrectState("backend entry gone or corrupted")

            # cache our newly found entries
            self.cache.set(NODE + ':' + path, self.node)
            self.cache.set(DATA + ':' + path, self.data)
            self.cache.set(KIDS + ':' + path, self.kids)

            # fetched from redis ok
            self.valid = True

        except Exception as e:
            self.valid = False
            raise rse.IncorrectState("backend entry gone or corrupted: %s" %
                                     str(e))
예제 #2
0
    def list(self):

        if not self.node[TYPE] == DIR:
            raise rse.IncorrectState("list() only supported on directories")

        self.fetch()

        return self.kids
예제 #3
0
    def create(self, flags=0):
        """
        This assumes that the target entry does not exist.  If flags contains
        CREATE though, we should not raise an exception if it in fact does not.
        """

        path = self.path

        if self.valid:
            raise rse.IncorrectState(
                "mkdir on %s fails, entry already exists" % path)

        # FIXME: need to ensure this via a WATCH call.

        self.logger.debug("redis_ns_entry.create %s" % path)

        name = redis_ns_name(path)
        parent = redis_ns_parent(path)

        now = time.time()

        self.node['mtime'] = now
        self.node['ctime'] = now

        p = self.r.pipeline()
        # FIXME: add guard
        if len(self.node): p.hmset(NODE + ':' + path, self.node)
        if len(self.data): p.hmset(DATA + ':' + path, self.data)
        if len(self.kids): p.hmset(KIDS + ':' + path, self.kids)

        # add entry as  kid to parent
        # FIXME: avoid duplicated entries!
        if path != '/':
            p.sadd(KIDS + ':' + parent, path)

        # add new index entries
        for key in self.data:
            val = self.data[key]
            p.sadd(KEYS + ':' + str(key), path)
            p.sadd(VALS + ':' + str(val), path)

        # FIXME: eval vals
        p.execute()

        # issue notification about entry creation to parent dir
        self.logger.debug("pub CREATE %s [%s]" % (parent, name))
        self.r.publish(MON, "CREATE %s [%s]" % (parent, name))

        # refresh cache state
        self.cache.set(NODE + ':' + path, self.node)
        self.cache.set(DATA + ':' + path, self.data)
        self.cache.set(KIDS + ':' + path, self.kids)

        self.valid = True
예제 #4
0
    def mkdir(self, flags):
        """
        Don't call this  directly -- to create a dir, call opendir with
        'create'/'create_parents' and 'exclusive'.  If called, assumes that
        entry is invalid (and thus does not yet exist).
        """

        path = self.path

        if self.valid:
            raise rse.IncorrectState("mkdir %s failed, entry exists" % path)

        self.logger.debug("redis_ns_entry.mkdir %s" % path)

        # if / does not exist, we always create it - no need for checks
        if path != '/':

            # if CREATE_PARENTS is set, we need to check all parents, and need
            # to create them as needed.  We go top down, and terminate once
            # a parent is found
            if c.CREATE_PARENTS & flags:

                # this will recursively travel down the chimney hole, and stop
                # whenever it finds an existing  directory
                parent = redis_ns_parent(path)
                pe = redis_ns_entry.opendir(self.r, parent, c.CREATE_PARENTS)

            else:
                # if 'CREATE_PARENTS is not set, parent must exist.
                parent = redis_ns_parent(path)
                pe = None

                try:
                    pe = redis_ns_entry(self.r, parent)
                    pe.fetch()

                except Exception as e:
                    raise rse.BadParameter(
                        "mkdir %s fails, parent does not exist: %s" %
                        (path, e))

                if not pe.is_dir():
                    raise rse.BadParameter(
                        "mkdir %s fails, parent is no directory: %s" %
                        (path, parent))

        self.node[TYPE] = DIR
        self.create(flags)