示例#1
0
 def __rtypes_query__(self, pcc_types, **parameters):
     self.start_transaction()
     cursor = self.cursor()
     result = RecursiveDictionary()
     try:
         for pcc_type in pcc_types:
             metadata = pcc_type.__rtypes_metadata__
             # if PCCCategories.impure in metadata.categories:
             #     continue
             # if PCCCategories.pcc_set not in metadata.categories:
             #     continue
             dims_order, query = convert_to_read_query(pcc_type)
             cursor.execute(query)
             # metadata = pcc_type.__rtypes_metadata__
             grp_changes = result.setdefault(metadata.groupname,
                                             RecursiveDictionary())
             for row in cursor.fetchall():
                 dim_dict = dict(zip(dims_order, row))
                 primarykey_value = dim_dict[metadata.primarykey.name]
                 dim_changes = convert_to_dim_map(dim_dict)
                 obj_changes = grp_changes.setdefault(
                     primarykey_value, RecursiveDictionary())
                 obj_changes.setdefault(
                     "types",
                     RecursiveDictionary())[metadata.name] = Event.New
                 obj_changes.setdefault(
                     "dims", RecursiveDictionary()).rec_update(dim_changes)
     except errors.Error as err:
         self.rollback()
         # LOGGER.error("Exeception %s seen during query", repr(err))
         result = RecursiveDictionary()
     self.commit()
     cursor.close()
     return {"gc": result}, True
