def record_metering_data(self, data):
        """Write the data to the backend storage system.

        :param data: a dictionary such as returned by
                     ceilometer.meter.meter_message_from_counter
        """
        if data['source']:
            source = self.session.query(Source).get(data['source'])
            if not source:
                source = Source(id=data['source'])
                self.session.add(source)
        else:
            source = None

        # create/update user && project, add/update their sources list
        if data['user_id']:
            user = self.session.merge(User(id=str(data['user_id'])))
            if not filter(lambda x: x.id == source.id, user.sources):
                user.sources.append(source)
        else:
            user = None

        if data['project_id']:
            project = self.session.merge(Project(id=str(data['project_id'])))
            if not filter(lambda x: x.id == source.id, project.sources):
                project.sources.append(source)
        else:
            project = None

        # Record the updated resource metadata
        rmetadata = data['resource_metadata']

        resource = self.session.merge(Resource(id=str(data['resource_id'])))
        if not filter(lambda x: x.id == source.id, resource.sources):
            resource.sources.append(source)
        resource.project = project
        resource.user = user
        # Current metadata being used and when it was last updated.
        resource.resource_metadata = rmetadata
        # autoflush didn't catch this one, requires manual flush
        self.session.flush()

        # Record the raw data for the event.
        meter = Meter(counter_type=data['counter_type'],
                      counter_unit=data['counter_unit'],
                      counter_name=data['counter_name'],
                      resource=resource)
        self.session.add(meter)
        if not filter(lambda x: x.id == source.id, meter.sources):
            meter.sources.append(source)
        meter.project = project
        meter.user = user
        meter.timestamp = data['timestamp']
        meter.resource_metadata = rmetadata
        meter.counter_volume = data['counter_volume']
        meter.message_signature = data['message_signature']
        meter.message_id = data['message_id']

        return
    def record_metering_data(data):
        """Write the data to the backend storage system.

        :param data: a dictionary such as returned by
                     ceilometer.meter.meter_message_from_counter
        """
        session = sqlalchemy_session.get_session()
        with session.begin():
            if data['source']:
                source = session.query(Source).get(data['source'])
                if not source:
                    source = Source(id=data['source'])
                    session.add(source)
            else:
                source = None

            # create/update user && project, add/update their sources list
            if data['user_id']:
                user = session.merge(User(id=str(data['user_id'])))
                if not filter(lambda x: x.id == source.id, user.sources):
                    user.sources.append(source)
            else:
                user = None

            if data['project_id']:
                project = session.merge(Project(id=str(data['project_id'])))
                if not filter(lambda x: x.id == source.id, project.sources):
                    project.sources.append(source)
            else:
                project = None

            # Record the updated resource metadata
            rmetadata = data['resource_metadata']

            resource = session.merge(Resource(id=str(data['resource_id'])))
            if not filter(lambda x: x.id == source.id, resource.sources):
                resource.sources.append(source)
            resource.project = project
            resource.user = user
            # Current metadata being used and when it was last updated.
            resource.resource_metadata = rmetadata

            # Record the raw data for the meter.
            meter = Meter(counter_type=data['counter_type'],
                          counter_unit=data['counter_unit'],
                          counter_name=data['counter_name'],
                          resource=resource)
            session.add(meter)
            if not filter(lambda x: x.id == source.id, meter.sources):
                meter.sources.append(source)
            meter.project = project
            meter.user = user
            meter.timestamp = data['timestamp']
            meter.resource_metadata = rmetadata
            meter.counter_volume = data['counter_volume']
            meter.message_signature = data['message_signature']
            meter.message_id = data['message_id']
            session.flush()

            if rmetadata:
                if isinstance(rmetadata, dict):
                    for key, v in utils.dict_to_keyval(rmetadata):
                        try:
                            _model = META_TYPE_MAP[type(v)]
                        except KeyError:
                            LOG.warn(
                                _("Unknown metadata type. Key (%s) will "
                                  "not be queryable."), key)
                        else:
                            session.add(
                                _model(id=meter.id, meta_key=key, value=v))

            session.flush()