Skip to content

Commit 9588a6a

Browse files
committed
feat: add serverUUID as part of states mgmt (persistence), fix(UserMgmtTest), version bump to 0.9.0.3
1 parent 72bd20e commit 9588a6a

File tree

11 files changed

+118
-52
lines changed

11 files changed

+118
-52
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,12 @@ Just include immudb4j as a dependency in your project:
5555
<dependency>
5656
<groupId>io.codenotary</groupId>
5757
<artifactId>immudb4j</artifactId>
58-
<version>0.9.0.2</version>
58+
<version>0.9.0.3</version>
5959
</dependency>
6060
```
6161
- if using Gradle:
6262
```groovy
63-
compile 'io.codenotary:immudb4j:0.9.0.2'
63+
compile 'io.codenotary:immudb4j:0.9.0.3'
6464
```
6565

6666
`immudb4j` is currently hosted on both [Maven Central] and [Github Packages].
@@ -77,9 +77,9 @@ and _Configuring Gradle for use with GitHub Packages_ at [Github Packages].
7777

7878
## Supported Versions
7979

80-
immudb4j supports the [latest immudb release], that is 0.9.1 at the time of this writing.
80+
immudb4j supports the [latest immudb server] release, that is 0.9.1 at the time of updating this document.
8181

82-
[latest immudb release]: https://github.com/codenotary/immudb/releases/tag/v0.9.1
82+
[latest immudb server]: https://github.com/codenotary/immudb/releases/tag/v0.9.1
8383

8484
## Quickstart
8585

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ apply plugin: 'signing'
3838

3939
group = 'io.codenotary'
4040
archivesBaseName = 'immudb4j'
41-
version = '0.9.0.2'
41+
version = '0.9.0.3'
4242

4343
sourceCompatibility = 1.8
4444
targetCompatibility = 1.8

immudb/clean.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,5 @@ fi
1313
rm -rf data
1414
rm -rf states
1515

16-
echo "immudb4j data and states folders were removed."
16+
echo "immudb's data and immudb4j's states folders were removed."
1717

src/main/java/io/codenotary/immudb4j/FileImmuStateHolder.java

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ private FileImmuStateHolder(Builder builder) throws IOException, IllegalStateExc
4545

4646
stateHolder = new SerializableImmuStateHolder();
4747

48-
String lastRootFilename = new String(Files.readAllBytes(currentStateFile));
48+
String lastStateFilename = new String(Files.readAllBytes(currentStateFile));
4949

50-
if (!lastRootFilename.isEmpty()) {
51-
stateHolderFile = statesFolder.resolve(lastRootFilename);
50+
if (!lastStateFilename.isEmpty()) {
51+
stateHolderFile = statesFolder.resolve(lastStateFilename);
5252

5353
if (Files.notExists(stateHolderFile)) {
5454
throw new IllegalStateException("Inconsistent current state file");
@@ -59,40 +59,40 @@ private FileImmuStateHolder(Builder builder) throws IOException, IllegalStateExc
5959
}
6060

6161
@Override
62-
public synchronized ImmuState getState(String database) {
63-
return stateHolder.getState(database);
62+
public synchronized ImmuState getState(String serverUuid, String database) {
63+
return stateHolder.getState(serverUuid, database);
6464
}
6565

6666
@Override
67-
public synchronized void setState(ImmuState state) throws IllegalStateException {
68-
ImmuState currentState = stateHolder.getState(state.database);
67+
public synchronized void setState(String serverUuid, ImmuState state) throws IllegalStateException {
6968

69+
ImmuState currentState = stateHolder.getState(serverUuid, state.database);
7070
if (currentState != null && currentState.txId >= state.txId) {
7171
return;
7272
}
7373

74-
stateHolder.setState(state);
74+
stateHolder.setState(serverUuid, state);
7575

76-
Path newStateHolderFile = statesFolder.resolve("state_" + System.nanoTime());
76+
Path newStateFile = statesFolder.resolve("state_" + serverUuid + "_" + state.database + "_" + System.nanoTime());
7777

78-
if (Files.exists(newStateHolderFile)) {
79-
throw new RuntimeException("Failed attempting to create fresh state file. Please retry.");
78+
if (Files.exists(newStateFile)) {
79+
throw new RuntimeException("Failed attempting to create a new state file. Please retry.");
8080
}
8181

8282
try {
83-
Files.createFile(newStateHolderFile);
84-
stateHolder.writeTo(Files.newOutputStream(newStateHolderFile));
83+
Files.createFile(newStateFile);
84+
stateHolder.writeTo(Files.newOutputStream(newStateFile));
8585

8686
BufferedWriter bufferedWriter = Files.newBufferedWriter(currentStateFile, StandardOpenOption.TRUNCATE_EXISTING);
87-
bufferedWriter.write(newStateHolderFile.getFileName().toString());
87+
bufferedWriter.write(newStateFile.getFileName().toString());
8888
bufferedWriter.flush();
8989
bufferedWriter.close();
9090

9191
if (stateHolderFile != null) {
9292
Files.delete(stateHolderFile);
9393
}
9494

95-
stateHolderFile = newStateHolderFile;
95+
stateHolderFile = newStateFile;
9696
} catch (IOException e) {
9797
e.printStackTrace();
9898
throw new IllegalStateException("Unexpected error " + e);

src/main/java/io/codenotary/immudb4j/ImmuClient.java

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ public class ImmuClient {
5757
private final ImmuStateHolder stateHolder;
5858
private ManagedChannel channel;
5959
private String authToken;
60+
private String currentServerUuid;
6061
private String currentDb = "defaultdb";
6162

6263
public ImmuClient(Builder builder) {
@@ -72,10 +73,24 @@ public static Builder newBuilder() {
7273
private ImmuServiceGrpc.ImmuServiceBlockingStub createStubFrom(Builder builder) {
7374
channel = ManagedChannelBuilder.forAddress(builder.getServerUrl(), builder.getServerPort())
7475
.usePlaintext()
76+
.intercept(new ImmuServerUUIDInterceptor(this))
7577
.build();
7678
return ImmuServiceGrpc.newBlockingStub(channel);
7779
}
7880

81+
// ---------------------------------------------------------------------
82+
// These two currentServerUuid related methods are not publicly exposed,
83+
// since these should be called by the ImmuServerUUIDInterceptor only.
84+
85+
void setCurrentServerUuid(String serverUuid) {
86+
currentServerUuid = serverUuid;
87+
}
88+
89+
String getCurrentServerUuid() {
90+
return currentServerUuid;
91+
}
92+
// ---------------------------------------------------------------------
93+
7994
public synchronized void shutdown() {
8095
if (channel == null) {
8196
return;
@@ -99,7 +114,6 @@ private ImmuServiceGrpc.ImmuServiceBlockingStub getStub() {
99114
if (!withAuthToken || authToken == null) {
100115
return stub;
101116
}
102-
103117
Metadata metadata = new Metadata();
104118
metadata.put(Metadata.Key.of(AUTH_HEADER, Metadata.ASCII_STRING_MARSHALLER), "Bearer " + authToken);
105119

@@ -128,10 +142,10 @@ public synchronized void logout() {
128142
* If nothing exists already, it is fetched from the server and save it locally.
129143
*/
130144
public ImmuState state() {
131-
ImmuState state = stateHolder.getState(currentDb);
145+
ImmuState state = stateHolder.getState(currentServerUuid, currentDb);
132146
if (state == null) {
133147
state = currentState();
134-
stateHolder.setState(state);
148+
stateHolder.setState(currentServerUuid, state);
135149
}
136150
return state;
137151
}
@@ -336,7 +350,7 @@ private Entry verifiedGet(ImmudbProto.KeyRequest keyReq, ImmuState state) throws
336350
// TODO: to-be-implemented (see pkg/client/client.go:620, newState.CheckSignature(c.serverSigningPubKey))
337351
// if (serverSigningPubKey != null) { }
338352

339-
stateHolder.setState(newState);
353+
stateHolder.setState(currentServerUuid, newState);
340354

341355
return Entry.valueOf(vEntry.getEntry());
342356
}
@@ -527,7 +541,7 @@ public TxMetadata verifiedSet(byte[] key, byte[] value) throws VerificationExcep
527541
// TODO: to-be-implemented (see pkg/client/client.go:803 newState.CheckSignature ...)
528542
// if (serverSigningPubKey != null) { ... }
529543

530-
stateHolder.setState(newState);
544+
stateHolder.setState(currentServerUuid, newState);
531545

532546
return TxMetadata.valueOf(vtx.getTx().getMetadata());
533547
}
@@ -579,7 +593,7 @@ public TxMetadata verifiedSetReferenceAt(byte[] key, byte[] referencedKey, long
579593
// TODO: to-be-implemented (see pkg/client/client.go:1122 newState.CheckSignature ...)
580594
// if (serverSigningPubKey != null) { ... }
581595

582-
stateHolder.setState(newState);
596+
stateHolder.setState(currentServerUuid, newState);
583597

584598
return TxMetadata.valueOf(vtx.getTx().getMetadata());
585599
}
@@ -686,7 +700,7 @@ public TxMetadata verifiedZAddAt(byte[] set, double score, byte[] key, long atTx
686700
// TODO: to-be-implemented (see pkg/client/client.go:803 newState.CheckSignature ...)
687701
// if (serverSigningPubKey != null) { ... }
688702

689-
stateHolder.setState(newState);
703+
stateHolder.setState(currentServerUuid, newState);
690704

691705
return TxMetadata.valueOf(vtx.getTx().getMetadata());
692706
}
@@ -769,7 +783,7 @@ public Tx verifiedTxById(long txId) throws VerificationException {
769783
// TODO: to-be-implemented (see pkg/client/client.go:803 newState.CheckSignature ...)
770784
// if (serverSigningPubKey != null) { ... }
771785

772-
stateHolder.setState(newState);
786+
stateHolder.setState(currentServerUuid, newState);
773787

774788
Tx tx = null;
775789
try {
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package io.codenotary.immudb4j;
2+
3+
import io.grpc.*;
4+
import io.grpc.ForwardingClientCallListener.SimpleForwardingClientCallListener;
5+
6+
7+
public class ImmuServerUUIDInterceptor implements ClientInterceptor {
8+
9+
private static final String SERVER_UUID = "immudb-uuid";
10+
11+
private final ImmuClient client;
12+
13+
public ImmuServerUUIDInterceptor(ImmuClient client) {
14+
this.client = client;
15+
}
16+
17+
@Override
18+
public <ReqT, RespT> ClientCall<ReqT, RespT> interceptCall(
19+
MethodDescriptor<ReqT, RespT> method,
20+
CallOptions callOptions, Channel next) {
21+
22+
return new ForwardingClientCall.SimpleForwardingClientCall<ReqT, RespT>(next.newCall(method, callOptions)) {
23+
24+
@Override
25+
public void start(Listener<RespT> responseListener, Metadata headers) {
26+
27+
SimpleForwardingClientCallListener<RespT> listener = new SimpleForwardingClientCallListener<RespT>(responseListener) {
28+
29+
@Override
30+
public void onHeaders(Metadata headers) {
31+
String serverUuid = headers.get(Metadata.Key.of(SERVER_UUID, Metadata.ASCII_STRING_MARSHALLER));
32+
if (serverUuid != null && !serverUuid.equals(client.getCurrentServerUuid())) {
33+
client.setCurrentServerUuid(serverUuid);
34+
// System.out.printf(">>> ImmuServerUUIDInterceptor > Updated currentServerUuid to '%s'.\n", serverUuid);
35+
}
36+
super.onHeaders(headers);
37+
}
38+
};
39+
super.start(listener, headers);
40+
}
41+
42+
};
43+
44+
}
45+
46+
}

src/main/java/io/codenotary/immudb4j/ImmuState.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
*/
1616
package io.codenotary.immudb4j;
1717

18-
import java.security.PublicKey;
1918
import java.util.Base64;
2019

2120
/**
@@ -47,4 +46,5 @@ public String toString() {
4746
", signature(base64)=" + enc.encodeToString(signature) +
4847
" }";
4948
}
49+
5050
}

src/main/java/io/codenotary/immudb4j/ImmuStateHolder.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818

1919
public interface ImmuStateHolder {
2020

21-
ImmuState getState(String database);
21+
ImmuState getState(String serverUuid, String database);
2222

23-
void setState(ImmuState state);
23+
void setState(String serverUuid, ImmuState state);
2424

2525
}

src/main/java/io/codenotary/immudb4j/SerializableImmuStateHolder.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626

2727
public class SerializableImmuStateHolder implements ImmuStateHolder {
2828

29+
/**
30+
* Mapping "{serverUuid}_{databaseName}" to the appropriate state.
31+
*/
2932
private Map<String, ImmuState> statesMap = new HashMap<>();
3033

3134
public void readFrom(InputStream is) {
@@ -43,13 +46,13 @@ public void writeTo(OutputStream os) throws IOException {
4346
}
4447

4548
@Override
46-
public ImmuState getState(String database) {
47-
return this.statesMap.get(database);
49+
public ImmuState getState(String serverUuid, String database) {
50+
return this.statesMap.get(serverUuid + "_" + database);
4851
}
4952

5053
@Override
51-
public void setState(ImmuState state) {
52-
this.statesMap.put(state.database, state);
54+
public void setState(String serverUuid, ImmuState state) {
55+
this.statesMap.put(serverUuid + "_" + state.database, state);
5356
}
5457

5558
}

src/test/java/io/codenotary/immudb4j/FileImmuStateHolderTest.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public void t1() {
1818
File statesDir = null;
1919
try {
2020
String tempDir = System.getProperty("java.io.tmpdir");
21-
statesDir = new File(tempDir, "fileimmustateholdertest_states/");
21+
statesDir = new File(tempDir, "FileImmuStateHolderTest_states/");
2222
File currStateFile = new File(statesDir, "current_state");
2323

2424
// Write some fake "state_..." into "current_state" file.
@@ -31,6 +31,9 @@ public void t1() {
3131
} catch (IOException e) {
3232
// If that would be the case, it's not the test's fault.
3333
System.out.println(">>> Got IO ex (expected): " + e.getMessage());
34+
if (e.getCause() != null) {
35+
System.out.println(">>> Got IO ex (expected) cause: " + e.getCause().getMessage());
36+
}
3437
} catch (IllegalStateException ignored) {
3538
// This should actually happen with that "fake" state entry.
3639
}

0 commit comments

Comments
 (0)