Skip to content

Bump org.apache.zookeeper:zookeeper from 3.4.6 to 3.7.2 #12

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions doc/eight-byte-id-structure.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ The eight byte IDs generated by the `LocalUniqueIDGenerator` and
`SynchronizedUniqueIDGenerator` classes conform to the following structure:

```
TTTTTTTT TTTTTTTT TTTTTTTT TTTTTTTT TTTTTTTT TTSSSSSS ...MGGGG GGGGCCCC
TTTTTTTT TTTTTTTT TTTTTTTT TTTTTTTT TTTTTTTT TTSSSSSS GGGMGGGG GGGGCCCC
| | | || |
v | | |\ |
| v \ \ |
Date of ID creation, measured in milliseconds | \ \ |
ellapsed since 1970-01-01T00:00:00.000, | Reserved \ \ |
represented in reverse byte-order (in SPREAD | for future | | |
mode) to guarantee an even spread of IDs. | use. | | |
ellapsed since 1970-01-01T00:00:00.000, | Generator \ \ |
represented in reverse byte-order (in SPREAD | ID, see | | |
mode) to guarantee an even spread of IDs. | below. | | |
| | | |
v | | |
| | |
Expand All @@ -27,13 +27,13 @@ mode) to guarantee an even spread of IDs. | use. | | |
v |
|
Generator ID, manually assigned, or acquired |
through negotiation via a ZooKeeper-quorum. |
|
through negotiation via Etcd. Limited to 2048 |
per Cluster ID. |
v

Cluster ID. Always manually assigned
or statically configured. Limited to
16 (actieve) clusters.
16 (active) clusters.
```

This approach offers a few useful features:
Expand Down
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

<groupId>org.lable.oss.uniqueid</groupId>
<artifactId>uniqueid</artifactId>
<version>3.2-SNAPSHOT</version>
<version>3.3-SNAPSHOT</version>
<packaging>pom</packaging>

<name>UniqueID</name>
Expand All @@ -45,12 +45,12 @@
<java.language.level>1.8</java.language.level>

<dynamicconfig.version>2.9-beta4</dynamicconfig.version>
<zookeeper.version>3.4.6</zookeeper.version>
<zookeeper.version>3.7.2</zookeeper.version>
<jetcd-version>0.4.1</jetcd-version>
<slf4j.version>1.7.21</slf4j.version>

<!-- For testing only. -->
<log4j.version>2.7</log4j.version>
<log4j.version>2.17.1</log4j.version>
<hamcrest.optional>1.0</hamcrest.optional>
</properties>

Expand Down
2 changes: 1 addition & 1 deletion uniqueid-core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<parent>
<artifactId>uniqueid</artifactId>
<groupId>org.lable.oss.uniqueid</groupId>
<version>3.2-SNAPSHOT</version>
<version>3.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
*/
package org.lable.oss.uniqueid;

import javax.annotation.PreDestroy;
import java.io.IOException;
import java.util.ArrayDeque;
import java.util.Deque;
Expand Down Expand Up @@ -63,7 +62,6 @@ public static IDGenerator decorate(IDGenerator generator, int batchSize) {
return new AutoRefillStack(generator, batchSize);
}