class store(object):
    def __init__(self):
        self.logger = logging.getLogger(__name__)
        self.__objects = RecursiveDictionary()
        self._changes = RecursiveDictionary({
            "new": RecursiveDictionary(),
            "deleted": RecursiveDictionary()
        })
        self.__deleted = set()

    def add_types(self, types):
        for tp in types:
            self.__objects.setdefault(tp, RecursiveDictionary())

    def get(self, tp):
        return self.__objects[tp].values()

    def get_one(self, tp, id):
        if id in self.__objects[tp]:
            return self.__objects[tp][id]
        else:
            raise Exception("Could not find object %s of type %s" % (id, tp))

    def frame_insert(self, tp, id, objjson):
        obj = create_tracking_obj(tp, objjson, self.__objects, False, False)
        obj._primarykey = id
        obj.__primarykey__ = id
        self.__objects.setdefault(tp, RecursiveDictionary())[id] = obj
        obj.__start_tracking__ = True
        return obj

    def frame_insert_all(self, tp, objjsons):
        ret = []
        for id, obj in objjsons.items():
            ret.append(self.frame_insert(tp, id, obj))
        return ret

    def insert(self, obj):
        objjson = create_jsondict(obj)
        self._changes["new"].setdefault(obj, RecursiveDictionary()).setdefault(
            obj.__primarykey__, RecursiveDictionary()).rec_update(objjson)
        self.__objects.setdefault(
            obj.__class__, RecursiveDictionary())[obj.__primarykey__] = obj
        if hasattr(obj.__class__,
                   "__pcc_projection__") and obj.__class__.__pcc_projection__:

            class _dummy(object):
                pass

            new_obj = _dummy()
            new_obj.__class__ = obj.__class__.__ENTANGLED_TYPES__[0]
            for dimension in new_obj.__dimensions__:
                if hasattr(obj, dimension._name):
                    setattr(new_obj, dimension._name,
                            getattr(obj, dimension._name))
            self.__objects.setdefault(new_obj.__class__,
                                      RecursiveDictionary()).setdefault(
                                          new_obj.__primarykey__,
                                          []).append(new_obj)
        if (hasattr(obj, "__dependent_type__")):
            obj.__class__ = obj
        obj.__start_tracking__ = True

    def insert_all(self, objs):
        for obj in objs:
            self.insert(obj)

    def frame_delete_with_id(self, tp, obj_id):
        obj = self.get_one(tp, obj_id)
        self.__deleted.add((tp, obj))

    def delete(self, tp, obj):
        if tp in self.__objects and obj.__primarykey__ in self.__objects[tp]:
            self._changes["deleted"].setdefault(obj.__class__,
                                                set()).add(obj.__primarykey__)
        self.__deleted.add((tp, obj))

    def delete_with_id(self, tp, obj_id):
        obj = self.get_one(tp, obj_id)
        self.delete(tp, obj)

    def __flush_derived_objs(self):
        types = self.__objects.keys()
        for tp in types:
            if not tp.__PCC_BASE_TYPE__:
                self.__objects[tp] = RecursiveDictionary()

    def clear_all(self, t=None):
        self.clear_changes()
        self.clear_incoming_record()
        if not t:
            for tp in self.__objects.keys():
                self.__objects[tp] = RecursiveDictionary()
        else:
            self.__objects[t] = RecursiveDictionary()

    def clear_changes(self):
        self._changes["new"].clear()
        if currentThread().getName() in rtype_property.change_tracker:
            rtype_property.change_tracker[currentThread().getName()].clear()
        for tp, obj in self.__deleted:
            del self.__objects[tp][obj.__primarykey__]
        self.__deleted.clear()
        self.__flush_derived_objs()
        self._changes["deleted"] = {}

    def get_changes(self):
        mod = rtype_property.change_tracker[
            currentThread().getName()] if currentThread().getName(
            ) in rtype_property.change_tracker else {}
        for tp in self._changes["deleted"]:
            for id in self._changes["deleted"][tp]:
                if tp in mod and id in mod[tp]:
                    del mod[tp][id]
        for tp in self._changes["new"]:
            for id in self._changes["new"][tp]:
                if tp in mod and id in mod[tp]:
                    del mod[tp][id]
        return {
            "mod": mod,
            "new": self._changes["new"],
            "deleted": self._changes["deleted"]
        }

    def update(self, tp, id, updatejson):
        try:
            obj = self.__objects[tp][id]
            for dim_name in updatejson:
                if dim_name in tp.__dimensions_name__:
                    # TODO: O(n) search: needs to be improved
                    dimension = None
                    for dim in tp.__dimensions__:
                        if dim._name == dim_name:
                            dimension = dim
                    if not dimension:
                        raise Exception(
                            "Could not find dimension with name %s" % dim_name)
                    if hasattr(dimension._type, "__dependent_type__"):
                        setattr(
                            obj, dimension._name,
                            create_tracking_obj(tp, updatejson, self.__objects,
                                                True))
                    else:
                        setattr(
                            obj, dimension._name,
                            create_obj(dimension._type,
                                       updatejson[dimension._name]))
            obj.__start_tracking__ = True
            return self.__objects[tp][id]
        except:
            self.logger.debug("could not update %s: not found in store.", id)
            return None

    def update_all(self, tp, updatejsons):
        ret = []
        for id, updatejson in updatejsons.items():
            obj = self.update(tp, id, updatejson)
            if obj is not None:
                ret.append(obj)
        return ret

    def clear_incoming_record(self):
        self.__incoming_new = {}
        self.__incoming_mod = {}
        self.__incoming_del = {}

    def create_incoming_record(self, new, mod, deleted):
        for tp in new:
            self.__incoming_new.setdefault(tp, []).extend(new[tp])
        for tp in mod:
            self.__incoming_mod.setdefault(tp, []).extend(mod[tp])
        for tp in deleted:
            self.__incoming_del.setdefault(tp, []).extend(deleted[tp])

    def get_new(self, tp):
        return self.__incoming_new[tp] if tp in self.__incoming_new else []

    def get_mod(self, tp):
        return self.__incoming_mod[tp] if tp in self.__incoming_mod else []

    def get_deleted(self, tp):
        return self.__incoming_del[tp] if tp in self.__incoming_del else []
