diff --git a/.circleci/config.yml b/.circleci/config.yml index 6f06b29..2f502ae 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -2,7 +2,7 @@ version: 2.1 jobs: build: machine: - image: ubuntu-1604:202104-01 + image: ubuntu-2004:202104-01 working_directory: ~/cassandra-everywhere-strategy @@ -22,6 +22,7 @@ jobs: - ~/.m2 key: m2-{{ checksum "pom.xml" }} + - run: echo "2" | sudo update-alternatives --config java - run: ./conf/setup.sh && mvn clean install && (cd test && ./run-tests.sh) - persist_to_workspace: @@ -31,6 +32,7 @@ jobs: - "cassandra-3.0/target/everywhere-strategy-cassandra*.jar" - "cassandra-3.11/target/everywhere-strategy-cassandra*.jar" - "cassandra-4.0/target/everywhere-strategy-cassandra*.jar" + - "cassandra-4.1/target/everywhere-strategy-cassandra*.jar" build-2-2: docker: @@ -160,6 +162,38 @@ jobs: - "everywhere-strategy-cassandra-4.0*.deb" - "everywhere-strategy-cassandra-4.0*.rpm" + build-4-1: + docker: + - image: circleci/openjdk:8-jdk-stretch + + working_directory: ~/cassandra-everywhere-strategy + + environment: + MAVEN_OPTS: -Xmx3200m + + steps: + + - checkout + + - restore_cache: + keys: + - m2-{{ checksum "pom.xml" }} + - m2- + + - run: mvn clean install -DoutputDirectory=/tmp/artifacts + + - save_cache: + paths: + - ~/.m2 + key: m2-{{ checksum "pom.xml" }} + + - persist_to_workspace: + root: /tmp/artifacts + paths: + - "everywhere-strategy-cassandra-4.1*.jar" + - "everywhere-strategy-cassandra-4.1*.deb" + - "everywhere-strategy-cassandra-4.1*.rpm" + publish-github-release-2-2: docker: - image: circleci/golang @@ -213,6 +247,19 @@ jobs: go get github.com/tcnksm/ghr ghr -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} -delete ${CIRCLE_TAG} ./artifacts/ + publish-github-release-4-1: + docker: + - image: circleci/golang + steps: + - attach_workspace: + at: ./artifacts + - run: + name: "Publish 4.1 Release on GitHub" + command: | + set -xue + go get github.com/tcnksm/ghr + ghr -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} -delete ${CIRCLE_TAG} ./artifacts/ + workflows: version: 2 main: @@ -245,6 +292,12 @@ workflows: ignore: /.*/ tags: only: /^v4.0.\d+-\d+\.\d+\.\d+$/ + - build-4-1: + filters: + branches: + ignore: /.*/ + tags: + only: /^v4.1.\d+-\d+\.\d+\.\d+$/ - publish-github-release-2-2: requires: - build-2-2 @@ -277,3 +330,11 @@ workflows: ignore: /.*/ tags: only: /^v4.0.\d+-\d+\.\d+\.\d+$/ + - publish-github-release-4-1: + requires: + - build-4-1 + filters: + branches: + ignore: /.*/ + tags: + only: /^v4.1.\d+-\d+\.\d+\.\d+$/ \ No newline at end of file diff --git a/README.md b/README.md index 2e0bebb..21f4b2e 100644 --- a/README.md +++ b/README.md @@ -149,11 +149,11 @@ So we resort to reflection to fix this. Yuck! But, it works… | Cassandra Version | Status | | --- | --- | -| 3.11.x | Supported | | 4.x | Supported | -| 3.0.x | _Supported_ | -| 2.2.x | _Supported_ | -| 2.1.x | _Supported_ | +| 3.11.x | Supported | +| 3.0.x | Supported | +| 2.2.x | Supported | +| 2.1.x | Supported | | 2.0.x | Supported | For 2.1.x and 2.0.x versions, you can use version 2.2.x, it is compatible. @@ -164,4 +164,4 @@ This project is licensed under the Apache License, version 2.0. See [LICENSE](LI ## Instaclustr Support -Please see our [Open Source Project Status](https://www.instaclustr.com/support/documentation/announcements/instaclustr-open-source-project-status/) page for details on Instaclustr's support status of this project. \ No newline at end of file +Please see our [Open Source Project Status](https://www.instaclustr.com/support/documentation/announcements/instaclustr-open-source-project-status/) page for details on Instaclustr's support status of this project. diff --git a/cassandra-2.2/pom.xml b/cassandra-2.2/pom.xml index 12a0618..75ad535 100644 --- a/cassandra-2.2/pom.xml +++ b/cassandra-2.2/pom.xml @@ -20,7 +20,7 @@ org.apache.cassandra cassandra-all - 2.2.18 + 2.2.19 provided diff --git a/cassandra-3.0/pom.xml b/cassandra-3.0/pom.xml index b63a885..397f287 100644 --- a/cassandra-3.0/pom.xml +++ b/cassandra-3.0/pom.xml @@ -20,7 +20,7 @@ org.apache.cassandra cassandra-all - 3.0.24 + 3.0.26 provided diff --git a/cassandra-3.11/pom.xml b/cassandra-3.11/pom.xml index a33c7ed..e67a365 100644 --- a/cassandra-3.11/pom.xml +++ b/cassandra-3.11/pom.xml @@ -20,7 +20,7 @@ org.apache.cassandra cassandra-all - 3.11.8 + 3.11.14 provided diff --git a/cassandra-4.1/pom.xml b/cassandra-4.1/pom.xml new file mode 100644 index 0000000..35f5eaf --- /dev/null +++ b/cassandra-4.1/pom.xml @@ -0,0 +1,69 @@ + + + + 4.0.0 + + + com.instaclustr + everywhere-strategy-parent + 1.0.0 + ../pom.xml + + + everywhere-strategy-cassandra-4.1 + 1.0.0 + + everywhere-strategy-cassandra-4.1 + An EverywhereStrategy implementation for Apache Cassandra 4.1 + + + + org.apache.cassandra + cassandra-all + 4.1.0 + provided + + + + + + + org.apache.maven.plugins + maven-release-plugin + + + v4.1-@{project.version} + + + + + jdeb + org.vafer + + + + de.dentrassi.maven + rpm + + + package + + rpm + + + + + cassandra + 4.1 + + + + + + + + + + diff --git a/cassandra-4.1/src/deb/control/control b/cassandra-4.1/src/deb/control/control new file mode 100644 index 0000000..b5cfd44 --- /dev/null +++ b/cassandra-4.1/src/deb/control/control @@ -0,0 +1,7 @@ +Package: [[name]] +Version: [[version]] +Section: misc +Priority: optional +Architecture: all +Depends: cassandra (>= 4.1) +Maintainer: [[maintainer]] diff --git a/cassandra-4.1/src/main/java/org/apache/cassandra/locator/EverywhereStrategy.java b/cassandra-4.1/src/main/java/org/apache/cassandra/locator/EverywhereStrategy.java new file mode 100644 index 0000000..7abb0ac --- /dev/null +++ b/cassandra-4.1/src/main/java/org/apache/cassandra/locator/EverywhereStrategy.java @@ -0,0 +1,87 @@ +package org.apache.cassandra.locator; + +import java.lang.reflect.Field; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import com.google.common.collect.ImmutableMap; +import org.apache.cassandra.dht.Token; +import org.apache.cassandra.exceptions.ConfigurationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/* + The strategy should be DC-aware, but DC-awareness is hardcoded to NTS throughout Cassandra. + (see for example org.apache.cassandra.db.ConsistencyLevel) + Hence why this implementation subclasses NTS. + */ +public class EverywhereStrategy extends NetworkTopologyStrategy { + + private static final Logger logger = LoggerFactory.getLogger(EverywhereStrategy.class); + + protected final Map datacenters; + + public EverywhereStrategy(final String keyspaceName, + final TokenMetadata tokenMetadata, + final IEndpointSnitch snitch, + final Map configOptions) throws NoSuchFieldException, IllegalAccessException { + super(keyspaceName, tokenMetadata, snitch, null); + + if (configOptions != null && configOptions.size() != 0) { + throw new ConfigurationException("EverywhereStrategy doesn't accept any options."); + } + + // yuck. but then again, why is this field private? + // also, sucks that its final *and* and an unmodifiable collection. + // lets fix that... + final Field field = NetworkTopologyStrategy.class.getDeclaredField("datacenters"); + field.setAccessible(true); + + this.datacenters = new HashMap<>(); + + field.set(this, this.datacenters); + } + + // this gets called whenever the ring topology changes. + // redetermine the RF for each DC. + @Override + public EndpointsForRange calculateNaturalReplicas(Token searchToken, TokenMetadata tokenMetadata) { + final Set endpoints = tokenMetadata.getAllEndpoints(); + + final Map previousDataCenters = ImmutableMap.copyOf(this.datacenters); + + this.datacenters.clear(); + + for (final InetAddressAndPort endpoint : endpoints) { + if (!tokenMetadata.isMember(endpoint)) + continue; + + final String datacenter = this.snitch.getDatacenter(endpoint); + this.datacenters.merge(datacenter, ReplicationFactor.fromString("1"), (rf1, rf2) -> ReplicationFactor.fullOnly(rf1.fullReplicas + rf2.fullReplicas)); + } + + if (!previousDataCenters.equals(this.datacenters)) { + logger.info("Data center replication factors for keyspace '{}' = {}", this.keyspaceName, this.datacenters); + } + + return super.calculateNaturalReplicas(searchToken, tokenMetadata); + } + + @Override + public Collection recognizedOptions() { + return Collections.emptyList(); + } + + @Override + public void validateOptions() throws ConfigurationException { + super.validateOptions(); + } + + @Override + protected void validateExpectedOptions() throws ConfigurationException { + // do nothing, we are not excepting any options and method in super would throw as we have not provided any + } +} diff --git a/cassandra-4/pom.xml b/cassandra-4/pom.xml index 96f97f8..122c53f 100644 --- a/cassandra-4/pom.xml +++ b/cassandra-4/pom.xml @@ -22,7 +22,7 @@ org.apache.cassandra cassandra-all - 4.0.0 + 4.0.7 provided diff --git a/conf/setup.sh b/conf/setup.sh index b8db39a..b0775dd 100755 --- a/conf/setup.sh +++ b/conf/setup.sh @@ -3,4 +3,4 @@ sudo apt-get update sudo apt-get --allow-downgrades --allow-remove-essential --allow-change-held-packages install libev4 libev-dev -pip3.9 install ccm && wget https://github.com/zegelin/ccm-extensions/archive/refs/heads/master.zip && unzip master.zip && cd ccm-extensions-master && python3.9 setup.py install \ No newline at end of file +pip3.9 install ccm && wget https://github.com/smiklosovic/ccm-extensions/archive/refs/heads/master.zip && unzip master.zip && cd ccm-extensions-master && python3.9 setup.py install diff --git a/pom.xml b/pom.xml index 78b8f1c..3e2ee37 100644 --- a/pom.xml +++ b/pom.xml @@ -13,6 +13,7 @@ cassandra-3.0 cassandra-3.11 cassandra-4 + cassandra-4.1 everywhere-strategy-parent diff --git a/test/compare_dumps.py b/test/compare_dumps.py index 8ec4449..0140e20 100644 --- a/test/compare_dumps.py +++ b/test/compare_dumps.py @@ -87,8 +87,13 @@ def flush_dump_compare(nodes: Iterable[Node], dump_dir: Path): dump_dir.mkdir(parents=True,exist_ok=True) path = (dump_dir / f'{node.ip_addr}-{i}.json') logger.info(f'Writing {node.ip_addr} dump to {path}') - with path.open('wb') as f: - f.write(result.stdout) + print(result.stdout) + try: + with path.open('w') as f: + f.write(result.stdout) + except: + with path.open('wb') as f: + f.write(result.stdout) logger.info('Comparing dumps') compare_sstable_dumps(dump_dir) diff --git a/test/run-tests.sh b/test/run-tests.sh index e278de5..290215c 100755 --- a/test/run-tests.sh +++ b/test/run-tests.sh @@ -2,6 +2,7 @@ # ssltabledump not available on 2.2.x #python3 ccm-test.py -j ../cassandra-2.2/target/everywhere-strategy-cassandra-2.2-1.0.0.jar 2.2.18 -python3 ccm-test.py -j ../cassandra-3.0/target/everywhere-strategy-cassandra-3.0-1.0.0.jar 3.0.24 -python3 ccm-test.py -j ../cassandra-3.11/target/everywhere-strategy-cassandra-3.11-1.0.0.jar 3.11.10 -python3 ccm-test.py -j ../cassandra-4/target/everywhere-strategy-cassandra-4.0-1.0.0.jar 4.0.0 \ No newline at end of file +python3 ccm-test.py -j ../cassandra-3.0/target/everywhere-strategy-cassandra-3.0-1.0.0.jar 3.0.26 +python3 ccm-test.py -j ../cassandra-3.11/target/everywhere-strategy-cassandra-3.11-1.0.0.jar 3.11.14 +python3 ccm-test.py -j ../cassandra-4/target/everywhere-strategy-cassandra-4.0-1.0.0.jar 4.0.7 +python3 ccm-test.py -j ../cassandra-4.1/target/everywhere-strategy-cassandra-4.1-1.0.0.jar 4.1.0 \ No newline at end of file