- Type Parameters:
 T- This is the type of data, which is always an implementation of theDbDataclass. See the code ofInmatefor an example of how this should look.
     There are two kinds of database provided, which only differ in how they
     store data on disk.  The "classic" kind, Db, stores each piece of
     data in its own file.  This is the simplest approach.
 
     However, for significant speed gains, the new DbEngine2 will
     store each change as an append to a file, and will consolidate the on-disk
     data occasionally, and on start.  That way is thousands of times faster
     to write to disk and to read from disk at startup.
 
- 
Field Summary
FieldsModifier and TypeFieldDescriptionprotected final ContextHolds some system-wide information that is beneficial for components of the databaseThe internal data structure of the database that resides in memory.protected final PathThe directory of the database on diskprotected final TAn empty instance of the type of data stored by this database, used for better handling of generics.protected final FileUtilsUsed for handling some file utilities in the database like creating directoriesprotected AtomicLongThe current index, used when creating new data items.protected final ILoggerUsed for providing logging throughout the databaseThis map holds the functions that are registered to indexes, which are used to construct the mappings between string values and items in the database.This data structure is a nested map used for providing indexed data search. - 
Constructor Summary
ConstructorsModifierConstructorDescriptionprotectedAbstractDb(Path dbDirectory, Context context, T instance)  - 
Method Summary
Modifier and TypeMethodDescriptionprotected voidaddToIndexes(T dbData) add the data to registered indexes.abstract voidDelete dataprotected voiddeleteFromMemory(T dataToDelete) Remove a particular item from the internal data structure in memoryfindExactlyOne(String indexName, String indexKey) A utility to find exactly one item from the database.findExactlyOne(String indexName, String indexKey, Callable<T> alternate) Find one item, with an alternate value if null
This utility will search the indexes for a particular data by indexName and indexKey.getIndexedData(String indexName, String key) Given the name of a registered index (seeregisterIndex(String, Function)), use the key to find the collection of data that matches it.Get a set of the currently-registered indexes on this database, useful for debugging.abstract voidloadData()Grabs all the data from disk and returns it as a list.protected booleanprocessDataIndex(T newData) When new data comes in, we look at its "index" value.booleanregisterIndex(String indexName, Function<T, String> keyObtainingFunction) Register an index in the database for higher performance data access.abstract voidstop()Used to cleanly stop the database.abstract voidstop(int count, int sleepTime) Used to cleanly stop the database, with extra allowance of time for cleanup.abstract Collection<T> values()This method provides read capability for the values of a database.abstract TWrite data to the database.protected voidwriteToMemory(T newData, boolean newElementCreated) Write database data into memory 
- 
Field Details
- 
dbDirectory
The directory of the database on disk - 
emptyInstance
An empty instance of the type of data stored by this database, used for better handling of generics. - 
fileUtils
Used for handling some file utilities in the database like creating directories - 
context
Holds some system-wide information that is beneficial for components of the database - 
logger
Used for providing logging throughout the database - 
data
The internal data structure of the database that resides in memory. The beating heart of the database while it runs. - 
index
The current index, used when creating new data items. Each item has its own index value, this is where it is tracked. - 
registeredIndexes
This data structure is a nested map used for providing indexed data search.
The outer map is between the name of the index and the inner map.
The inner map is between strings and sets of items related to that string. - 
partitioningMap
This map holds the functions that are registered to indexes, which are used to construct the mappings between string values and items in the database. 
 - 
 - 
Constructor Details
- 
AbstractDb
 
 - 
 - 
Method Details
- 
stop
public abstract void stop() - 
stop
public abstract void stop(int count, int sleepTime) Used to cleanly stop the database, with extra allowance of time for cleanup.
Note that this method mostly applies toDb, and not as much toDbEngine2. Only Db uses a processing queue on a thread which is what requires a longer shutdown time for interruption.- Parameters:
 count- number of loops before we are done waiting for a clean close and instead crash the instance closed.sleepTime- how long to wait, in milliseconds, for each iteration of the waiting loop.
 - 
