use of com.apple.foundationdb.record.RecordMetaData in project fdb-record-layer by FoundationDB.
the class FDBRecordStore method checkPossiblyRebuild.
private CompletableFuture<Void> checkPossiblyRebuild(@Nullable UserVersionChecker userVersionChecker, @Nonnull RecordMetaDataProto.DataStoreInfo.Builder info, @Nonnull boolean[] dirty) {
final int oldFormatVersion = info.getFormatVersion();
final int newFormatVersion = Math.max(oldFormatVersion, formatVersion);
final boolean formatVersionChanged = oldFormatVersion != newFormatVersion;
formatVersion = newFormatVersion;
final boolean newStore = oldFormatVersion == 0;
final int oldMetaDataVersion = newStore ? -1 : info.getMetaDataversion();
final RecordMetaData metaData = getRecordMetaData();
final int newMetaDataVersion = metaData.getVersion();
if (oldMetaDataVersion > newMetaDataVersion) {
CompletableFuture<Void> ret = new CompletableFuture<>();
ret.completeExceptionally(new RecordStoreStaleMetaDataVersionException("Local meta-data has stale version", LogMessageKeys.LOCAL_VERSION, newMetaDataVersion, LogMessageKeys.STORED_VERSION, oldMetaDataVersion, subspaceProvider.logKey(), subspaceProvider.toString(context)));
return ret;
}
final boolean metaDataVersionChanged = oldMetaDataVersion != newMetaDataVersion;
if (!formatVersionChanged && !metaDataVersionChanged) {
return AsyncUtil.DONE;
}
if (LOGGER.isInfoEnabled()) {
if (newStore) {
LOGGER.info(KeyValueLogMessage.of("new record store", LogMessageKeys.FORMAT_VERSION, newFormatVersion, LogMessageKeys.META_DATA_VERSION, newMetaDataVersion, subspaceProvider.logKey(), subspaceProvider.toString(context)));
} else {
if (formatVersionChanged) {
LOGGER.info(KeyValueLogMessage.of("format version changed", LogMessageKeys.OLD_VERSION, oldFormatVersion, LogMessageKeys.NEW_VERSION, newFormatVersion, subspaceProvider.logKey(), subspaceProvider.toString(context)));
}
if (metaDataVersionChanged) {
LOGGER.info(KeyValueLogMessage.of("meta-data version changed", LogMessageKeys.OLD_VERSION, oldMetaDataVersion, LogMessageKeys.NEW_VERSION, newMetaDataVersion, subspaceProvider.logKey(), subspaceProvider.toString(context)));
}
}
}
dirty[0] = true;
return checkRebuild(userVersionChecker, info, metaData);
}
use of com.apple.foundationdb.record.RecordMetaData in project fdb-record-layer by FoundationDB.
the class FDBRecordStore method deleteTypedRecord.
@Nonnull
protected <M extends Message> CompletableFuture<Boolean> deleteTypedRecord(@Nonnull RecordSerializer<M> typedSerializer, @Nonnull Tuple primaryKey) {
preloadCache.invalidate(primaryKey);
final RecordMetaData metaData = metaDataProvider.getRecordMetaData();
CompletableFuture<Boolean> result = loadTypedRecord(typedSerializer, primaryKey, false).thenCompose(oldRecord -> {
if (oldRecord == null) {
return AsyncUtil.READY_FALSE;
}
SplitHelper.deleteSplit(getRecordContext(), recordsSubspace(), primaryKey, metaData.isSplitLongRecords(), omitUnsplitRecordSuffix, true, oldRecord);
countKeysAndValues(FDBStoreTimer.Counts.DELETE_RECORD_KEY, FDBStoreTimer.Counts.DELETE_RECORD_KEY_BYTES, FDBStoreTimer.Counts.DELETE_RECORD_VALUE_BYTES, oldRecord);
addRecordCount(metaData, oldRecord, LITTLE_ENDIAN_INT64_MINUS_ONE);
final boolean oldHasIncompleteVersion = oldRecord.hasVersion() && !oldRecord.getVersion().isComplete();
if (useOldVersionFormat()) {
byte[] versionKey = getSubspace().pack(recordVersionKey(primaryKey));
if (oldHasIncompleteVersion) {
context.removeVersionMutation(versionKey);
} else if (metaData.isStoreRecordVersions()) {
ensureContextActive().clear(versionKey);
}
}
CompletableFuture<Void> updateIndexesFuture = updateSecondaryIndexes(oldRecord, null);
if (oldHasIncompleteVersion) {
return updateIndexesFuture.thenApply(vignore -> {
byte[] versionKey = getSubspace().pack(recordVersionKey(primaryKey));
context.removeLocalVersion(versionKey);
return true;
});
} else {
return updateIndexesFuture.thenApply(vignore -> true);
}
});
return context.instrument(FDBStoreTimer.Events.DELETE_RECORD, result);
}
use of com.apple.foundationdb.record.RecordMetaData in project fdb-record-layer by FoundationDB.
the class FDBRecordStore method loadRecordVersionAsync.
/**
* Async version of {@link #loadRecordVersion(Tuple, boolean)}.
* @param primaryKey the primary key of the record
* @param snapshot whether to snapshot read
* @return a future that completes with the version of the record of {@code Optional.empty()} if versions are not enabled for this store
*/
@Nonnull
public Optional<CompletableFuture<FDBRecordVersion>> loadRecordVersionAsync(@Nonnull final Tuple primaryKey, final boolean snapshot) {
final RecordMetaData metaData = metaDataProvider.getRecordMetaData();
if (useOldVersionFormat() && !metaData.isStoreRecordVersions()) {
// a priori that this will return an empty optional, so we return it without doing any I/O.
return Optional.empty();
} else {
byte[] versionKey = getSubspace().pack(recordVersionKey(primaryKey));
Optional<CompletableFuture<FDBRecordVersion>> cachedOptional = context.getLocalVersion(versionKey).map(localVersion -> CompletableFuture.completedFuture(FDBRecordVersion.incomplete(localVersion)));
if (cachedOptional.isPresent()) {
return cachedOptional;
}
final ReadTransaction tr = snapshot ? ensureContextActive().snapshot() : ensureContextActive();
return Optional.of(tr.get(versionKey).thenApply(valueBytes -> {
if (valueBytes == null) {
return null;
} else if (useOldVersionFormat()) {
return FDBRecordVersion.complete(valueBytes, false);
} else {
return SplitHelper.unpackVersion(valueBytes);
}
}));
}
}
use of com.apple.foundationdb.record.RecordMetaData in project fdb-record-layer by FoundationDB.
the class FDBRecordStore method saveTypedRecord.
@Nonnull
@API(API.Status.INTERNAL)
protected <M extends Message> CompletableFuture<FDBStoredRecord<M>> saveTypedRecord(@Nonnull RecordSerializer<M> typedSerializer, @Nonnull M rec, @Nonnull RecordExistenceCheck existenceCheck, @Nullable FDBRecordVersion version, @Nonnull VersionstampSaveBehavior behavior) {
final RecordMetaData metaData = metaDataProvider.getRecordMetaData();
final Descriptors.Descriptor recordDescriptor = rec.getDescriptorForType();
final RecordType recordType = metaData.getRecordTypeForDescriptor(recordDescriptor);
final KeyExpression primaryKeyExpression = recordType.getPrimaryKey();
final FDBStoredRecordBuilder<M> recordBuilder = FDBStoredRecord.newBuilder(rec).setRecordType(recordType);
final FDBRecordVersion recordVersion = recordVersionForSave(metaData, version, behavior);
recordBuilder.setVersion(recordVersion);
final Tuple primaryKey = primaryKeyExpression.evaluateSingleton(recordBuilder).toTuple();
recordBuilder.setPrimaryKey(primaryKey);
final CompletableFuture<FDBStoredRecord<M>> result = loadExistingRecord(typedSerializer, primaryKey).thenCompose(oldRecord -> {
if (oldRecord == null) {
if (existenceCheck.errorIfNotExists()) {
throw new RecordDoesNotExistException("record does not exist", LogMessageKeys.PRIMARY_KEY, primaryKey);
}
} else {
if (existenceCheck.errorIfExists()) {
throw new RecordAlreadyExistsException("record already exists", LogMessageKeys.PRIMARY_KEY, primaryKey);
}
if (existenceCheck.errorIfTypeChanged() && oldRecord.getRecordType() != recordType) {
throw new RecordTypeChangedException("record type changed", LogMessageKeys.PRIMARY_KEY, primaryKey, LogMessageKeys.ACTUAL_TYPE, oldRecord.getRecordType().getName(), LogMessageKeys.EXPECTED_TYPE, recordType.getName());
}
}
final FDBStoredRecord<M> newRecord = serializeAndSaveRecord(typedSerializer, recordBuilder, metaData, oldRecord);
if (oldRecord == null) {
addRecordCount(metaData, newRecord, LITTLE_ENDIAN_INT64_ONE);
} else {
if (getTimer() != null) {
getTimer().increment(FDBStoreTimer.Counts.REPLACE_RECORD_VALUE_BYTES, oldRecord.getValueSize());
}
}
return updateSecondaryIndexes(oldRecord, newRecord).thenApply(v -> newRecord);
});
return context.instrument(FDBStoreTimer.Events.SAVE_RECORD, result);
}
use of com.apple.foundationdb.record.RecordMetaData in project fdb-record-layer by FoundationDB.
the class FDBRecordStore method deserializeRecord.
private <M extends Message> CompletableFuture<FDBStoredRecord<M>> deserializeRecord(@Nonnull RecordSerializer<M> typedSerializer, @Nonnull final FDBRawRecord rawRecord, @Nonnull final RecordMetaData metaData, @Nonnull final Optional<CompletableFuture<FDBRecordVersion>> versionFutureOptional) {
final Tuple primaryKey = rawRecord.getPrimaryKey();
final byte[] serialized = rawRecord.getRawRecord();
try {
final M protoRecord = typedSerializer.deserialize(metaData, primaryKey, rawRecord.getRawRecord(), getTimer());
final RecordType recordType = metaData.getRecordTypeForDescriptor(protoRecord.getDescriptorForType());
countKeysAndValues(FDBStoreTimer.Counts.LOAD_RECORD_KEY, FDBStoreTimer.Counts.LOAD_RECORD_KEY_BYTES, FDBStoreTimer.Counts.LOAD_RECORD_VALUE_BYTES, rawRecord);
final FDBStoredRecordBuilder<M> recordBuilder = FDBStoredRecord.newBuilder(protoRecord).setPrimaryKey(primaryKey).setRecordType(recordType).setSize(rawRecord);
if (rawRecord.hasVersion()) {
// In the current format version, the version should be read along with the version,
// so this should be hit the majority of the time.
recordBuilder.setVersion(rawRecord.getVersion());
return CompletableFuture.completedFuture(recordBuilder.build());
} else if (versionFutureOptional.isPresent()) {
// another read (which has hopefully happened in parallel with the main record read in the background).
return versionFutureOptional.get().thenApply(version -> {
recordBuilder.setVersion(version);
return recordBuilder.build();
});
} else {
// this will return an FDBStoredRecord where the version is unset.
return CompletableFuture.completedFuture(recordBuilder.build());
}
} catch (Exception ex) {
final LoggableException ex2 = new RecordCoreException("Failed to deserialize record", ex);
ex2.addLogInfo(subspaceProvider.logKey(), subspaceProvider.toString(context), LogMessageKeys.PRIMARY_KEY, primaryKey, LogMessageKeys.META_DATA_VERSION, metaData.getVersion());
if (LOGGER.isDebugEnabled()) {
ex2.addLogInfo("serialized", ByteArrayUtil2.loggable(serialized));
}
if (LOGGER.isTraceEnabled()) {
ex2.addLogInfo("descriptor", metaData.getUnionDescriptor().getFile().toProto());
}
throw ex2;
}
}
Aggregations