示例#3
0
class ApplicationQueue(object):
    def __init__(self,
                 name,
                 types,
                 dataframe,
                 all=False,
                 compress_in_parallel=False):
        self.app_name = name
        self.known_objects = RecursiveDictionary()
        self.current_record = RecursiveDictionary()
        self.types = types
        self.dataframe = dataframe
        self.all = all
        self.type_changes = dict()
        self.registered_impures, self.queue = self.dataframe.connect_app_queue(
            self)
        self.lock = RLock()
        self.first_run = True
        if compress_in_parallel:
            self.p = Thread(target=self.merge_parallel,
                            name="Thread_ApplicationQueue_MergeParallel")
            self.p.daemon = True
            self.p.start()

    def merge_parallel(self):
        records = list()
        while True:
            with self.lock:
                while True:
                    try:
                        records.extend(self.queue.get_nowait())
                    except Empty:
                        self.merge_records(records)
                        records = list()
                        break
            time.sleep(2)

    def add_types(self, pairs_added):
        for tpname, _ in pairs_added:
            self.type_changes[tpname] = Event.New

    def merge_records(self, records):
        #new_records_this_cycle = RecursiveDictionary()
        for rec in records:
            event, tpname, groupname, oid, dim_change, full_obj = (
                rec.event, rec.tpname, rec.groupname, rec.oid, rec.dim_change,
                rec.full_obj)
            obj_changes = self.current_record.setdefault(
                groupname,
                RecursiveDictionary()).setdefault(oid, RecursiveDictionary())
            type_changes = obj_changes.setdefault("types",
                                                  RecursiveDictionary())
            if (tpname in type_changes
                    and type_changes[tpname] == Event.Delete):
                continue
            is_known = (tpname in self.known_objects
                        and oid in self.known_objects[tpname])
            if event == Event.New:
                type_changes[tpname] = event
                obj_changes.setdefault("dims",
                                       RecursiveDictionary()).update(full_obj)
            elif event == Event.Modification:
                type_changes[tpname] = event if is_known else Event.New
                change = dim_change if is_known else full_obj
                if change:
                    obj_changes.setdefault(
                        "dims", RecursiveDictionary()).update(change)
            elif event == Event.Delete:
                type_changes[tpname] = event

    def get_record(self):
        records = list()
        with self.lock:
            while True:
                try:
                    records.extend(self.queue.get_nowait())
                except Empty:
                    self.merge_records(records)
                    records = list()
                    break
        objmap = self.fetch_impure_types()

        return ApplicationQueue.__convert_to_serializable_dict(
            self.set_known_objects(
                self.merge_impure_record(self.current_record, objmap)),
            types=self.set_and_clear_type_changes())

    def set_and_clear_type_changes(self):
        type_changes = self.type_changes
        self.type_changes = dict()
        return type_changes

    def clear_record(self):
        with self.lock:
            self.current_record = RecursiveDictionary()

    def fetch_impure_types(self):
        objmap = RecursiveDictionary()
        for tp in (self.registered_impures
                   if not self.first_run else self.types):
            objmap[tp] = self.dataframe.get(tp)
        self.first_run = False
        return objmap

    def merge_impure_record(self, current_record, results):
        deleted = RecursiveDictionary()

        for tp in self.registered_impures:
            tpname = tp.__rtypes_metadata__.name
            obj_oids = (self.known_objects[tpname]
                        if tpname in self.known_objects else set())
            next_oids = (set([obj.__primarykey__ for obj in results[tp]])
                         if tp in results else set())
            deleted_oids = obj_oids.difference(next_oids)
            deleted[tpname] = deleted_oids

        impure_results = self.dataframe.convert_to_record(results, deleted)
        for group_name, grpchanges in impure_results.items():
            if group_name not in current_record:
                current_record[group_name] = grpchanges
                continue
            for oid, obj_changes in grpchanges.items():
                if oid not in current_record[group_name]:
                    current_record[group_name][oid] = obj_changes
                    continue

                for tpname, event in obj_changes["types"].items():
                    if tpname in current_record[group_name][oid]["types"]:
                        existing_event = (
                            current_record[group_name][oid]["types"][tpname])
                    else:
                        existing_event = event
                    if (existing_event == Event.Delete
                            or existing_event == Event.Modification):
                        continue
                    current_record[group_name][oid].setdefault(
                        "dims",
                        RecursiveDictionary()).rec_update(obj_changes["dims"])
                    current_record[group_name][oid]["types"][tpname] = (
                        existing_event)
        return current_record

    def set_known_objects(self, current_record):
        for _, grp_changes in current_record.iteritems():
            for oid, obj_changes in grp_changes.items():
                for tpname, status in obj_changes["types"].items():
                    if status == Event.New:
                        self.known_objects.setdefault(tpname, set()).add(oid)
                    elif (status == Event.Delete
                          and oid in self.known_objects.setdefault(
                              tpname, set())):
                        self.known_objects[tpname].remove(oid)

        return current_record

    @staticmethod
    def __convert_to_serializable_dict(current_record, types=dict()):
        df_changes = df_repr.DataframeChanges_Base()
        dict_changes = ({
            "gc": current_record,
            "types": types
        } if types else {
            "gc": current_record
        })
        df_changes.ParseFromDict(dict_changes)
        return df_changes