Store
An abstract Condensation store.
The ID is a string unique to the store, often loosely describing it, e.g.:
Object Cache Hash Verification Store https://condensation.io file:///srv/store
However, it should be treated as an opaque string, and not be interpreted or parsed. Two store instances with the same ID are interchangeable.
In the Java implementation, all store requests are non-blocking. You are passing a done handler to the request, and one of its functions will be invoked when the request has been executed.
In the JavaScript implementation, all store requests are non-blocking. The request function returns a done object, and one of its functions will be invoked when the request has been executed.
In the Perl implementation, all store requests are blocking. That means, the function waits until the request has been executed, and returns the result.
Instance creation
Every store implementation provides its own constructors.
Store requests
Get
store.get(hash, keyPair, done); class GetDone implements Store.GetDone { public void onGetDone(@NonNull CondensationObject object) { ... } public void onGetNotFound() { ... } public void onGetFailed(@NonNull String error) { ... } }
var done = store.get(hash, keyPair); done.onDone = function(object) { ... }; done.onNotFound = function() { ... }; done.onFailed = function(error) { ... };
my ($object, $error) = $store->get($hash, $keyPair); if (defined $error) { # request failed } elsif (defined $object) { # found } else { # not found }
Retrieves the desired object from the store.
Under normal conditions, the received object matches the requested hash. Failure to do so points to data corruption or tampering, and should be treated as an unexpected error that requires investigation by an IT specialist.
Unless specified otherwise, stores do not verify the hash of the retrieved object. Use a hash verification store where this makes sense.
The key pair is used to sign the request in case the store requires authentication. If the request fails, a technical error message is returned.
Put
store.put(hash, object, keyPair, done); class PutDone implements Store.PutDone { public void onPutDone() { ... } public void onPutFailed(@NonNull String error) { ... } }
var done = store.put(hash, object, keyPair); done.onDone = function() { ... }; done.onFailed = function(error) { ... };
my $error = $store->put($hash, $object, $keyPair); if (defined $error) { # request failed } else { # done }
Uploads an object onto the store.
The hash must match the object. The key pair is used to sign the request in case the store requires authentication. If the request fails, a technical error message is returned.
Book
store.book(hash, keyPair, done); class BookDone implements Store.BookDone { public void onBookDone() { ... } public void onBookNotFound() { ... } public void onBookFailed(@NonNull String error) { ... } }
var done = store.book(hash, keyPair); done.onDone = function() { ... }; done.onNotFound = function() { ... }; done.onFailed = function(error) { ... };
my ($booked, $error) = $store->book($hash, $keyPair); if (defined $error) { # request failed } elsif ($booked) { # booked } else { # not found (and therefore not booked) }
Books the object on the store, and returns whether booking succeeded.
The key pair is used to sign the request in case the store requires authentication. If the request fails, a technical error message is returned.
List
store.list(accountHash, boxLabel, keyPair, done); class ListDone implements Store.ListDone { public void onListDone(@NonNull Iterable<Hash> hashes) { ... } public void onListFailed(@NonNull String error) { ... } }
var done = store.list(accountHash, boxLabel, keyPair); done.onDone = function(hashes) { ... }; done.onFailed = function(error) { ... };
my ($hashes, $error) = $store->list($accountHash, $boxLabel, $keyPair); if (defined $error) { # request failed } else { for my $hash (@$hashes) { ... } }
Lists the corresponding box on the store.
The returned hash list may contain duplicates. The key pair is used to sign the request in case the store requires authentication. If the request fails, a technical error message is returned.
Modify
store.modify(boxAdditions, boxRemovals, keyPair, done); class ModifyDone implements Store.ModifyDone { public void onModifyDone() { ... } public void onModifyFailed(@NonNull String error) { ... } }
var done = store.modify(boxAdditions, boxRemovals, keyPair); done.onDone = function() { ... }; done.onFailed = function(error) { ... };
my $error = $store->modify($boxAdditions, $boxRemovals, $keyPair); if (defined $error) { # request failed } else { # done }
Modifies boxes on the store.
The key pair is used to sign the request in case the store requires authentication. If the request fails, a technical error message is returned.
Threading
Stores must always be accessed from the main thread. If necessary, they will offload work onto different threads.
Implementations
Store | Availability |
---|---|
HTTP store | All platforms |
In-memory store | All platforms |
Hash verification store | All platforms |
Get from any store | All platforms |
Folder store | Java, Perl |
FTP store | Perl |
SFTP store | Perl |
Object cache | Perl, Java/Android |
Split store | Perl |
Log store | Perl |
Implementing a store
A minimal store implementation must provide the above store access functions.
The constructor should be lightweight, since store instances are created frequently, and sometimes without actually accessing the store. In most cases, it should just set URL and ID, and perhaps a few other fields. It should not connect to a server, for instance, or carry out other work. A store instance can also be created if the store is temporarily or permanently not available.
On multi-threaded platforms, the store access functions are always called from the main thread, but may obviously carry out their work on separate threads. The done handlers must be called on the main thread.
Since many store instances may be created for the same store, they should avoid keeping internal state. If necessary, state should be managed globally. Stores accessing the network typically manage a connection pool, for example, which ultimately carries out the requests. With this approach, a store instance is merely a lightweight interface to the connection pool:
A store implementation may offer additional functions, such as garbage collection or account administration. Such functions are available when the store is instantiated directly, and not through an URL.