write
Write data to the database. Use an index of 0 to store new data, and a positive non-zero value to update data.Example of adding new data to the database:
final var newSalt = StringUtils.generateSecureRandomString(10); final var hashedPassword = CryptoUtils.createPasswordHash(newPassword, newSalt); final var newUser = new User(0L, newUsername, hashedPassword, newSalt); userDb.write(newUser);Example of updating data:
// write the updated salted password to the database final var updatedUser = new User( user().getIndex(), user().getUsername(), hashedPassword, newSalt); userDb.write(updatedUser);- Parameters:
 newData- the data we are writing- Returns:
 - the data with its new index assigned.
 
 - 
writeToMemory
Write database data into memory- Parameters:
 newData- the new data may be totally new or an updatenewElementCreated- if true, this is a create. If false, an update.
 - 
processDataIndex
When new data comes in, we look at its "index" value. If it is zero, it's a create, and we assign it a new value. If it is positive, it is an update, and we had better find it in the database already, or else throw an exception.- Returns:
 - true if a create, false if an update
 
 - 
delete
Delete dataExample:
userDb.delete(user);- Parameters:
 dataToDelete- the data we are serializing and writing
 - 
deleteFromMemory
Remove a particular item from the internal data structure in memory - 
addToIndexes
add the data to registered indexes.
For each of the registered indexes, get the stored function to obtain a string value which helps divide the overall data into partitions. - 
loadData
Grabs all the data from disk and returns it as a list. This method is run by various programs when the system first loads.- Throws:
 IOException
 - 
values
This method provides read capability for the values of a database.
The returned collection is a read-only view over the data, throughCollections.unmodifiableCollection(Collection)Example:
boolean doesUserAlreadyExist(String username) { return userDb.values().stream().anyMatch(x -> x.getUsername().equals(username)); } - 
registerIndex
Register an index in the database for higher performance data access.This command should be run immediately after database declaration, or more specifically, before any data is loaded from disk. Otherwise, it would be possible to skip indexing that data.
Example:final var myDatabase = context.getDb("photos", Photograph.EMPTY); myDatabase.registerIndex("url", photo -> photo.getUrl());- Parameters:
 indexName- a string used to distinguish this index. This string will be used again when requesting data in a method likegetIndexedData(java.lang.String, java.lang.String)orfindExactlyOne(java.lang.String, java.lang.String)keyObtainingFunction- a function which obtains data from the data in this database, used to partition the data into groups (potentially up to a 1-to-1 correspondence between id and object)- Returns:
 - true if the registration succeeded
 - Throws:
 DbException- if the parameters are not entered properly, if the index has already been registered, or if the data has already been loaded. It is necessary that this is run immediately after declaring the database. To explain further: the data is not actually loaded until the first time it is needed, such as running a write or delete, or if theloadData()()} method is run. Creating an index map for the data that is read from disk only occurs once, at data load time. Thus, it is crucial that the registerIndex command is run before any data is loaded.
 - 
getIndexedData
Given the name of a registered index (seeregisterIndex(String, Function)), use the key to find the collection of data that matches it.- Parameters:
 indexName- the name of an indexkey- a string value that matches a partition calculated from the partition function provided toregisterIndex(String, Function)- Returns:
 - a collection of data, an empty collection if nothing found
 
 - 
getSetOfIndexes
Get a set of the currently-registered indexes on this database, useful for debugging. - 
findExactlyOne
A utility to find exactly one item from the database.
This utility will search the indexes for a particular data by indexName and indexKey. If not found, it will return null. If found, it will be returned. If more than one are found, an exception will be thrown. Use this tool when the data has been uniquely indexed, like for example when setting a unique identifier into each data.- Parameters:
 indexName- the name of the index, an arbitrary value set by the user to help distinguish among potentially many indexes set on this dataindexKey- the key for this particular value, such as a UUID or a name or any other way to partition the data- See Also:
 
 - 
findExactlyOne
Find one item, with an alternate value if null
This utility will search the indexes for a particular data by indexName and indexKey. If not found, it will return null. If found, it will be returned. If more than one are found, an exception will be thrown. Use this tool when the data has been uniquely indexed, like for example when setting a unique identifier into each data.- Parameters:
 indexName- the name of the index, an arbitrary value set by the user to help distinguish among potentially many indexes set on this dataindexKey- the key for this particular value, such as a UUID or a name or any other way to partition the dataalternate- a functional interface that will be run if the result would have been null, useful for situations where you don't want the output to be null when nothing is found.- See Also:
 
 
 -