Package org.lilyproject.util.repo

Examples of org.lilyproject.util.repo.RecordEvent


    public Result encodeRecord(Record record) throws InterruptedException, RepositoryException {
        TypeManager typeManager = repositoryManager.getDefaultRepository().getTypeManager();
        List<KeyValue> kvs = Lists.newArrayList();

        RecordEvent event = new RecordEvent();
        event.setType(RecordEvent.Type.CREATE);
        event.setTableName(LilyHBaseSchema.Table.RECORD.name);
        event.setVersionCreated(record.getVersion());

        byte[] rowKey = record.getId().toBytes();
        byte[] family = LilyHBaseSchema.RecordCf.DATA.bytes;

        kvs.add(new KeyValue(rowKey, family, LilyHBaseSchema.RecordColumn.VERSION.bytes, 1L, Bytes.toBytes(record.getVersion())));

        kvs.add(new KeyValue(rowKey, family, LilyHBaseSchema.RecordColumn.NON_VERSIONED_RT_ID.bytes,
                1L, typeManager.getRecordTypeByName(record.getRecordTypeName(Scope.NON_VERSIONED),
                        record.getRecordTypeVersion(Scope.NON_VERSIONED)).getId().getBytes()));
        kvs.add(new KeyValue(rowKey, family, LilyHBaseSchema.RecordColumn.NON_VERSIONED_RT_VERSION.bytes,
                1L, Bytes.toBytes(record.getRecordTypeVersion(Scope.NON_VERSIONED))));
        /*
        kvs.add(new KeyValue(rowKey, family, LilyHBaseSchema.RecordColumn.VERSIONED_RT_ID.bytes,
                typeManager.getRecordTypeByName(record.getRecordTypeName(Scope.VERSIONED),
                        record.getRecordTypeVersion(Scope.VERSIONED)).getId().getBytes()));
        kvs.add(new KeyValue(rowKey, family, LilyHBaseSchema.RecordColumn.VERSIONED_RT_VERSION.bytes,
                Bytes.toBytes(record.getRecordTypeVersion(Scope.VERSIONED))));

        kvs.add(new KeyValue(rowKey, family, LilyHBaseSchema.RecordColumn.VERSIONED_MUTABLE_RT_ID.bytes,
                typeManager.getRecordTypeByName(record.getRecordTypeName(Scope.VERSIONED_MUTABLE),
                        record.getRecordTypeVersion(Scope.VERSIONED_MUTABLE)).getId().getBytes()));
        kvs.add(new KeyValue(rowKey, family, LilyHBaseSchema.RecordColumn.NON_VERSIONED_RT_VERSION.bytes,
                Bytes.toBytes(record.getRecordTypeVersion(Scope.VERSIONED_MUTABLE))));
                */

        for (QName fieldName : record.getFields().keySet()) {
            FieldType fieldType = typeManager.getFieldTypeByName(fieldName);
            Metadata metadata = record.getMetadata(fieldName);
            boolean hasMetadata = metadata != null && !metadata.getMap().isEmpty();

            DataOutput output = new DataOutputImpl();

            output.writeByte(hasMetadata ? FieldFlags.METADATA_V1 : FieldFlags.DEFAULT);
            output.writeBytes(fieldType.getValueType().toBytes(record.getField(fieldName), new IdentityRecordStack()));
            if (hasMetadata) {
                HBaseRepository.writeMetadataWithLengthSuffix(metadata, output);
            }

            event.addUpdatedField(fieldType.getId());

            kvs.add(new KeyValue(rowKey, family,
                    Bytes.add(new byte[]{LilyHBaseSchema.RecordColumn.DATA_PREFIX}, fieldType.getId().getBytes()),
                    output.toByteArray()));
        }
       
        // fields to delete, should we add these too?
        kvs.add(new KeyValue(rowKey, family, LilyHBaseSchema.RecordColumn.PAYLOAD.bytes, event.toJsonBytes()));

        return new Result(kvs);
    }