@PreDestroy
@Override
public void close() throws IOException {
generator.close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public class LocalUniqueIDGeneratorFactory {
* Return the UniqueIDGenerator instance for this specific generator-ID, cluster-ID combination. If one was
* already created, that is returned.
*
* @param generatorId Generator ID to use (0 ≤ n ≤ 255).
* @param generatorId Generator ID to use (0 ≤ n ≤ 2047).
* @param clusterId Cluster ID to use (0 ≤ n ≤ 15).
* @param clock Clock implementation.
* @param mode Generator mode.
Expand All @@ -58,7 +58,7 @@ public synchronized static IDGenerator generatorFor(int generatorId, int cluster
* Return the UniqueIDGenerator instance for this specific generator-ID, cluster-ID combination. If one was
* already created, that is returned.
*
* @param generatorId Generator ID to use (0 ≤ n ≤ 255).
* @param generatorId Generator ID to use (0 ≤ n ≤ 2047).
* @param clusterId Cluster ID to use (0 ≤ n ≤ 15).
* @param mode Generator mode.
* @return A thread-safe UniqueIDGenerator instance.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public class Blueprint {
/**
* Upper bound (inclusive) of the generator-ID.
*/
public final static int MAX_GENERATOR_ID = 255;
public final static int MAX_GENERATOR_ID = 2047;

/**
* Upper bound (inclusive) of the cluster-ID.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
* <p>
* The eight byte ID is composed as follows:
*
* <pre>TTTTTTTT TTTTTTTT TTTTTTTT TTTTTTTT TTTTTTTT TTSSSSSS ...MGGGG GGGGCCCC</pre>
* <pre>TTTTTTTT TTTTTTTT TTTTTTTT TTTTTTTT TTTTTTTT TTSSSSSS GGGMGGGG GGGGCCCC</pre>
*
* <ul>
* <li><code>T</code>: Timestamp (in milliseconds, bit order depends on mode)
Expand Down Expand Up @@ -67,8 +67,9 @@ public static byte[] build(Blueprint blueprint) {
tsBytes[5] = (byte) or;

// Last two bytes. The mode flag, generator ID, and cluster ID.
// [6] ...MGGGG [7] GGGGCCCC
int flagGeneratorCluster = blueprint.getGeneratorId() << 4;
// [6] GGGMGGGG [7] GGGGCCCC
int flagGeneratorCluster = (blueprint.getGeneratorId() << 5) & 0xE000;
flagGeneratorCluster += (blueprint.getGeneratorId() & 0x00FF) << 4;
flagGeneratorCluster += blueprint.getClusterId();
flagGeneratorCluster += blueprint.getMode().getModeMask() << 12;

Expand Down Expand Up @@ -160,8 +161,8 @@ private static int parseSequenceIdNoChecks(byte[] id) {
}

private static int parseGeneratorIdNoChecks(byte[] id) {
// [6] ....GGGG [7] GGGG....
return (id[7] >> 4 & 0x0F) | (id[6] << 4 & 0xF0);
// [6] GGG.GGGG [7] GGGG....
return (id[7] >> 4 & 0x0F) | (id[6] << 3 & 0x0700) | (id[6] << 4 & 0xF0);
}

private static int parseClusterIdNoChecks(byte[] id) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class LocalUniqueIDGeneratorFactoryTest {

@Test(expected = IllegalArgumentException.class)
public void outOfBoundsGeneratorIDTest() {
LocalUniqueIDGeneratorFactory.generatorFor(256, 0, Mode.SPREAD);
LocalUniqueIDGeneratorFactory.generatorFor(2048, 0, Mode.SPREAD);
}

@Test(expected = IllegalArgumentException.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@

import org.apache.commons.codec.binary.Hex;
import org.junit.Test;
import org.lable.oss.uniqueid.ByteArray;

import java.util.HashSet;
import java.util.Set;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
Expand All @@ -41,8 +45,7 @@ public void buildMostlyOnes() {
Blueprint.MAX_CLUSTER_ID,
Mode.SPREAD
));
// The "0f" for the 7th byte is due to the reserved bits that are always zero for the SPREAD mode.
final String expected = "ffffffffffff0fff";
final String expected = "ffffffffffffefff";

// Baseline check, if all ID parts are all ones so is the result (except for the reserved bytes).
assertThat(Hex.encodeHexString(result), is(expected));
Expand Down Expand Up @@ -234,4 +237,31 @@ public void parseIllegalArgument() {
public void parseIllegalArgumentNull() {
IDBuilder.parse(null);
}

@Test
public void fullGeneratorSpace() {
// Verify that bitwise operations in IDBuilder work.
Set<ByteArray> results = new HashSet<>();
for (int generatorId = 0; generatorId <= Blueprint.MAX_GENERATOR_ID; generatorId++) {
byte[] result = IDBuilder.build(new Blueprint(
Blueprint.MAX_TIMESTAMP,
Blueprint.MAX_SEQUENCE_COUNTER,
generatorId,
Blueprint.MAX_CLUSTER_ID,
Mode.SPREAD
));
results.add(new ByteArray(result));

result = IDBuilder.build(new Blueprint(
Blueprint.MAX_TIMESTAMP,
Blueprint.MAX_SEQUENCE_COUNTER,
generatorId,
Blueprint.MAX_CLUSTER_ID,
Mode.TIME_SEQUENTIAL
));
results.add(new ByteArray(result));
}

assertThat(results.size(), is(2 *(Blueprint.MAX_GENERATOR_ID + 1)));
}
}
2 changes: 1 addition & 1 deletion uniqueid-etcd/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
<parent>
<artifactId>uniqueid</artifactId>
<groupId>org.lable.oss.uniqueid</groupId>
<version>3.2-SNAPSHOT</version>
<version>3.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,22 @@ public static Optional<Integer> getInt(Client etcd, String key) throws Execution
}
}

public static Optional<String> get(Client etcd, String key) throws ExecutionException, InterruptedException {
GetResponse getResponse = etcd.getKVClient().get(asByteSequence(key)).get();

if (getResponse.getCount() == 0) return Optional.empty();

return Optional.of(getResponse.getKvs().get(0).getValue().toString(StandardCharsets.UTF_8));
}

public static void put(Client etcd, String key, int value) throws ExecutionException, InterruptedException {
etcd.getKVClient().put(asByteSequence(key), asByteSequence(value)).get();
}

public static void put(Client etcd, String key) throws ExecutionException, InterruptedException {
etcd.getKVClient().put(asByteSequence(key),ByteSequence.EMPTY).get();
}

public static void delete(Client etcd, String key) throws ExecutionException, InterruptedException {
etcd.getKVClient().delete(asByteSequence(key)).get();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* Copyright (C) 2014 Lable ([email protected])
*
* 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 org.lable.oss.uniqueid.etcd;

import io.etcd.jetcd.ByteSequence;
import io.etcd.jetcd.Client;
import org.lable.oss.uniqueid.GeneratorException;
import org.lable.oss.uniqueid.GeneratorIdentityHolder;
import org.lable.oss.uniqueid.bytes.Blueprint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.Duration;

/**
* Holder for a claimed cluster-id and generator-id that once claimed remains claimed without an active connection to
* an Etcd cluster. The claim is relinquished upon calling {@link #close()} (where a new connection to Etcd will be
* set up briefly).
*/
public class RegistryBasedGeneratorIdentity implements GeneratorIdentityHolder {
private static final Logger logger = LoggerFactory.getLogger(RegistryBasedGeneratorIdentity.class);

private final String endpoints;
private final String namespace;
private final Duration acquisitionTimeout;
private final boolean waitWhenNoResourcesAvailable;
private final RegistryBasedResourceClaim resourceClaim;

public RegistryBasedGeneratorIdentity(String endpoints,
String namespace,
String registryEntry,
Duration acquisitionTimeout,
boolean waitWhenNoResourcesAvailable) {
this.endpoints = endpoints;
this.namespace = namespace;
this.acquisitionTimeout = acquisitionTimeout;
this.waitWhenNoResourcesAvailable = waitWhenNoResourcesAvailable;

try {
resourceClaim = acquireResourceClaim(registryEntry, 0);
} catch (GeneratorException e) {
throw new RuntimeException(e);
}
}

public static RegistryBasedGeneratorIdentity basedOn(String endpoints, String namespace, String registryEntry)
throws IOException {
return new RegistryBasedGeneratorIdentity(
endpoints, namespace, registryEntry, Duration.ofMinutes(5), true
);
}

public static RegistryBasedGeneratorIdentity basedOn(String endpoints,
String namespace,
String registryEntry,
Duration acquisitionTimeout,
boolean waitWhenNoResourcesAvailable)
throws IOException {
return new RegistryBasedGeneratorIdentity(
endpoints, namespace, registryEntry, acquisitionTimeout, waitWhenNoResourcesAvailable
);
}

@Override
public int getClusterId() throws GeneratorException {
return resourceClaim.getClusterId();
}

@Override
public int getGeneratorId() throws GeneratorException {
return resourceClaim.getGeneratorId();
}

public String getRegistryEntry() {
return resourceClaim.getRegistryEntry();
}

private RegistryBasedResourceClaim acquireResourceClaim(String registryEntry, int retries)
throws GeneratorException {
try {
return RegistryBasedResourceClaim.claim(
this::getEtcdConnection,
Blueprint.MAX_GENERATOR_ID + 1,
registryEntry,
acquisitionTimeout,
waitWhenNoResourcesAvailable
);
} catch (IOException e) {
if (retries < 3) {
logger.warn(
"Connection to Etcd failed, retrying claim acquisition, attempt " + (retries + 1) + ".",
e
);
return acquireResourceClaim(registryEntry, retries + 1);
} else {
logger.error("Failed to acquire resource claim after attempt " + (retries + 1) + ".", e);
throw new GeneratorException(e);
}
}
}

Client getEtcdConnection() {
return Client.builder()
.endpoints(endpoints.split(","))
.namespace(ByteSequence.from(namespace, StandardCharsets.UTF_8))
.build();
}

@Override
public void close() throws IOException {
if (resourceClaim != null) {
resourceClaim.close();
}
}
}
Loading