Skip to content

Commit

Permalink
feat: additional operations, SDK alignment, ver. 0.9.0.5
Browse files Browse the repository at this point in the history
  • Loading branch information
dxps committed Mar 2, 2021
1 parent 0765f2e commit e919ec9
Show file tree
Hide file tree
Showing 13 changed files with 238 additions and 106 deletions.
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ immudb4j implements a [gRPC] immudb client, based on [immudb's official protobuf
It exposes a minimal and simple to use API for applications, while the cryptographic verifications and state update protocol implementation
are fully implemented internally by this client.

The latest validated immudb state may be kept in the local file system using default `FileRootHolder`.<br/>
The latest validated immudb state may be kept in the local file system using default `FileImmuStateHolder`.<br/>
Please read [immudb Research Paper] for details of how immutability is ensured by [immudb].

[gRPC]: https://grpc.io/
Expand All @@ -55,12 +55,12 @@ Just include immudb4j as a dependency in your project:
<dependency>
<groupId>io.codenotary</groupId>
<artifactId>immudb4j</artifactId>
<version>0.9.0.4</version>
<version>0.9.0.5</version>
</dependency>
```
- if using Gradle:
```groovy
compile 'io.codenotary:immudb4j:0.9.0.4'
compile 'io.codenotary:immudb4j:0.9.0.5'
```

`immudb4j` is currently hosted on both [Maven Central] and [Github Packages].
Expand Down Expand Up @@ -89,7 +89,7 @@ immudb4j supports the [latest immudb server] release, that is 0.9.1 at the time

Follow its [README](https://github.com/codenotary/immudb-client-examples/blob/master/java/README.md) to build and run it.

## Step-by-step guide
## Step-by-step Guide

### Creating a Client

Expand Down Expand Up @@ -150,7 +150,7 @@ Specify the active database with:

### Standard Read and Write

immudb provides standard read and write operations that behave as in a traditional
immudb provides standard read and write operations that behave as in a standard
key-value store i.e. no cryptographic verification is involved. Such operations
may be used when validations can be postponed.

Expand All @@ -160,10 +160,10 @@ may be used when validations can be postponed.
byte[] v = client.get("k123");
```

### Verified or Safe read and write
### Verified or Safe Read and Write

immudb provides built-in cryptographic verification for any entry. The client
implements the mathematical validations while the application uses as a traditional
implements the mathematical validations while the application uses as a standard
read or write operation:

```java
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ apply plugin: 'signing'

group = 'io.codenotary'
archivesBaseName = 'immudb4j'
version = '0.9.0.4'
version = '0.9.0.5'

sourceCompatibility = 1.8
targetCompatibility = 1.8
Expand Down
86 changes: 62 additions & 24 deletions src/main/java/io/codenotary/immudb4j/ImmuClient.java
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public class ImmuClient {

private static final String AUTH_HEADER = "authorization";
private final ImmuServiceGrpc.ImmuServiceBlockingStub stub;
private final boolean withAuthToken;
private final boolean withAuth;
private final ImmuStateHolder stateHolder;
private ManagedChannel channel;
private String authToken;
Expand All @@ -62,7 +62,7 @@ public class ImmuClient {

public ImmuClient(Builder builder) {
this.stub = createStubFrom(builder);
this.withAuthToken = builder.isWithAuthToken();
this.withAuth = builder.isWithAuth();
this.stateHolder = builder.getStateHolder();
}

Expand Down Expand Up @@ -111,7 +111,7 @@ public synchronized boolean isShutdown() {
}

private ImmuServiceGrpc.ImmuServiceBlockingStub getStub() {
if (!withAuthToken || authToken == null) {
if (!withAuth || authToken == null) {
return stub;
}
Metadata metadata = new Metadata();
Expand Down Expand Up @@ -377,18 +377,28 @@ public Entry verifiedGetSince(byte[] key, long txId) throws VerificationExceptio
// ========== HISTORY ==========
//

public List<KV> history(String key, int limit, long offset, boolean reverse) {
return history(key.getBytes(StandardCharsets.UTF_8), limit, offset, reverse);

public List<KV> history(String key, int limit, long offset, boolean desc) {
return history(key.getBytes(StandardCharsets.UTF_8), limit, offset, desc);
}

public List<KV> history(byte[] key, int limit, long offset, boolean desc) {
return history(key, limit, offset, desc, 1);
}

public List<KV> history(byte[] key, int limit, long offset, boolean reverse) {
public List<KV> history(String key, int limit, long offset, boolean desc, long sinceTxId) {
return history(key.getBytes(StandardCharsets.UTF_8), limit, offset, desc, sinceTxId);
}

public List<KV> history(byte[] key, int limit, long offset, boolean desc, long sinceTxId) {
ImmudbProto.Entries entries;
try {
entries = getStub().history(ImmudbProto.HistoryRequest.newBuilder()
.setKey(ByteString.copyFrom(key))
.setLimit(limit)
.setOffset(offset)
.setDesc(reverse)
.setDesc(desc)
.setSinceTx(sinceTxId)
.build()
);
} catch (StatusRuntimeException e) {
Expand All @@ -401,26 +411,45 @@ public List<KV> history(byte[] key, int limit, long offset, boolean reverse) {
// ========== SCAN ==========
//

public List<KV> scan(String key) {
return scan(ByteString.copyFrom(key, StandardCharsets.UTF_8).toByteArray());
public List<KV> scan(String prefix) {
return scan(ByteString.copyFrom(prefix, StandardCharsets.UTF_8).toByteArray());
}

public List<KV> scan(String prefix, long sinceTxId, long limit, boolean desc) {
return scan(ByteString.copyFrom(prefix, StandardCharsets.UTF_8).toByteArray(), sinceTxId, limit, desc);
}

public List<KV> scan(String key, long sinceTxId, long limit, boolean reverse) {
return scan(ByteString.copyFrom(key, StandardCharsets.UTF_8).toByteArray(), sinceTxId, limit, reverse);
public List<KV> scan(String prefix, String seekKey, long sinceTxId, long limit, boolean desc) {
return scan(
ByteString.copyFrom(prefix, StandardCharsets.UTF_8).toByteArray(),
ByteString.copyFrom(seekKey, StandardCharsets.UTF_8).toByteArray(),
sinceTxId, limit, desc);
}

public List<KV> scan(byte[] key) {
ScanRequest req = ScanRequest.newBuilder().setPrefix(ByteString.copyFrom(key)).build();
public List<KV> scan(byte[] prefix) {
ScanRequest req = ScanRequest.newBuilder().setPrefix(ByteString.copyFrom(prefix)).build();
ImmudbProto.Entries entries = getStub().scan(req);
return buildList(entries);
}

public List<KV> scan(byte[] key, long sinceTxId, long limit, boolean reverse) {
public List<KV> scan(byte[] prefix, long sinceTxId, long limit, boolean desc) {
ScanRequest req = ScanRequest.newBuilder()
.setPrefix(ByteString.copyFrom(key))
.setPrefix(ByteString.copyFrom(prefix))
.setLimit(limit)
.setSinceTx(sinceTxId)
.setDesc(reverse)
.setDesc(desc)
.build();
ImmudbProto.Entries entries = getStub().scan(req);
return buildList(entries);
}

public List<KV> scan(byte[] prefix, byte[] seekKey, long sinceTxId, long limit, boolean desc) {
ScanRequest req = ScanRequest.newBuilder()
.setPrefix(ByteString.copyFrom(prefix))
.setLimit(limit)
.setSeekKey(ByteString.copyFrom(seekKey))
.setSinceTx(sinceTxId)
.setDesc(desc)
.build();
ImmudbProto.Entries entries = getStub().scan(req);
return buildList(entries);
Expand Down Expand Up @@ -800,12 +829,12 @@ public List<Tx> txScan(long initialTxId) {
return buildList(txList);
}

public List<Tx> txScan(long initialTxId, int limit, boolean reverse) {
public List<Tx> txScan(long initialTxId, int limit, boolean desc) {
ImmudbProto.TxScanRequest req = ImmudbProto.TxScanRequest
.newBuilder()
.setInitialTx(initialTxId)
.setLimit(limit)
.setDesc(reverse)
.setDesc(desc)
.build();
ImmudbProto.TxList txList = getStub().txScan(req);
return buildList(txList);
Expand Down Expand Up @@ -892,6 +921,15 @@ public void changePassword(String user, String oldPassword, String newPassword)
getStub().changePassword(changePasswordRequest);
}

//
// ========== USER MGMT ==========
//

public void cleanIndex() {
//noinspection ResultOfMethodCallIgnored
getStub().cleanIndex(Empty.getDefaultInstance());
}

//
// ========== INTERNAL UTILS ==========
//
Expand Down Expand Up @@ -932,15 +970,15 @@ public static class Builder {

private int serverPort;

private boolean withAuthToken;
private boolean withAuth;

private ImmuStateHolder stateHolder;

private Builder() {
this.serverUrl = "localhost";
this.serverPort = 3322;
this.stateHolder = new SerializableImmuStateHolder();
this.withAuthToken = true;
this.withAuth = true;
}

public ImmuClient build() {
Expand All @@ -965,12 +1003,12 @@ public Builder withServerPort(int serverPort) {
return this;
}

public boolean isWithAuthToken() {
return withAuthToken;
public boolean isWithAuth() {
return withAuth;
}

public Builder withAuthToken(boolean withAuthToken) {
this.withAuthToken = withAuthToken;
public Builder withAuth(boolean withAuth) {
this.withAuth = withAuth;
return this;
}

Expand Down
80 changes: 80 additions & 0 deletions src/test/java/io/codenotary/immudb4j/HistoryTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
Copyright 2021 CodeNotary, Inc. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package io.codenotary.immudb4j;

import io.codenotary.immudb4j.exceptions.CorruptedDataException;
import org.testng.Assert;
import org.testng.annotations.Test;

import java.nio.charset.StandardCharsets;
import java.util.List;

public class HistoryTest extends ImmuClientIntegrationTest {

@Test(testName = "set, history", priority = 2)
public void t1() {

immuClient.login("immudb", "immudb");
immuClient.useDatabase("defaultdb");

byte[] value1 = {0, 1, 2, 3};
byte[] value2 = {4, 5, 6, 7};
byte[] value3 = {8, 9, 10, 11};

try {
immuClient.set("history1", value1);
immuClient.set("history1", value2);
immuClient.set("history2", value1);
immuClient.set("history2", value2);
immuClient.set("history2", value3);
} catch (CorruptedDataException e) {
Assert.fail("Failed at set.", e);
}

List<KV> historyResponse1 = immuClient.history("history1", 10, 0, false);

Assert.assertEquals(historyResponse1.size(), 2);

Assert.assertEquals(historyResponse1.get(0).getKey(), "history1".getBytes(StandardCharsets.UTF_8));
Assert.assertEquals(historyResponse1.get(0).getValue(), value1);

Assert.assertEquals(historyResponse1.get(1).getKey(), "history1".getBytes(StandardCharsets.UTF_8));
Assert.assertEquals(historyResponse1.get(1).getValue(), value2);

List<KV> historyResponse2 = immuClient.history("history2", 10, 0, false);

Assert.assertEquals(historyResponse2.size(), 3);

Assert.assertEquals(historyResponse2.get(0).getKey(), "history2".getBytes(StandardCharsets.UTF_8));
Assert.assertEquals(historyResponse2.get(0).getValue(), value1);

Assert.assertEquals(historyResponse2.get(1).getKey(), "history2".getBytes(StandardCharsets.UTF_8));
Assert.assertEquals(historyResponse2.get(1).getValue(), value2);

Assert.assertEquals(historyResponse2.get(2).getKey(), "history2".getBytes(StandardCharsets.UTF_8));
Assert.assertEquals(historyResponse2.get(2).getValue(), value3);

historyResponse2 = immuClient.history("history2", 10, 2, false, 5);
Assert.assertNotNull(historyResponse2);
Assert.assertEquals(historyResponse2.size(), 1);

List<KV> nonExisting = immuClient.history("nonExisting", 10, 0, false);
Assert.assertTrue(nonExisting.isEmpty());

immuClient.logout();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ public static void beforeClass() throws IOException {
.withStateHolder(stateHolder)
.withServerUrl("localhost")
.withServerPort(3322)
.withAuthToken(true)
.build();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,17 @@
import org.testng.Assert;
import org.testng.annotations.Test;

public class LoginAndHealthCheckTest extends ImmuClientIntegrationTest {
public class LoginAndHealthCheckAndCleanIndexTest extends ImmuClientIntegrationTest {

@Test(testName = "login (with default credentials), healthCheck, logout")
public void t1() {

immuClient.login("immudb", "immudb");

Assert.assertTrue(immuClient.healthCheck());
boolean isHealthy = immuClient.healthCheck();
Assert.assertTrue(isHealthy);

immuClient.cleanIndex();

immuClient.logout();
}
Expand Down
2 changes: 2 additions & 0 deletions src/test/java/io/codenotary/immudb4j/ReferenceTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ public void t1() {
}
Assert.assertNotNull(ref1TxMd);



TxMetadata ref2TxMd = null;
try {
ref2TxMd = immuClient.setReferenceAt(ref2Key, key, setTxMd.id);
Expand Down
Loading

0 comments on commit e919ec9

Please sign in to comment.