@API(value=MAINTAINED) public class FDBMetaDataStore extends FDBStoreBase implements RecordMetaDataProvider
RecordMetaData
into the database.
Storing meta-data in the database allows for it to be updated atomically. All clients of the database will see the new version at the same time. If, on the other hand, meta-data is part of the application itself, it is possible that during deployment of a new version of the application some instances will have out-of-date meta-data.
Modifier and Type | Class and Description |
---|---|
static class |
FDBMetaDataStore.MissingMetaDataException
Thrown if meta-data was never written to the store.
|
Modifier and Type | Field and Description |
---|---|
static Tuple |
CURRENT_KEY |
static Tuple |
HISTORY_KEY_PREFIX |
static Tuple |
OLD_FORMAT_KEY |
context, subspaceProvider
Constructor and Description |
---|
FDBMetaDataStore(FDBRecordContext context,
KeySpacePath path) |
FDBMetaDataStore(FDBRecordContext context,
Subspace subspace,
MetaDataCache cache) |
Modifier and Type | Method and Description |
---|---|
void |
addIndex(String recordType,
Index index)
Add a new index to the record meta-data.
|
void |
addIndex(String recordType,
String indexName,
KeyExpression indexExpression)
Add a new index to the record meta-data.
|
void |
addIndex(String recordType,
String indexName,
String fieldName)
Add a new index to the record meta-data.
|
CompletableFuture<Void> |
addIndexAsync(String recordType,
Index index)
Add a new index to the record meta-data asynchronously.
|
CompletableFuture<Void> |
addIndexAsync(String recordType,
String indexName,
KeyExpression indexExpression)
Add a new index to the record meta-data asynchronously.
|
CompletableFuture<Void> |
addIndexAsync(String recordType,
String indexName,
String fieldName)
Add a new index to the record meta-data asynchronously.
|
void |
addMultiTypeIndex(List<String> recordTypes,
Index index)
Add a new index to the record meta-data that contains multiple record types.
|
CompletableFuture<Void> |
addMultiTypeIndexAsync(List<String> recordTypes,
Index index)
Add a new index to the record meta-data that contains multiple record types asynchronously.
|
void |
addUniversalIndex(Index index)
Add a new index on all record types.
|
CompletableFuture<Void> |
addUniversalIndexAsync(Index index)
Add a new index on all record types.
|
protected RecordMetaData |
buildMetaData(RecordMetaDataProto.MetaData metaDataProto,
boolean validate) |
protected RecordMetaData |
buildMetaData(RecordMetaDataProto.MetaData metaDataProto,
boolean validate,
boolean useLocalFileDescriptor) |
protected RecordMetaDataBuilder |
createMetaDataBuilder(RecordMetaDataProto.MetaData metaDataProto) |
protected RecordMetaDataBuilder |
createMetaDataBuilder(RecordMetaDataProto.MetaData metaDataProto,
boolean useLocalFileDescriptor) |
void |
dropIndex(String indexName)
Remove the given index from the record meta-data.
|
CompletableFuture<Void> |
dropIndexAsync(String indexName)
Remove the given index from the record meta-data asynchronously.
|
void |
enableSplitLongRecords()
Enable splitting long records.
|
CompletableFuture<Void> |
enableSplitLongRecordsAsync()
Enable splitting long records asynchronously.
|
MetaDataCache |
getCache() |
MetaDataEvolutionValidator |
getEvolutionValidator()
Get the validator used when saving a new version of the meta-data to ensure the new meta-data is a valid
evolution of the old meta-data.
|
protected ExtensionRegistry |
getExtensionRegistry()
Get the extension registry used when deserializing meta-data proto messages.
|
Descriptors.FileDescriptor |
getLocalFileDescriptor()
Get the local meta-data file descriptor.
|
RecordMetaData |
getRecordMetaData()
Provide an instance of
RecordMetaData . |
CompletableFuture<RecordMetaData> |
getRecordMetaDataAsync(boolean errorIfMissing) |
CompletableFuture<RecordMetaDataProto.MetaData> |
loadAndSetCurrent(boolean checkCache,
int currentVersion)
Load current meta-data from store and set for
getRecordMetaData . |
protected CompletableFuture<byte[]> |
loadCurrentSerialized() |
CompletableFuture<RecordMetaData> |
loadVersion(int version) |
void |
mutateMetaData(Consumer<RecordMetaDataProto.MetaData.Builder> mutateMetaDataProto)
Mutate the stored meta-data proto using a mutation callback.
|
void |
mutateMetaData(Consumer<RecordMetaDataProto.MetaData.Builder> mutateMetaDataProto,
Consumer<RecordMetaDataBuilder> mutateRecordMetaDataBuilder)
Mutate the stored meta-data proto and record meta-data builder using mutation callbacks.
|
CompletableFuture<Void> |
mutateMetaDataAsync(Consumer<RecordMetaDataProto.MetaData.Builder> mutateMetaDataProto)
Mutate the stored meta-data proto using a mutation callback asynchronously.
|
CompletableFuture<Void> |
mutateMetaDataAsync(Consumer<RecordMetaDataProto.MetaData.Builder> mutateMetaDataProto,
Consumer<RecordMetaDataBuilder> mutateRecordMetaDataBuilder)
Mutate the stored meta-data proto and record meta-data builder using mutation callbacks asynchronously.
|
protected RecordMetaDataProto.MetaData |
parseMetaDataProto(byte[] serialized) |
CompletableFuture<Void> |
preloadMetaData(RecordMetaDataProvider metaDataProvider)
Prepare a meta-data store for use by loading any existing
RecordMetaData or storing an initial
seed from the given provider. |
CompletableFuture<Void> |
saveAndSetCurrent(RecordMetaDataProto.MetaData metaDataProto)
Build meta-data to use from Protobuf and save.
|
void |
saveRecordMetaData(Descriptors.FileDescriptor fileDescriptor)
Save the record meta-data into the meta-data store.
|
void |
saveRecordMetaData(RecordMetaDataProto.MetaData metaDataProto)
Save the record meta-data into the meta-data store.
|
void |
saveRecordMetaData(RecordMetaDataProvider metaDataProvider)
Save the record meta-data into the meta-data store.
|
CompletableFuture<Void> |
saveRecordMetaDataAsync(Descriptors.FileDescriptor fileDescriptor)
Save the record meta-data into the meta-data store.
|
void |
setDependencies(Descriptors.FileDescriptor[] dependencies)
Set dependencies upon which record descriptors may depend.
|
void |
setEvolutionValidator(MetaDataEvolutionValidator evolutionValidator)
Set the validator used when saving a new version of the meta-data to ensure the new meta-data is a valid
evolution of the old meta-data.
|
void |
setExtensionRegistry(ExtensionRegistry extensionRegistry)
Set the extension registry used when deserializing meta-data proto messages.
|
void |
setLocalFileDescriptor(Descriptors.FileDescriptor localFileDescriptor)
Set the local meta-data file descriptor.
|
void |
setMaintainHistory(boolean maintainHistory)
Set whether this store keeps a record of older versions.
|
void |
updateRecords(Descriptors.FileDescriptor recordsDescriptor)
Update the meta-data records descriptor.
|
CompletableFuture<Void> |
updateRecordsAsync(Descriptors.FileDescriptor recordsDescriptor)
Update the meta-data records descriptor asynchronously.
|
void |
updateStoreRecordVersions(boolean storeRecordVersions)
Update whether record versions should be stored in the meta-data.
|
CompletableFuture<Void> |
updateStoreRecordVersionsAsync(boolean storeRecordVersions)
Update whether record versions should be stored in the meta-data asynchronously.
|
addConflictForSubspace, ensureContextActive, getExecutor, getRecordContext, getSubspace, getSubspaceAsync, getSubspaceProvider, getTimer, increment, increment, instrument, instrument, instrument, record, record
public static final Tuple CURRENT_KEY
public static final Tuple HISTORY_KEY_PREFIX
public static final Tuple OLD_FORMAT_KEY
@API(value=UNSTABLE) public FDBMetaDataStore(@Nonnull FDBRecordContext context, @Nonnull Subspace subspace, @Nullable MetaDataCache cache)
public FDBMetaDataStore(@Nonnull FDBRecordContext context, @Nonnull KeySpacePath path)
public void setDependencies(@Nonnull Descriptors.FileDescriptor[] dependencies)
dependencies
- array of descriptors that record descriptors might depend on@Nullable public Descriptors.FileDescriptor getLocalFileDescriptor()
RecordMetaDataBuilder.setLocalFileDescriptor(Descriptors.FileDescriptor)
for more information.RecordMetaDataBuilder.setLocalFileDescriptor(Descriptors.FileDescriptor)
public void setLocalFileDescriptor(@Nullable Descriptors.FileDescriptor localFileDescriptor)
A record store created off of the meta-data store may not be able to store a record created by a
statically-generated proto file because the meta-data and record have mismatched descriptors. Using this method,
the meta-data can use the same version of the descriptor as the record.
See RecordMetaDataBuilder.setLocalFileDescriptor(Descriptors.FileDescriptor)
for more information.
Note that it is not allowed to (a) change the name of the existing record types or (b) change existing
non-NESTED
record types to NESTED
record types in the evolved local file descriptor.
localFileDescriptor
- the local descriptor of the meta-dataRecordMetaDataBuilder.setLocalFileDescriptor(Descriptors.FileDescriptor)
@Nonnull public MetaDataEvolutionValidator getEvolutionValidator()
MetaDataEvolutionValidator
's
default instance, but the user can tweak
the validator's options by supplying a different validator through setEvolutionValidator(MetaDataEvolutionValidator)
.
See setEvolutionValidator(MetaDataEvolutionValidator)
for more details.setEvolutionValidator(MetaDataEvolutionValidator)
,
MetaDataEvolutionValidator
public void setEvolutionValidator(@Nonnull MetaDataEvolutionValidator evolutionValidator)
getEvolutionValidator()
for more details.
Whenever the meta-data store, saves a new version of the meta-data (through, for example, saveRecordMetaData(RecordMetaDataProvider)
),
the existing meta-data from the store is read. The new and existing meta-data are then compared, and an error
is thrown if the new meta-data is not a valid evolution of the existing meta-data. See MetaDataEvolutionValidator
for more details on how the meta-data should be evolved.
If one sets a local file descriptor, then this validator is also used to make sure that the local file descriptor is compatible with the file descriptor within the meta-data proto retrieved from the database.
evolutionValidator
- the validator used to ensure the new meta-data is a valid evolution of the existing meta-dataMetaDataEvolutionValidator
@Nullable protected ExtensionRegistry getExtensionRegistry()
record_metadata_options.proto
". Note that this
differs from the empty extension registry.
When the meta-data proto is built into a RecordMetaData
object, extension options on fields
specifying primary key and index information are ignored. However, options specifying each record's
type are still processed, including information specifying the meta-data's union descriptor. As a result,
if the provided registry does not at least register the (record).usage
extension option, the
RecordMetaData
may fail to build with an error message indicating that no union descriptor was specified.
public void setExtensionRegistry(@Nullable ExtensionRegistry extensionRegistry)
null
extension registry serves as a synonym for the
empty extension registry, but in Protobuf version 3,
a null
extension registry can result in NullPointerException
s when the meta-data proto is
deserialized. Therefore, users who upgrade from proto2 to proto3 may need to adjust the registry they pass
to the meta-data store through this function.extensionRegistry
- the extension registry used when parsing meta-datapublic void setMaintainHistory(boolean maintainHistory)
maintainHistory
- true
if this store should maintain a historypublic CompletableFuture<RecordMetaDataProto.MetaData> loadAndSetCurrent(boolean checkCache, int currentVersion)
getRecordMetaData
.checkCache
- true
if the cache should be checked firstcurrentVersion
- the version to loadprotected CompletableFuture<byte[]> loadCurrentSerialized()
@Nonnull protected RecordMetaDataProto.MetaData parseMetaDataProto(@Nonnull byte[] serialized)
@Nonnull protected RecordMetaDataBuilder createMetaDataBuilder(@Nonnull RecordMetaDataProto.MetaData metaDataProto)
@Nonnull protected RecordMetaDataBuilder createMetaDataBuilder(@Nonnull RecordMetaDataProto.MetaData metaDataProto, boolean useLocalFileDescriptor)
@Nonnull protected RecordMetaData buildMetaData(@Nonnull RecordMetaDataProto.MetaData metaDataProto, boolean validate, boolean useLocalFileDescriptor)
@Nonnull protected RecordMetaData buildMetaData(@Nonnull RecordMetaDataProto.MetaData metaDataProto, boolean validate)
public CompletableFuture<RecordMetaData> loadVersion(int version)
@Nonnull public CompletableFuture<Void> saveAndSetCurrent(@Nonnull RecordMetaDataProto.MetaData metaDataProto)
metaDataProto
- the Protobuf form of the meta-data to savepublic CompletableFuture<RecordMetaData> getRecordMetaDataAsync(boolean errorIfMissing)
@Nonnull public CompletableFuture<Void> preloadMetaData(@Nullable RecordMetaDataProvider metaDataProvider)
RecordMetaData
or storing an initial
seed from the given provider.metaDataProvider
- a provider for a seed meta-data to be used when this store is empty@Nonnull public RecordMetaData getRecordMetaData()
RecordMetaDataProvider
RecordMetaData
.
Implementors should assume that this method will be called frequently, so it may
be necessary to cache the result if generating the RecordMetaData
is expensive.getRecordMetaData
in interface RecordMetaDataProvider
RecordMetaData
@API(value=MAINTAINED) public void saveRecordMetaData(@Nonnull Descriptors.FileDescriptor fileDescriptor)
If the given records descriptor is missing a union message, this method will automatically add one to the descriptor
before saving the meta-data. If the meta-data store is currently empty, a default union descriptor will be added to
the meta-data based on the non-NESTED
record types. Otherwise, it will update the records descriptor of
the currently stored meta-data (see updateRecords(Descriptors.FileDescriptor)
). The new union descriptor
will include any type in existing union and any new record type in the new file descriptor. This method will
process extension options.
fileDescriptor
- the file descriptor of the record meta-dataMetaDataProtoEditor.addDefaultUnionIfMissing(Descriptors.FileDescriptor)
public void saveRecordMetaData(@Nonnull RecordMetaDataProvider metaDataProvider)
metaDataProvider
- the meta-data providerpublic void saveRecordMetaData(@Nonnull RecordMetaDataProto.MetaData metaDataProto)
metaDataProto
- the serialized record meta-data@API(value=MAINTAINED) public CompletableFuture<Void> saveRecordMetaDataAsync(@Nonnull Descriptors.FileDescriptor fileDescriptor)
If the given records descriptor is missing a union message, this method will automatically add one to the descriptor
before saving the meta-data. If the meta-data store is currently empty, a default union descriptor will be added to
the meta-data based on the non-NESTED
record types. Otherwise, it will update the records descriptor of
the currently stored meta-data (see updateRecords(Descriptors.FileDescriptor)
). The new union descriptor
will include any type in existing union and any new record type in the new file descriptor. This method will
process extension options. Also the records descriptor of the meta-data will change while generating the union.
fileDescriptor
- the file descriptor of the record meta-dataMetaDataProtoEditor.addDefaultUnionIfMissing(Descriptors.FileDescriptor)
public void addIndex(@Nonnull String recordType, @Nonnull String indexName, @Nonnull String fieldName)
recordType
- the name of the record typeindexName
- the name of the new indexfieldName
- the field to be indexedpublic void addIndex(@Nonnull String recordType, @Nonnull String indexName, @Nonnull KeyExpression indexExpression)
recordType
- the name of the record typeindexName
- the name of the new indexindexExpression
- the root expression of the indexpublic void addIndex(@Nonnull String recordType, @Nonnull Index index)
recordType
- the name of the record typeindex
- the new index to be added@Nonnull public CompletableFuture<Void> addIndexAsync(@Nonnull String recordType, @Nonnull String indexName, @Nonnull String fieldName)
recordType
- the name of the record typeindexName
- the name of the new indexfieldName
- the field to be indexed@Nonnull public CompletableFuture<Void> addIndexAsync(@Nonnull String recordType, @Nonnull String indexName, @Nonnull KeyExpression indexExpression)
recordType
- the name of the record typeindexName
- the name of the new indexindexExpression
- the root expression of the index@Nonnull public CompletableFuture<Void> addIndexAsync(@Nonnull String recordType, @Nonnull Index index)
recordType
- the name of the record typeindex
- the index to be addedpublic void addMultiTypeIndex(@Nullable List<String> recordTypes, @Nonnull Index index)
recordTypes
- a list of record types that the index will includeindex
- the index to be added@Nonnull public CompletableFuture<Void> addMultiTypeIndexAsync(@Nullable List<String> recordTypes, @Nonnull Index index)
recordTypes
- a list of record types that the index will includeindex
- the index to be addedpublic void addUniversalIndex(@Nonnull Index index)
index
- the index to be added@Nonnull public CompletableFuture<Void> addUniversalIndexAsync(@Nonnull Index index)
index
- the index to be addedpublic void dropIndex(@Nonnull String indexName)
indexName
- the name of the index to be removed@Nonnull public CompletableFuture<Void> dropIndexAsync(@Nonnull String indexName)
indexName
- the name of the index to be removed@API(value=MAINTAINED) public void updateRecords(@Nonnull Descriptors.FileDescriptor recordsDescriptor)
It is important to note that if a local file descriptor is set using setLocalFileDescriptor(Descriptors.FileDescriptor)
,
the local file descriptor must be at least as evolved as the records descriptor passed to this method.
Otherwise, updateRecords
will fail.
If the given file descriptor is missing a union message, this method will add one before updating the meta-data.
The generated union descriptor is constructed by adding any non-NESTED
types in the file descriptor to the
union descriptor from the currently stored meta-data. A new field is not added if a field of the given type already
exists, and the order of any existing fields is preserved. Note that types are identified by name, so renaming
top-level message types may result in validation errors when trying to update the record descriptor. Also the records
descriptor of the meta-data will change while generating the union.
recordsDescriptor
- the new recordsDescriptor@Nonnull @API(value=MAINTAINED) public CompletableFuture<Void> updateRecordsAsync(@Nonnull Descriptors.FileDescriptor recordsDescriptor)
It is important to note that if a local file descriptor is set using setLocalFileDescriptor(Descriptors.FileDescriptor)
,
the local file descriptor must be at least as evolved as the records descriptor passed to this method.
Otherwise, updateRecordsAsync
will fail.
If the given file descriptor is missing a union message, this method will add one before updating the meta-data.
The generated union descriptor is constructed by adding any non-NESTED
types in the file descriptor to the
union descriptor from the currently stored meta-data. A new field is not added if a field of the given type already
exists, and the order of any existing fields is preserved. Note that types are identified by name, so renaming
top-level message types may result in validation errors when trying to update the record descriptor.
recordsDescriptor
- the new recordsDescriptorpublic void mutateMetaData(@Nonnull Consumer<RecordMetaDataProto.MetaData.Builder> mutateMetaDataProto)
This method applies the given mutation callback on the stored meta-data and then saves it back to the store.
Callers might need to provide an appropriate MetaDataEvolutionValidator
to the meta-data store, depending on the
changes that the callback performs.
Also, callers must be cautious about modifying the stored records descriptor using mutation callbacks, as this will make the
meta-data store the ultimate (and sole) source of truth for the record definitions and not just the in-database
copy of a .proto
file under source control.
mutateMetaDataProto
- a callback that mutates the meta-data protopublic void mutateMetaData(@Nonnull Consumer<RecordMetaDataProto.MetaData.Builder> mutateMetaDataProto, @Nullable Consumer<RecordMetaDataBuilder> mutateRecordMetaDataBuilder)
This method applies the given mutation callbacks on the stored meta-data and then saves it back to the store. Note the
order that the callbacks are executed. mutateMetaDataProto
is called first on the meta-data proto and then the
second mutateRecordMetaDataBuilder
is executed on the meta-data builder.
Callers might need to provide an appropriate MetaDataEvolutionValidator
to the meta-data store, depending on the
changes that the callbacks perform.
Also, callers must be cautious about modifying the stored records descriptor using mutation callbacks, as this will make the
meta-data store the ultimate (and sole) source of truth for the record definitions and not just the in-database
copy of a .proto
file under source control.
mutateMetaDataProto
- a callback that mutates the meta-data protomutateRecordMetaDataBuilder
- a callback that mutates the record meta-data builder after the meta-data proto is mutated@Nonnull public CompletableFuture<Void> mutateMetaDataAsync(@Nonnull Consumer<RecordMetaDataProto.MetaData.Builder> mutateMetaDataProto)
This method applies the given mutation callback on the stored meta-data and then saves it back to the store.
Callers might need to provide an appropriate MetaDataEvolutionValidator
to the meta-data store, depending on the
changes that the callback performs.
Also, callers must be cautious about modifying the stored records descriptor using mutation callbacks, as this will make the
meta-data store the ultimate (and sole) source of truth for the record definitions and not just the in-database
copy of a .proto
file under source control.
mutateMetaDataProto
- a callback that mutates the meta-data proto@Nonnull public CompletableFuture<Void> mutateMetaDataAsync(@Nonnull Consumer<RecordMetaDataProto.MetaData.Builder> mutateMetaDataProto, @Nullable Consumer<RecordMetaDataBuilder> mutateRecordMetaDataBuilder)
This method applies the given mutation callbacks on the stored meta-data and then saves it back to the store. Note the
order that the callbacks are executed. mutateMetaDataProto
is called first on the meta-data proto and then the
second mutateRecordMetaDataBuilder
is executed on the meta-data builder.
Callers might need to provide an appropriate MetaDataEvolutionValidator
to the meta-data store, depending on the
changes that the callbacks perform.
Also, callers must be cautious about modifying the stored records descriptor using mutation callbacks, as this will make the
meta-data store the ultimate (and sole) source of truth for the record definitions and not just the in-database
copy of a .proto
file under source control.
mutateMetaDataProto
- a callback that mutates the meta-data protomutateRecordMetaDataBuilder
- a callback that mutates the record meta-data builder after the meta-data proto is mutatedpublic void updateStoreRecordVersions(boolean storeRecordVersions)
storeRecordVersions
- whether record versions should be stored@Nonnull public CompletableFuture<Void> updateStoreRecordVersionsAsync(boolean storeRecordVersions)
storeRecordVersions
- whether record versions should be storedstoreRecordVersions
is updatedpublic void enableSplitLongRecords()
Note that enabling splitting long records could result in data corruption if the record store was initially created with a format version older than
FDBRecordStore.SAVE_UNSPLIT_WITH_SUFFIX_FORMAT_VERSION
.
Hence the default evolution validator will fail if one enables it. To enable this, first build a custom evolution validator that MetaDataEvolutionValidator.allowsUnsplitToSplit()
and use setEvolutionValidator(MetaDataEvolutionValidator)
to set the evolution validator used by this store.
For more details, see MetaDataEvolutionValidator.allowsUnsplitToSplit()
.
@Nonnull public CompletableFuture<Void> enableSplitLongRecordsAsync()
Note that enabling splitting long records could result in data corruption if the record store was initially created with a format version older than
FDBRecordStore.SAVE_UNSPLIT_WITH_SUFFIX_FORMAT_VERSION
.
Hence the default evolution validator will fail if one enables it. To enable this, first build a custom evolution validator that MetaDataEvolutionValidator.allowsUnsplitToSplit()
and use setEvolutionValidator(MetaDataEvolutionValidator)
to set the evolution validator used by this store.
For more details, see MetaDataEvolutionValidator.allowsUnsplitToSplit()
.
splitLongRecords
is set@Nullable public MetaDataCache getCache()