View Full Code Here


        }
    }

    private boolean isValidKeyValue(KeyValue kv) {
        if (kv.matchingColumn(RecordCf.DATA.bytes, RecordColumn.PAYLOAD.bytes)) {
            RecordEvent recordEvent = null;
            try {
                recordEvent = new RecordEvent(kv.getValue(), idGenerator);
            } catch (IOException e) {
                log.error("Error parsing RecordEvent", e);
                return false;
            }
            if (recordEvent.hasAttributes() && "false".equals(recordEvent.getAttributes().get(NO_INDEX_FLAG))) {
                return false;
            }
            IndexRecordFilterData indexRecordFilterData = recordEvent.getIndexRecordFilterData();
            if (indexRecordFilterData != null) {
                return indexRecordFilterData.appliesToSubscription(subscriptionName);
            } else {
                log.warn("No IndexRecordFilterData on " + recordEvent.toJson());
            }
        }
        return false;
    }
View Full Code Here

    @Override
    public boolean containsRequiredData(Result result) {
        try {
            // If we have a request to reindex then all the information we need should be in the payload
            if (result.containsColumn(LilyHBaseSchema.RecordCf.DATA.bytes, LilyHBaseSchema.RecordColumn.PAYLOAD.bytes)) {
                RecordEvent event = new RecordEvent(result.getFamilyMap(LilyHBaseSchema.RecordCf.DATA.bytes)
                        .get(LilyHBaseSchema.RecordColumn.PAYLOAD.bytes), idGenerator);
                return event.getType().equals(INDEX);
            }
        } catch (IOException e) {
            log.error("Unable to decode record event", e);
        }
        // in other cases force a get for safe measure.
View Full Code Here

    @Override
    public void map(Result result, SolrUpdateWriter solrUpdateWriter) {
        try {
            Record record = recordDecoder.decodeRecord(result);
            RecordEvent event = new RecordEvent(result.getFamilyMap(LilyHBaseSchema.RecordCf.DATA.bytes)
                    .get(LilyHBaseSchema.RecordColumn.PAYLOAD.bytes), idGenerator);

            String tableName = event.getTableName();
            LTable table = repository.getTable(tableName != null ? tableName : LilyHBaseSchema.Table.RECORD.name);

            if (event.getType().equals(INDEX)) {
                if (log.isDebugEnabled()) {
                    log.debug(String.format("Record %1$s: reindex requested for these vtags: %2$s", record.getId(),
                            vtagSetToNameString(event.getVtagsToIndex())));
                }
                RecordEventHelper eventHelper = new RecordEventHelper(event, null, repository.getTypeManager());
                VTaggedRecord vtRecord = new VTaggedRecord(record.getId(), eventHelper, table, repository);

                IndexCase indexCase = lilyIndexerConf.getIndexCase(table.getTableName(), vtRecord.getRecord());
                Set<SchemaId> vtagsToIndex = event.getVtagsToIndex();
                if (indexCase == null) {
                    return;
                }

                // Only keep vtags which should be indexed
                vtagsToIndex.retainAll(indexCase.getVersionTags());
                // Only keep vtags which exist on the record
                vtagsToIndex.retainAll(vtRecord.getVTags().keySet());

                log.debug(vtagsToIndex.toString());
                index(table, vtRecord, vtagsToIndex, solrUpdateWriter);
            } else if (event.getType().equals(DELETE)) {
                solrUpdateWriter.deleteByQuery("lily.id:" + ClientUtils.escapeQueryChars(record.getId().toString()));

                if (log.isDebugEnabled()) {
                    log.debug(String.format("Record %1$s: deleted from index (if present) because of " +
                            "delete record event", record.getId()));
                }

                // After this we can go to update denormalized data
                if (derefMap != null) {
                    updateDenormalizedData(repository.getRepositoryName(), event.getTableName(), record.getId(),
                            null, null);
                }
            } else {
                // CREATE or UPDATE
                VTaggedRecord vtRecord;

                // Based on the partial old/new record state stored in the RecordEvent, determine whether we
                // now match a different IndexCase than before, and if so, if the new case would have less vtags
                // than the old one, perform the necessary deletes on Solr.
                Pair<Record,Record> oldAndNewRecords =
                        IndexRecordFilterUtil.getOldAndNewRecordForRecordFilterEvaluation(record.getId(), event,
                                repository);
                Record oldRecord = oldAndNewRecords.getV1();
                Record newRecord = oldAndNewRecords.getV2();
                IndexCase caseOld = oldRecord != null ? lilyIndexerConf.getIndexCase(
                        event.getTableName(), oldRecord) : null;
                IndexCase caseNew = newRecord != null ? lilyIndexerConf.getIndexCase(
                        event.getTableName(), newRecord) : null;

                if (oldRecord != null && newRecord != null) {
                    if (caseOld != null && caseNew != null) {
                        Set<SchemaId> droppedVtags = new HashSet<SchemaId>(caseOld.getVersionTags());
                        droppedVtags.removeAll(caseNew.getVersionTags());

                        if (droppedVtags.size() > 0) {
                            // Perform deletes
                            for (SchemaId vtag : droppedVtags) {
                                solrUpdateWriter.deleteById(LilyResultToSolrMapper.getIndexId(tableName,
                                        record.getId(), vtag));
                            }
                        }
                    }
                }

                // This is an optimization: an IndexCase with empty vtags list means that this record is
                // included in this index only to trigger updating of denormalized data.
                boolean doIndexing = true;
                if (caseNew != null) {
                    doIndexing = caseNew.getVersionTags().size() > 0;
                } else if (caseNew == null && caseOld != null) {
                    // caseNew == null means either the record has been deleted, or means the record does
                    // not match the recordFilter anymore. In either case, we only need to trigger update
                    // of denormalized data (if the vtags list was empty on caseOld).
                    doIndexing = caseOld.getVersionTags().size() > 0;
                }

                RecordEventHelper eventHelper = new RecordEventHelper(event, null, repository.getTypeManager());

                if (doIndexing) {
                    try {
                        // Read the vtags of the record. Note that while this algorithm is running, the record can
                        // meanwhile undergo changes. However, we continuously work with the snapshot of the vtags
                        // mappings read here. The processing of later events will bring the index up to date with
                        // any new changes.
                        vtRecord = new VTaggedRecord(record.getId(), eventHelper,
                                repository.getTable(event.getTableName()), repository);
                    } catch (RecordNotFoundException e) {
                        // The record has been deleted in the meantime.
                        // For now, we do nothing, when the delete event is received the record will be removed
                        // from the index (as well as update of denormalized data).
                        // TODO: we should process all outstanding messages for the record (up to delete) in one go
                        return;
                    }

                    handleRecordCreateUpdate(vtRecord, table, solrUpdateWriter);
                }

                if (derefMap != null) {
                    updateDenormalizedData(repository.getRepositoryName(), event.getTableName(), record.getId(),
                            eventHelper.getUpdatedFieldsByScope(), eventHelper.getModifiedVTags());
                }
            }
        } catch (Exception e) {
            log.warn("Something went wrong while indexing", e);
View Full Code Here

        //
        // Now add an index message to each of the found referrers, their actual indexing
        // will be triggered by the message queue.
        //
        for (AbsoluteRecordId referrer : referrersAndVTags.keySet()) {
            RecordEvent payload = new RecordEvent();
            payload.setTableName(referrer.getTable());
            payload.setType(INDEX);
            for (SchemaId vtag : referrersAndVTags.get(referrer)) {
                payload.addVTagToIndex(vtag);
            }
            RecordEvent.IndexRecordFilterData filterData = new RecordEvent.IndexRecordFilterData();
            filterData.setSubscriptionInclusions(ImmutableSet.of(this.subscriptionId));
            payload.setIndexRecordFilterData(filterData);

            try {
                eventPublisherManager.getEventPublisher(repo, referrer.getTable()
                ).publishEvent(referrer.getRecordId().toBytes(), payload.toJsonBytes());
            } catch (Exception e) {
                // We failed to put the message: this is pretty important since it means the record's index
                // won't get updated, therefore log as error, but after this we continue with the next one.
                log.error("Error putting index message on queue of record " + referrer, e);
                //metrics.errors.inc();
View Full Code Here

        }
    }

    private void handleRecordCreateUpdate(VTaggedRecord vtRecord, LTable table, SolrUpdateWriter solrUpdateWriter) throws Exception {

        RecordEvent event = vtRecord.getRecordEvent();
        Map<Long, Set<SchemaId>> vtagsByVersion = vtRecord.getVTagsByVersion();

        // Determine the IndexCase:
        //  The indexing of all versions is determined by the record type of the non-versioned scope.
        //  This makes that the indexing behavior of all versions is equal, and can be changed (the
        //  record type of the versioned scope is immutable).
        IndexCase indexCase = lilyIndexerConf.getIndexCase(table.getTableName(), vtRecord.getRecord());

        if (indexCase == null) {
            // The record should not be indexed

            // The record might however have been previously indexed, therefore we need to perform a delete
            // (note that IndexAwareMQFeeder only sends events to us if either the current or old record
            //  state matched the inclusion rules)

            solrUpdateWriter.deleteByQuery("lily.id:" + ClientUtils.escapeQueryChars(vtRecord.getId().toString()));

            if (log.isDebugEnabled()) {
                log.debug(String.format("Record %1$s: no index case found, record deleted from index.",
                        vtRecord.getId()));
            }

            // The data from this record might be denormalized into other index entries
            // After this we go to update denormalized data
        } else {
            final Set<SchemaId> vtagsToIndex;

            if (event.getType().equals(CREATE)) {
                // New record: just index everything
                vtagsToIndex = Sets.intersection(indexCase.getVersionTags(), vtRecord.getVTags().keySet());
                //vtagsToIndex = indexer.retainExistingVtagsOnly(indexCase.getVersionTags(), vtRecord);
                // After this we go to the indexing

            } else if (event.getRecordTypeChanged()) {
                // When the record type changes, the rules to index (= the IndexCase) change

                // Delete everything: we do not know the previous record type, so we do not know what
                // version tags were indexed, so we simply delete everything
                solrUpdateWriter.deleteByQuery("lily.id:" + ClientUtils.escapeQueryChars(vtRecord.getId().toString()));

                if (log.isDebugEnabled()) {
                    log.debug(String.format("Record %1$s: deleted existing entries from index (if present) " +
                            "because of record type change", vtRecord.getId()));
                }

                // Reindex all needed vtags
                vtagsToIndex = Sets.intersection(indexCase.getVersionTags(), vtRecord.getVTags().keySet());

                // After this we go to the indexing
            } else { // a normal update

                //
                // Handle changes to non-versioned fields
                //
                if (lilyIndexerConf.changesAffectIndex(vtRecord, Scope.NON_VERSIONED)) {
                    vtagsToIndex = Sets.intersection(indexCase.getVersionTags(), vtRecord.getVTags().keySet());
                    // After this we go to the treatment of changed vtag fields
                    if (log.isDebugEnabled()) {
                        log.debug(
                                String.format("Record %1$s: non-versioned fields changed, will reindex all vtags.",
                                        vtRecord.getId()));
                    }
                } else {
                    vtagsToIndex = new HashSet<SchemaId>();
                }

                //
                // Handle changes to versioned(-mutable) fields
                //
                // If there were non-versioned fields changed, then we already reindex all versions
                // so this can be skipped.
                //
                // In the case of newly created versions that should be indexed: this will often be
                // accompanied by corresponding changes to vtag fields, which are handled next, and in which case
                // it would work as well if this code would not be here.
                //
                if (vtagsToIndex.isEmpty() && (event.getVersionCreated() != -1 || event.getVersionUpdated() != -1)) {
                    if (lilyIndexerConf.changesAffectIndex(vtRecord, Scope.VERSIONED)
                            || lilyIndexerConf.changesAffectIndex(vtRecord, Scope.VERSIONED_MUTABLE)) {

                        long version =
                                event.getVersionCreated() != -1 ? event.getVersionCreated() : event.getVersionUpdated();
                        if (vtagsByVersion.containsKey(version)) {
                            Set<SchemaId> tmp = new HashSet<SchemaId>();
                            tmp.addAll(indexCase.getVersionTags());
                            tmp.retainAll(vtagsByVersion.get(version));
                            vtagsToIndex.addAll(tmp);
View Full Code Here

TOP

Related Classes of org.lilyproject.util.repo.RecordEvent

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.