Rya-82 Rya Console updated to incorporate Rya Details for an instance and provide administrative commands.
Project: http://git-wip-us.apache.org/repos/asf/incubator-rya/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-rya/commit/fcc98bd9 Tree: http://git-wip-us.apache.org/repos/asf/incubator-rya/tree/fcc98bd9 Diff: http://git-wip-us.apache.org/repos/asf/incubator-rya/diff/fcc98bd9 Branch: refs/heads/master Commit: fcc98bd924b3dab0b4f9296058aed541d585eb9a Parents: 57df230 Author: Kevin Chilton <[email protected]> Authored: Mon Jul 18 15:10:05 2016 -0400 Committer: Aaron Mihalik <[email protected]> Committed: Tue Aug 23 10:41:39 2016 -0400 ---------------------------------------------------------------------- common/rya.api/pom.xml | 5 + .../main/java/mvm/rya/api/client/CreatePCJ.java | 40 ++ .../main/java/mvm/rya/api/client/DeletePCJ.java | 38 ++ .../mvm/rya/api/client/GetInstanceDetails.java | 44 ++ .../main/java/mvm/rya/api/client/Install.java | 268 ++++++++++++ .../client/InstanceDoesNotExistException.java | 38 ++ .../java/mvm/rya/api/client/InstanceExists.java | 37 ++ .../java/mvm/rya/api/client/ListInstances.java | 38 ++ .../main/java/mvm/rya/api/client/RyaClient.java | 101 +++++ .../mvm/rya/api/client/RyaClientException.java | 37 ++ .../java/mvm/rya/api/instance/RyaDetails.java | 141 ++++++- .../api/instance/RyaDetailsToConfiguration.java | 4 +- .../mvm/rya/api/instance/RyaDetailsUpdater.java | 124 ++++++ .../mvm/rya/api/instance/RyaDetailsTest.java | 21 +- .../instance/RyaDetailsToConfigurationTest.java | 7 +- .../rya/api/instance/RyaDetailsUpdaterTest.java | 141 +++++++ dao/accumulo.rya/pom.xml | 14 + .../java/mvm/rya/accumulo/AccumuloRyaDAO.java | 26 +- .../AccumuloRyaInstanceDetailsRepository.java | 4 +- .../java/mvm/rya/accumulo/AccumuloITBase.java | 107 +++++ .../mvm/rya/accumulo/AccumuloRyaITBase.java | 109 +++++ .../accumulo/MiniAccumuloClusterInstance.java | 119 ++++++ .../AccumuloRyaDetailsRepositoryIT.java | 101 ++--- .../mongodb/instance/MongoDetailsAdapter.java | 112 +++-- .../instance/MongoDetailsAdapterTest.java | 215 ++++++---- .../instance/MongoRyaDetailsRepositoryIT.java | 52 +-- extras/indexing/pom.xml | 11 + .../api/client/accumulo/AccumuloCommand.java | 64 +++ .../accumulo/AccumuloConnectionDetails.java | 83 ++++ .../api/client/accumulo/AccumuloCreatePCJ.java | 185 +++++++++ .../api/client/accumulo/AccumuloDeletePCJ.java | 130 ++++++ .../accumulo/AccumuloGetInstanceDetails.java | 77 ++++ .../api/client/accumulo/AccumuloInstall.java | 217 ++++++++++ .../client/accumulo/AccumuloInstanceExists.java | 71 ++++ .../client/accumulo/AccumuloListInstances.java | 141 +++++++ .../accumulo/AccumuloRyaClientFactory.java | 59 +++ .../api/client/accumulo/FluoClientFactory.java | 72 ++++ .../external/PrecomputedJoinIndexer.java | 18 +- .../external/accumulo/AccumuloPcjStorage.java | 96 ----- .../accumulo/AccumuloPcjStorageConfig.java | 1 + .../accumulo/AccumuloPcjStorageSupplier.java | 1 + .../external/tupleSet/AccumuloIndexSet.java | 146 ++++--- .../rya/indexing/pcj/matching/PCJOptimizer.java | 136 ++++--- .../rya/sail/config/RyaAccumuloSailConfig.java | 65 +-- .../rya/sail/config/RyaAccumuloSailFactory.java | 52 +-- .../mvm/rya/sail/config/RyaSailFactory.java | 22 +- .../client/accumulo/AccumuloCreatePCJIT.java | 161 ++++++++ .../client/accumulo/AccumuloDeletePCJIT.java | 141 +++++++ .../accumulo/AccumuloGetInstanceDetailsIT.java | 142 +++++++ .../api/client/accumulo/AccumuloInstallIT.java | 85 ++++ .../accumulo/AccumuloInstanceExistsIT.java | 100 +++++ .../accumulo/AccumuloListInstancesIT.java | 65 +++ .../mvm/rya/api/client/accumulo/FluoITBase.java | 313 ++++++++++++++ .../AccumuloConstantPcjIntegrationTest.java | 2 +- .../external/AccumuloPcjIntegrationTest.java | 28 +- .../indexing/external/PCJOptionalTestIT.java | 2 +- .../external/PcjIntegrationTestingUtil.java | 7 +- .../PrecompJoinOptimizerIntegrationTest.java | 2 +- .../PrecomputedJoinStorageSupplierTest.java | 2 +- .../AccumuloIndexSetColumnVisibilityTest.java | 406 ++++++++++--------- .../external/tupleSet/AccumuloIndexSetTest.java | 3 +- extras/indexingExample/pom.xml | 17 + .../src/main/java/EntityDirectExample.java | 48 ++- .../src/main/java/MongoRyaDirectExample.java | 1 - .../src/main/java/RyaClientExample.java | 286 +++++++++++++ .../src/main/java/RyaDirectExample.java | 30 +- extras/rya.console/pom.xml | 174 ++++++-- .../java/mvm/rya/console/RyaBannerProvider.java | 69 ---- .../mvm/rya/console/RyaConsoleCommands.java | 230 ----------- .../rya/console/RyaHistoryFileNameProvider.java | 47 --- .../java/mvm/rya/console/RyaPromptProvider.java | 47 --- .../java/mvm/rya/shell/RyaAdminCommands.java | 254 ++++++++++++ .../java/mvm/rya/shell/RyaBannerProvider.java | 97 +++++ .../mvm/rya/shell/RyaConnectionCommands.java | 167 ++++++++ .../java/mvm/rya/shell/RyaPromptProvider.java | 62 +++ .../java/mvm/rya/shell/SharedShellState.java | 338 +++++++++++++++ .../mvm/rya/shell/util/ConnectorFactory.java | 66 +++ .../java/mvm/rya/shell/util/InstallPrompt.java | 131 ++++++ .../rya/shell/util/InstanceNamesFormatter.java | 77 ++++ .../java/mvm/rya/shell/util/JLinePrompt.java | 200 +++++++++ .../java/mvm/rya/shell/util/PasswordPrompt.java | 71 ++++ .../mvm/rya/shell/util/RyaDetailsFormatter.java | 117 ++++++ .../java/mvm/rya/shell/util/SparqlPrompt.java | 55 +++ .../rya.console/src/main/resources/LICENSE.txt | 16 + .../META-INF/spring/spring-shell-plugin.xml | 46 ++- .../mvm/rya/shell/RyaAdminCommandsTest.java | 261 ++++++++++++ .../mvm/rya/shell/RyaConnectionCommandsIT.java | 269 ++++++++++++ .../mvm/rya/shell/RyaPromptProviderTest.java | 80 ++++ .../test/java/mvm/rya/shell/RyaShellITBase.java | 103 +++++ .../mvm/rya/shell/SharedShellStateTest.java | 167 ++++++++ .../mvm/rya/shell/util/ConnectorFactoryIT.java | 57 +++ .../shell/util/InstanceNamesFormatterTest.java | 81 ++++ .../rya/shell/util/RyaDetailsFormatterTest.java | 106 +++++ .../src/test/resources/RyaShellTest-context.xml | 52 +++ extras/rya.indexing.pcj/pom.xml | 10 + .../rya/indexing/pcj/storage/PCJIdFactory.java | 34 ++ .../pcj/storage/PrecomputedJoinStorage.java | 18 +- .../storage/accumulo/AccumuloPcjStorage.java | 202 +++++++++ .../storage/accumulo/PcjTableNameFactory.java | 31 +- .../pcj/storage/accumulo/PcjTables.java | 211 +++++----- .../storage/accumulo/PcjVarOrderFactory.java | 14 + .../accumulo/ScannerBindingSetIterator.java | 73 ++++ .../storage/accumulo/ShiftVarOrderFactory.java | 17 + .../accumulo/PcjTableNameFactoryTest.java | 54 +++ .../accumulo/PcjTablesIntegrationTest.java | 250 ++++++------ .../accumulo/ShiftVarOrderFactoryTest.java | 73 ++++ .../accumulo/accumulo/AccumuloPcjStorageIT.java | 272 +++++++++++++ .../rya/indexing/pcj/fluo/api/CreatePcj.java | 96 ++--- .../rya/indexing/pcj/fluo/api/DeletePcj.java | 287 +++++++++++++ .../indexing/pcj/fluo/api/GetPcjMetadata.java | 43 +- .../indexing/pcj/fluo/api/InsertTriples.java | 2 + extras/rya.pcj.fluo/pcj.fluo.app/pom.xml | 16 + .../rya/indexing/pcj/fluo/app/NodeType.java | 52 ++- .../app/export/rya/RyaExportParameters.java | 16 + .../fluo/app/export/rya/RyaResultExporter.java | 26 +- .../export/rya/RyaResultExporterFactory.java | 12 +- .../pcj/fluo/app/query/FluoQueryColumns.java | 158 ++++++-- .../fluo/app/query/SparqlFluoQueryBuilder.java | 7 +- extras/rya.pcj.fluo/pcj.fluo.client/pom.xml | 4 + .../fluo/client/command/ListQueriesCommand.java | 7 +- .../fluo/client/command/NewQueryCommand.java | 12 +- extras/rya.pcj.fluo/pcj.fluo.demo/pom.xml | 4 + .../rya/indexing/pcj/fluo/demo/DemoDriver.java | 38 +- .../pcj/fluo/demo/FluoAndHistoricPcjsDemo.java | 105 ++--- .../apache/rya/indexing/pcj/fluo/ITBase.java | 63 +-- .../pcj/fluo/api/CountStatementsIT.java | 13 +- .../indexing/pcj/fluo/api/GetPcjMetadataIT.java | 39 +- .../indexing/pcj/fluo/api/GetQueryReportIT.java | 14 +- .../indexing/pcj/fluo/api/ListQueryIdsIT.java | 3 - .../fluo/app/query/FluoQueryMetadataDAOIT.java | 3 +- .../pcj/fluo/integration/CreateDeleteIT.java | 124 ++++++ .../indexing/pcj/fluo/integration/InputIT.java | 35 +- .../indexing/pcj/fluo/integration/QueryIT.java | 35 +- .../pcj/fluo/integration/RyaExportIT.java | 89 +--- .../RyaInputIncrementalUpdateIT.java | 40 +- .../pcj/fluo/visibility/PcjVisibilityIT.java | 299 ++++---------- .../rya/rdftriplestore/RdfCloudTripleStore.java | 32 +- 137 files changed, 9650 insertions(+), 2154 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/common/rya.api/pom.xml ---------------------------------------------------------------------- diff --git a/common/rya.api/pom.xml b/common/rya.api/pom.xml index 7c90521..302d335 100644 --- a/common/rya.api/pom.xml +++ b/common/rya.api/pom.xml @@ -71,6 +71,11 @@ under the License. <artifactId>junit</artifactId> <scope>test</scope> </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-all</artifactId> + <scope>test</scope> + </dependency> </dependencies> </project> http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/common/rya.api/src/main/java/mvm/rya/api/client/CreatePCJ.java ---------------------------------------------------------------------- diff --git a/common/rya.api/src/main/java/mvm/rya/api/client/CreatePCJ.java b/common/rya.api/src/main/java/mvm/rya/api/client/CreatePCJ.java new file mode 100644 index 0000000..ae22ffe --- /dev/null +++ b/common/rya.api/src/main/java/mvm/rya/api/client/CreatePCJ.java @@ -0,0 +1,40 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 mvm.rya.api.client; + +import javax.annotation.ParametersAreNonnullByDefault; + +/** + * Create a new PCJ within the target instance of Rya. + */ +@ParametersAreNonnullByDefault +public interface CreatePCJ { + + /** + * Designate a new PCJ that will be maintained by the target instance of Rya. + * + * @param instanceName - Indicates which Rya instance will create and maintain + * the PCJ. (not null) + * @param sparql - The SPARQL query that will be maintained. (not null) + * @return The ID that was assigned to this newly created PCJ. + * @throws InstanceDoesNotExistException No instance of Rya exists for the provided name. + * @throws RyaClientException Something caused the command to fail. + */ + public String createPCJ(final String instanceName, String sparql) throws InstanceDoesNotExistException, RyaClientException; +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/common/rya.api/src/main/java/mvm/rya/api/client/DeletePCJ.java ---------------------------------------------------------------------- diff --git a/common/rya.api/src/main/java/mvm/rya/api/client/DeletePCJ.java b/common/rya.api/src/main/java/mvm/rya/api/client/DeletePCJ.java new file mode 100644 index 0000000..92b6b71 --- /dev/null +++ b/common/rya.api/src/main/java/mvm/rya/api/client/DeletePCJ.java @@ -0,0 +1,38 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 mvm.rya.api.client; + +import javax.annotation.ParametersAreNonnullByDefault; + +/** + * Deletes a PCJ from an instance of Rya. + */ +@ParametersAreNonnullByDefault +public interface DeletePCJ { + + /** + * Deletes a PCJ from an instance of Rya. + * + * @param instanceName - Indicates which Rya instance is maintaining the PCJ. (not null) + * @param pcjId - The ID of the PCJ that will be deleted. (not null) + * @throws InstanceDoesNotExistException No instance of Rya exists for the provided name. + * @throws RyaClientException Something caused the command to fail. + */ + public void deletePCJ(String instanceName, final String pcjId) throws InstanceDoesNotExistException, RyaClientException; +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/common/rya.api/src/main/java/mvm/rya/api/client/GetInstanceDetails.java ---------------------------------------------------------------------- diff --git a/common/rya.api/src/main/java/mvm/rya/api/client/GetInstanceDetails.java b/common/rya.api/src/main/java/mvm/rya/api/client/GetInstanceDetails.java new file mode 100644 index 0000000..536b5a8 --- /dev/null +++ b/common/rya.api/src/main/java/mvm/rya/api/client/GetInstanceDetails.java @@ -0,0 +1,44 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 mvm.rya.api.client; + +import javax.annotation.ParametersAreNonnullByDefault; + +import com.google.common.base.Optional; + +import mvm.rya.api.instance.RyaDetails; + +/** + * Get configuration and maintenance information about a specific instance of Rya. + */ +@ParametersAreNonnullByDefault +public interface GetInstanceDetails { + + /** + * Get configuration and maintenance information about a specific instance of Rya. + * + * @param instanceName - Indicates which Rya instance to fetch the details from. (not null) + * @return The {@link RyaDetails} that describe the instance of Rya. If this is + * an older version of Rya, then there may not be any details to fetch. If + * this is the case, empty is returned. + * @throws InstanceDoesNotExistException No instance of Rya exists for the provided name. + * @throws RyaClientException Something caused the command to fail. + */ + public Optional<RyaDetails> getDetails(final String instanceName) throws InstanceDoesNotExistException, RyaClientException; +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/common/rya.api/src/main/java/mvm/rya/api/client/Install.java ---------------------------------------------------------------------- diff --git a/common/rya.api/src/main/java/mvm/rya/api/client/Install.java b/common/rya.api/src/main/java/mvm/rya/api/client/Install.java new file mode 100644 index 0000000..28a0dc5 --- /dev/null +++ b/common/rya.api/src/main/java/mvm/rya/api/client/Install.java @@ -0,0 +1,268 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 mvm.rya.api.client; + +import static java.util.Objects.requireNonNull; + +import java.util.Objects; + +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; +import javax.annotation.concurrent.Immutable; + +import com.google.common.base.Optional; + +/** + * Installs a new instance of Rya. + */ +@ParametersAreNonnullByDefault +public interface Install { + + /** + * Install a new instance of Rya. + * + * @param instanceName - Indicates the name of the Rya instance to install. (not null) + * @param installConfig - Configures how the Rya instance will operate. The + * instance name that is in this variable must match the {@code instanceName}. (not null) + * @throws DuplicateInstanceNameException A Rya instance already exists for the provided name. + * @throws RyaClientException Something caused the command to fail. + */ + public void install(final String instanceName, final InstallConfiguration installConfig) throws DuplicateInstanceNameException, RyaClientException; + + /** + * A Rya instance already exists for the provided name. + */ + public static class DuplicateInstanceNameException extends RyaClientException { + private static final long serialVersionUID = 1L; + + public DuplicateInstanceNameException(final String message) { + super(message); + } + } + + /** + * Configures how an instance of Rya will be configured when it is installed. + */ + @Immutable + @ParametersAreNonnullByDefault + public static class InstallConfiguration { + + private final boolean enableTableHashPrefix; + private final boolean enableFreeTextIndex; + private final boolean enableGeoIndex; + private final boolean enableEntityCentricIndex; + private final boolean enableTemporalIndex; + private final boolean enablePcjIndex; + private final Optional<String> fluoPcjAppName; + + /** + * Use a {@link Builder} to create instances of this class. + */ + private InstallConfiguration( + final boolean enableTableHashPrefix, + final boolean enableFreeTextIndex, + final boolean enableGeoIndex, + final boolean enableEntityCentricIndex, + final boolean enableTemporalIndex, + final boolean enablePcjIndex, + final Optional<String> fluoPcjAppName) { + this.enableTableHashPrefix = requireNonNull(enableTableHashPrefix); + this.enableFreeTextIndex = requireNonNull(enableFreeTextIndex); + this.enableGeoIndex = requireNonNull(enableGeoIndex); + this.enableEntityCentricIndex = requireNonNull(enableEntityCentricIndex); + this.enableTemporalIndex = requireNonNull(enableTemporalIndex); + this.enablePcjIndex = requireNonNull(enablePcjIndex); + this.fluoPcjAppName = requireNonNull(fluoPcjAppName); + } + + /** + * @return Whether or not the installed instance of Rya will include table prefix hashing. + */ + public boolean isTableHashPrefixEnabled() { + return enableTableHashPrefix; + } + + /** + * @return Whether or not the installed instance of Rya will maintain a Free Text index. + */ + public boolean isFreeTextIndexEnabled() { + return enableFreeTextIndex; + } + + /** + * @return Whether or not the installed instance of Rya will maintain a Geospatial index. + */ + public boolean isGeoIndexEnabled() { + return enableGeoIndex; + } + + /** + * @return Whether or not the installed instance of Rya will maintain an Entity Centric index. + */ + public boolean isEntityCentrixIndexEnabled() { + return enableEntityCentricIndex; + } + + /** + * @return Whether or not the installed instance of Rya will maintain a Temporal index. + */ + public boolean isTemporalIndexEnabled() { + return enableTemporalIndex; + } + + /** + * @return Whether or not the installed instance of Rya will maintain a PCJ index. + */ + public boolean isPcjIndexEnabled() { + return enablePcjIndex; + } + + /** + * @return The name of the Fluo application that updates this instance of Rya's PCJs. + * Optional because this does not have to be the update paradigm used. + */ + public Optional<String> getFluoPcjAppName() { + return fluoPcjAppName; + } + + @Override + public int hashCode() { + return Objects.hash( + enableTableHashPrefix, + enableFreeTextIndex, + enableGeoIndex, + enableEntityCentricIndex, + enableTemporalIndex, + enablePcjIndex, + fluoPcjAppName); + } + + @Override + public boolean equals(final Object obj) { + if(this == obj) { + return true; + } + if(obj instanceof InstallConfiguration) { + final InstallConfiguration config = (InstallConfiguration) obj; + return enableTableHashPrefix == config.enableTableHashPrefix && + enableFreeTextIndex == config.enableFreeTextIndex && + enableGeoIndex == config.enableGeoIndex && + enableEntityCentricIndex == config.enableEntityCentricIndex && + enableTemporalIndex == config.enableTemporalIndex && + enablePcjIndex == config.enablePcjIndex && + Objects.equals(fluoPcjAppName, config.fluoPcjAppName); + } + return false; + } + + /** + * @return An empty instance of {@link Builder}. + */ + public static Builder builder() { + return new Builder(); + } + + /** + * Builds instances of {@link InstallConfiguration}. + */ + @ParametersAreNonnullByDefault + public static class Builder { + private boolean enableTableHashPrefix = false; + private boolean enableFreeTextIndex = false; + private boolean enableGeoIndex = false; + private boolean enableEntityCentricIndex = false; + private boolean enableTemporalIndex = false; + private boolean enablePcjIndex = false; + private String fluoPcjAppName = null; + + /** + * @param enabled - Whether or not the installed instance of Rya will include table prefix hashing. + * @return This {@link Builder} so that method invocations may be chained. + */ + public Builder setEnableTableHashPrefix(final boolean enabled) { + enableTableHashPrefix = enabled; + return this; + } + + /** + * @param enabled - Whether or not the installed instance of Rya will maintain a Free Text index. + * @return This {@link Builder} so that method invocations may be chained. + */ + public Builder setEnableFreeTextIndex(final boolean enabled) { + enableFreeTextIndex = enabled; + return this; + } + + /** + * @param enabled - Whether or not the installed instance of Rya will maintain a Geospatial index. + * @return This {@link Builder} so that method invocations may be chained. + */ + public Builder setEnableGeoIndex(final boolean enabled) { + enableGeoIndex = enabled; + return this; + } + + /** + * @param enabled - Whether or not the installed instance of Rya will maintain an Entity Centric index. + * @return This {@link Builder} so that method invocations may be chained. + */ + public Builder setEnableEntityCentricIndex(final boolean enabled) { + enableEntityCentricIndex = enabled; + return this; + } + + /** + * @param enabled - Whether or not the installed instance of Rya will maintain a Temporal index. + * @return This {@link Builder} so that method invocations may be chained. + */ + public Builder setEnableTemporalIndex(final boolean enabled) { + enableTemporalIndex = enabled; + return this; + } + + /** + * @param enabled - Whether or not the installed instance of Rya will maintain a PCJ index. + * @return This {@link Builder} so that method invocations may be chained. + */ + public Builder setEnablePcjIndex(final boolean enabled) { + enablePcjIndex = enabled; + return this; + } + + public Builder setFluoPcjAppName(@Nullable final String fluoPcjAppName) { + this.fluoPcjAppName = fluoPcjAppName; + return this; + } + + /** + * @return Builds an instance of {@link InstallConfiguration} using this builder's values. + */ + public InstallConfiguration build() { + return new InstallConfiguration( + enableTableHashPrefix, + enableFreeTextIndex, + enableGeoIndex, + enableEntityCentricIndex, + enableTemporalIndex, + enablePcjIndex, + Optional.fromNullable(fluoPcjAppName)); + } + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/common/rya.api/src/main/java/mvm/rya/api/client/InstanceDoesNotExistException.java ---------------------------------------------------------------------- diff --git a/common/rya.api/src/main/java/mvm/rya/api/client/InstanceDoesNotExistException.java b/common/rya.api/src/main/java/mvm/rya/api/client/InstanceDoesNotExistException.java new file mode 100644 index 0000000..c8cc0aa --- /dev/null +++ b/common/rya.api/src/main/java/mvm/rya/api/client/InstanceDoesNotExistException.java @@ -0,0 +1,38 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 mvm.rya.api.client; + +import javax.annotation.ParametersAreNonnullByDefault; + +/** + * One of the {@link RyaClient} commands could not execute because the connected + * instance of Rya does not exist. + */ +@ParametersAreNonnullByDefault +public class InstanceDoesNotExistException extends RyaClientException { + private static final long serialVersionUID = 1L; + + public InstanceDoesNotExistException(final String message) { + super(message); + } + + public InstanceDoesNotExistException(final String message, final Throwable cause) { + super(message, cause); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/common/rya.api/src/main/java/mvm/rya/api/client/InstanceExists.java ---------------------------------------------------------------------- diff --git a/common/rya.api/src/main/java/mvm/rya/api/client/InstanceExists.java b/common/rya.api/src/main/java/mvm/rya/api/client/InstanceExists.java new file mode 100644 index 0000000..6f26fc6 --- /dev/null +++ b/common/rya.api/src/main/java/mvm/rya/api/client/InstanceExists.java @@ -0,0 +1,37 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 mvm.rya.api.client; + +import javax.annotation.ParametersAreNonnullByDefault; + +/** + * Checks if an instance of Rya has been installed. + */ +@ParametersAreNonnullByDefault +public interface InstanceExists { + + /** + * Checks if an instance of Rya has been installed. + * + * @param instanceName - The name to check. (not null) + * @return {@code true} If an instance of Rya exists with the provided name; otherwise {@code false}. + * @throws RyaClientException Something caused the command to fail. + */ + public boolean exists(String instanceName) throws RyaClientException; +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/common/rya.api/src/main/java/mvm/rya/api/client/ListInstances.java ---------------------------------------------------------------------- diff --git a/common/rya.api/src/main/java/mvm/rya/api/client/ListInstances.java b/common/rya.api/src/main/java/mvm/rya/api/client/ListInstances.java new file mode 100644 index 0000000..5edfbc4 --- /dev/null +++ b/common/rya.api/src/main/java/mvm/rya/api/client/ListInstances.java @@ -0,0 +1,38 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 mvm.rya.api.client; + +import java.util.List; + +import javax.annotation.ParametersAreNonnullByDefault; + +/** + * List the names of the installed Rya instances. + */ +@ParametersAreNonnullByDefault +public interface ListInstances { + + /** + * List the names of the installed Rya instances. + * + * @return The names of the installed Rya Instances. + * @throws RyaClientException Something caused the command to fail. + */ + public List<String> listInstances() throws RyaClientException; +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/common/rya.api/src/main/java/mvm/rya/api/client/RyaClient.java ---------------------------------------------------------------------- diff --git a/common/rya.api/src/main/java/mvm/rya/api/client/RyaClient.java b/common/rya.api/src/main/java/mvm/rya/api/client/RyaClient.java new file mode 100644 index 0000000..173e1e0 --- /dev/null +++ b/common/rya.api/src/main/java/mvm/rya/api/client/RyaClient.java @@ -0,0 +1,101 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 mvm.rya.api.client; + +import static java.util.Objects.requireNonNull; + +import javax.annotation.ParametersAreNonnullByDefault; +import javax.annotation.concurrent.Immutable; + +/** + * Provides access to a set of Rya functions. + */ +@Immutable +@ParametersAreNonnullByDefault +public class RyaClient { + // Administrative functions. + private final Install install; + private final CreatePCJ createPcj; + private final DeletePCJ deletePcj; + private final GetInstanceDetails getInstanceDetails; + private final InstanceExists instanceExists; + private final ListInstances listInstances; + + /** + * Constructs an isntance of {@link RyaClient}. + */ + public RyaClient( + final Install install, + final CreatePCJ createPcj, + final DeletePCJ deletePcj, + final GetInstanceDetails getInstanceDetails, + final InstanceExists instanceExists, + final ListInstances listInstances) { + this.install = requireNonNull(install); + this.createPcj = requireNonNull(createPcj); + this.deletePcj = requireNonNull(deletePcj); + this.getInstanceDetails = requireNonNull(getInstanceDetails); + this.instanceExists = requireNonNull(instanceExists); + this.listInstances = requireNonNull(listInstances); + } + + /** + * @return An instance of {@link Install} that is connected to a Rya storage. + */ + public Install getInstall() { + return install; + } + + /** + * @return An instance of {@link CreatePCJ} that is connected to a Rya storage + * if the Rya instance supports PCJ indexing. + */ + public CreatePCJ getCreatePCJ() { + return createPcj; + } + + /** + * @return An instance of {@link DeletePCJ} that is connected to a Rya storage + * if the Rya instance supports PCJ indexing. + */ + public DeletePCJ getDeletePCJ() { + return deletePcj; + } + + /** + * @return An instance of {@link GetInstanceDetails} that is connected to a Rya storage. + */ + public GetInstanceDetails getGetInstanceDetails() { + return getInstanceDetails; + } + + /** + * @return An instance of {@link ListInstances} that is connected to a Rya storage. + */ + public ListInstances getListInstances() { + return listInstances; + } + + /** + * @return An instance of {@link InstanceExists} that is connected to a Rya storage. + */ + public InstanceExists getInstanceExists() { + return instanceExists; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/common/rya.api/src/main/java/mvm/rya/api/client/RyaClientException.java ---------------------------------------------------------------------- diff --git a/common/rya.api/src/main/java/mvm/rya/api/client/RyaClientException.java b/common/rya.api/src/main/java/mvm/rya/api/client/RyaClientException.java new file mode 100644 index 0000000..28c78aa --- /dev/null +++ b/common/rya.api/src/main/java/mvm/rya/api/client/RyaClientException.java @@ -0,0 +1,37 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 mvm.rya.api.client; + +import javax.annotation.ParametersAreNonnullByDefault; + +/** + * One of the {@link RyaClient} functions failed. + */ +@ParametersAreNonnullByDefault +public class RyaClientException extends Exception { + private static final long serialVersionUID = 1L; + + public RyaClientException(final String message) { + super(message); + } + + public RyaClientException(final String message, final Throwable cause) { + super(message, cause); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/common/rya.api/src/main/java/mvm/rya/api/instance/RyaDetails.java ---------------------------------------------------------------------- diff --git a/common/rya.api/src/main/java/mvm/rya/api/instance/RyaDetails.java b/common/rya.api/src/main/java/mvm/rya/api/instance/RyaDetails.java index 91d6608..565b545 100644 --- a/common/rya.api/src/main/java/mvm/rya/api/instance/RyaDetails.java +++ b/common/rya.api/src/main/java/mvm/rya/api/instance/RyaDetails.java @@ -23,6 +23,9 @@ import static java.util.Objects.requireNonNull; import java.io.Serializable; import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; import java.util.Objects; import javax.annotation.Nullable; @@ -186,6 +189,14 @@ public class RyaDetails implements Serializable { } /** + * @param detials - The builder will be initialized with this object's values. (not null) + * @return An instance of {@link Builder} that is initialized with a {@link RyaDetails}'s values. + */ + public static Builder builder(final RyaDetails details) { + return new Builder(details); + } + + /** * Builds instances of {@link RyaDetails}. */ @ParametersAreNonnullByDefault @@ -198,7 +209,7 @@ public class RyaDetails implements Serializable { // Secondary Index Details. private EntityCentricIndexDetails entityCentricDetails; private GeoIndexDetails geoDetails; - private PCJIndexDetails pcjDetails; + private PCJIndexDetails.Builder pcjIndexDetailsBuilder; private TemporalIndexDetails temporalDetails; private FreeTextIndexDetails freeTextDetails; @@ -219,12 +230,11 @@ public class RyaDetails implements Serializable { */ public Builder(final RyaDetails details) { requireNonNull(details); - instanceName = details.instanceName; version = details.version; entityCentricDetails = details.entityCentricDetails; geoDetails = details.geoDetails; - pcjDetails = details.pcjDetails; + pcjIndexDetailsBuilder = PCJIndexDetails.builder( details.pcjDetails ); temporalDetails = details.temporalDetails; freeTextDetails = details.freeTextDetails; prospectorDetails = details.prospectorDetails; @@ -291,12 +301,20 @@ public class RyaDetails implements Serializable { * @param pcjDetails - Information about the instance's Precomputed Join Index. * @return This {@link Builder} so that method invocations may be chained. */ - public Builder setPCJIndexDetails(@Nullable final PCJIndexDetails pcjDetails) { - this.pcjDetails = pcjDetails; + public Builder setPCJIndexDetails(@Nullable final PCJIndexDetails.Builder pcjDetailsBuilder) { + this.pcjIndexDetailsBuilder = pcjDetailsBuilder; return this; } /** + * @return Get the {@link PCJIndexDetails.Builder} used to build the + * PCJ Index's details. + */ + public @Nullable PCJIndexDetails.Builder getPCJIndexDetails() { + return pcjIndexDetailsBuilder; + } + + /** * @param prospectorDetails - Information about the instance's Prospector Statistics. * @return This {@link Builder} so that method invocations may be chained. */ @@ -324,7 +342,7 @@ public class RyaDetails implements Serializable { version, entityCentricDetails, geoDetails, - pcjDetails, + pcjIndexDetailsBuilder.build(), temporalDetails, freeTextDetails, prospectorDetails, @@ -590,6 +608,14 @@ public class RyaDetails implements Serializable { } /** + * @param detials - The builder will be initialized with this object's values. (not null) + * @return An instance of {@link Builder} that is initialized with a {@link PCJIndexDetails}'s values. + */ + public static Builder builder(final PCJIndexDetails pcjIndexDetails) { + return new Builder(pcjIndexDetails); + } + + /** * Builds instance of {@link PCJIndexDetails). */ @ParametersAreNonnullByDefault @@ -597,7 +623,29 @@ public class RyaDetails implements Serializable { private Boolean enabled = null; private FluoDetails fluoDetails = null; - private final ImmutableMap.Builder<String, PCJDetails> pcjDetails = ImmutableMap.builder(); + private final Map<String, PCJDetails.Builder> pcjDetailsBuilders = new HashMap<>(); + + /** + * Constructs an empty instance of {@link Builder}. + */ + public Builder() { } + + /** + * Constructs an instance of {@link Builder} that is initialized with + * the values of a {@link PCJIndexDetails}. + * + * @param pcjIndexDetails - This objects values will be used to initialize + * the builder. (not null) + */ + public Builder(final PCJIndexDetails pcjIndexDetails) { + requireNonNull(pcjIndexDetails); + this.enabled = pcjIndexDetails.enabled; + this.fluoDetails = pcjIndexDetails.fluoDetails.orNull(); + + for(final PCJDetails pcjDetails : pcjIndexDetails.pcjDetails.values()) { + pcjDetailsBuilders.put(pcjDetails.getId(), PCJDetails.builder(pcjDetails)); + } + } /** * @param enabled - Whether or not a Precomputed Join Index will be maintained by the Rya instance. @@ -622,17 +670,32 @@ public class RyaDetails implements Serializable { * @param pcjDetails - Details about the PCJs that have been created for this Rya instance. * @return This {@link Builder} so that method invocations may be chained. */ - public Builder addPCJDetails(@Nullable final PCJDetails pcjDetails) { - if(pcjDetails != null) { - this.pcjDetails.put(pcjDetails.getId(), pcjDetails); + public Builder addPCJDetails(@Nullable final PCJDetails.Builder pcjDetailsBuilder) { + if(pcjDetailsBuilder != null) { + this.pcjDetailsBuilders.put(pcjDetailsBuilder.getId(), pcjDetailsBuilder); } return this; } /** + * @param pcjId - The PCJ ID of the {@link PCJDetails.Builder} to remove. (not null) + * @return This {@link Builder} so that method invocations may be chained. + */ + public Builder removePCJDetails(@Nullable final String pcjId) { + requireNonNull(pcjId); + this.pcjDetailsBuilders.remove(pcjId); + return this; + } + + /** * @return Builds an instance of {@link PCJIndexDetails} using this builder's values. */ public PCJIndexDetails build() { + final ImmutableMap.Builder<String, PCJDetails> pcjDetails = ImmutableMap.builder(); + for(final Entry<String, PCJDetails.Builder> entry : pcjDetailsBuilders.entrySet()) { + pcjDetails.put(entry.getKey(), entry.getValue().build()); + } + return new PCJIndexDetails( enabled, Optional.fromNullable( fluoDetails ), @@ -695,7 +758,7 @@ public class RyaDetails implements Serializable { private static final long serialVersionUID = 1L; private final String id; - private final PCJUpdateStrategy updateStrategy; + private final Optional<PCJUpdateStrategy> updateStrategy; private final Optional<Date> lastUpdateTime; /** @@ -709,7 +772,7 @@ public class RyaDetails implements Serializable { */ private PCJDetails( final String id, - final PCJUpdateStrategy updateStrategy, + final Optional<PCJUpdateStrategy> updateStrategy, final Optional<Date> lastUpdateTime) { this.id = requireNonNull(id); this.updateStrategy = requireNonNull(updateStrategy); @@ -726,7 +789,7 @@ public class RyaDetails implements Serializable { /** * @return Describes how the PCJ is being updated. */ - public PCJUpdateStrategy getUpdateStrategy() { + public Optional<PCJUpdateStrategy> getUpdateStrategy() { return updateStrategy; } @@ -765,6 +828,14 @@ public class RyaDetails implements Serializable { } /** + * @param detials - The builder will be initialized with this object's values. (not null) + * @return An instance of {@link Builder} that is initialized with a {@link PCJDetails}' values. + */ + public static Builder builder(final PCJDetails details) { + return new Builder(details); + } + + /** * Builds instance of {@link PCJDetails}. */ @ParametersAreNonnullByDefault @@ -775,6 +846,31 @@ public class RyaDetails implements Serializable { private Date lastUpdateTime; /** + * Constructs an instance of {@link Builder}. + */ + public Builder() { } + + /** + * Constructs an instance of {@link Builder} that is initialized with + * the values of a {@link PCJDetails}. + * + * @param details - This object's values will be used to initialize the builder. (not null) + */ + public Builder(final PCJDetails details) { + requireNonNull(details); + this.id = details.id; + this.updateStrategy = details.updateStrategy.orNull(); + this.lastUpdateTime = details.lastUpdateTime.orNull(); + } + + /** + * @return Uniquely identifies the PCJ within this instance of Rya. + */ + public @Nullable String getId() { + return id; + } + + /** * @param id - Uniquely identifies the PCJ within this instance of Rya. * @return This {@link Builder} so that method invocations may be chained. */ @@ -784,6 +880,13 @@ public class RyaDetails implements Serializable { } /** + * @return Describes how the PCJ is being updated. + */ + public PCJUpdateStrategy getUpdateStrategy() { + return updateStrategy; + } + + /** * @param updateStrategy - Describes how the PCJ is being updated. * @return This {@link Builder} so that method invocations may be chained. */ @@ -793,6 +896,13 @@ public class RyaDetails implements Serializable { } /** + * @return The last time the PCJ was updated. This information may not be provided. + */ + public @Nullable Date getLastUpdateTime() { + return lastUpdateTime; + } + + /** * @param lastUpdateTime - The last time the PCJ was updated. This information * may not be provided. * @return This {@link Builder} so that method invocations may be chained. @@ -806,7 +916,10 @@ public class RyaDetails implements Serializable { * @return An instance of {@link PCJDetails} built using this builder's values. */ public PCJDetails build() { - return new PCJDetails(id, updateStrategy, Optional.fromNullable(lastUpdateTime)); + return new PCJDetails( + id, + Optional.fromNullable(updateStrategy), + Optional.fromNullable(lastUpdateTime)); } } http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/common/rya.api/src/main/java/mvm/rya/api/instance/RyaDetailsToConfiguration.java ---------------------------------------------------------------------- diff --git a/common/rya.api/src/main/java/mvm/rya/api/instance/RyaDetailsToConfiguration.java b/common/rya.api/src/main/java/mvm/rya/api/instance/RyaDetailsToConfiguration.java index 75ae416..faec0ff 100644 --- a/common/rya.api/src/main/java/mvm/rya/api/instance/RyaDetailsToConfiguration.java +++ b/common/rya.api/src/main/java/mvm/rya/api/instance/RyaDetailsToConfiguration.java @@ -1,4 +1,4 @@ -/* +/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -7,7 +7,7 @@ * "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 + * 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 http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/common/rya.api/src/main/java/mvm/rya/api/instance/RyaDetailsUpdater.java ---------------------------------------------------------------------- diff --git a/common/rya.api/src/main/java/mvm/rya/api/instance/RyaDetailsUpdater.java b/common/rya.api/src/main/java/mvm/rya/api/instance/RyaDetailsUpdater.java new file mode 100644 index 0000000..9d5dae7 --- /dev/null +++ b/common/rya.api/src/main/java/mvm/rya/api/instance/RyaDetailsUpdater.java @@ -0,0 +1,124 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 mvm.rya.api.instance; + +import static java.util.Objects.requireNonNull; + +import javax.annotation.ParametersAreNonnullByDefault; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import mvm.rya.api.instance.RyaDetailsRepository.ConcurrentUpdateException; +import mvm.rya.api.instance.RyaDetailsRepository.RyaDetailsRepositoryException; +import mvm.rya.api.instance.RyaDetailsUpdater.RyaDetailsMutator.CouldNotApplyMutationException; + +/** + * A utility that will attempt to commit a change to a Rya instance's details + * until it either takes or the mutation can no longer be applied. This can + * can be used in place of boilerplate code that handles the concurrent nature + * of details updates. + */ +@ParametersAreNonnullByDefault +public class RyaDetailsUpdater { + private static final Logger log = LoggerFactory.getLogger(RyaDetailsUpdater.class); + + /** + * Applies a mutation to a an instance of {@link RyaDetails}. + */ + @ParametersAreNonnullByDefault + public static interface RyaDetailsMutator { + + /** + * Applies a mutation to a {@link RyaDetails} object. + * + * @param originalDetails - The {@link RyaDetails} that were just fetched + * from the {@link RyaDetailsRepository}. + * @return The updated details. + * @throws CouldNotApplyMutationException The mutation could not be applied + * to the supplied {@link RyaDetails}. This can be used to break out of + * the update loop when the details are in a state the mutation can not + * be applied to. + */ + public RyaDetails mutate(RyaDetails originalDetails) throws CouldNotApplyMutationException; + + /** + * Indicates a mutation could not be applied to an instance of {@link RyaDetails}. + */ + public static class CouldNotApplyMutationException extends Exception { + private static final long serialVersionUID = 1L; + + /** + * Constructs a new exception with the specified detail message. The + * cause is not initialized, and may subsequently be initialized by + * a call to {@link #initCause(Throwable)}. + * + * @param message the detail message. The detail message is saved for + * later retrieval by the {@link #getMessage()} method. + */ + public CouldNotApplyMutationException(final String message) { + super(message); + } + } + } + + private final RyaDetailsRepository repo; + + /** + * Constructs an instance of {@link RyaDetailsUpdater}. + * + * @param repo - The repository that this updater will commit changes to. (not null) + */ + public RyaDetailsUpdater(final RyaDetailsRepository repo) { + this.repo = requireNonNull(repo); + } + + /** + * Updates an instance of {@link RyaDetails} by fetching the details from + * the {@link RyaDetailsRepository} that was supplied at construction time, + * applying the {@link RyaDetailsMutator} to them, and them committing the + * change. If the update failed because of a concurrent update problem, then + * it will try again. The updater will continue to do this until the changes + * take or another exception type is thrown. + * + * @param mutator - The mutator that will be used to apply a chagne to the + * repository's {@link RyaDetails}. + * @throws RyaDetailsRepositoryException A repository side error caused + * the update to fail. This could be a communications problem with the + * store repository, uninitialized, etc. + * @throws CouldNotApplyMutationException An application side error caused + * the update to fail. This is thrown by the mutator when the details + * would be in an illegal state if the mutation were to be applied. + */ + public void update(final RyaDetailsMutator mutator) throws RyaDetailsRepositoryException, CouldNotApplyMutationException { + requireNonNull(mutator); + + boolean updated = false; + while(!updated) { + try { + final RyaDetails original = repo.getRyaInstanceDetails(); + final RyaDetails mutated = mutator.mutate(original); + repo.update(original, mutated); + updated = true; + } catch(final ConcurrentUpdateException e) { + log.debug("Failed to update the details because another application changed them. Trying again.", e); + } + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/common/rya.api/src/test/java/mvm/rya/api/instance/RyaDetailsTest.java ---------------------------------------------------------------------- diff --git a/common/rya.api/src/test/java/mvm/rya/api/instance/RyaDetailsTest.java b/common/rya.api/src/test/java/mvm/rya/api/instance/RyaDetailsTest.java index c629fb6..c613fee 100644 --- a/common/rya.api/src/test/java/mvm/rya/api/instance/RyaDetailsTest.java +++ b/common/rya.api/src/test/java/mvm/rya/api/instance/RyaDetailsTest.java @@ -61,14 +61,11 @@ public class RyaDetailsTest { PCJDetails.builder() .setId("pcj 1") .setUpdateStrategy(PCJUpdateStrategy.BATCH) - .setLastUpdateTime( new Date() ) - .build()) + .setLastUpdateTime( new Date() )) .addPCJDetails( PCJDetails.builder() .setId("pcj 2") - .setUpdateStrategy(PCJUpdateStrategy.INCREMENTAL) - .build()) - .build()) + .setUpdateStrategy(PCJUpdateStrategy.INCREMENTAL))) .setProspectorDetails( new ProspectorDetails(Optional.of(new Date())) ) .setJoinSelectivityDetails( new JoinSelectivityDetails(Optional.of(new Date())) ); @@ -95,14 +92,11 @@ public class RyaDetailsTest { PCJDetails.builder() .setId("pcj 1") .setUpdateStrategy(PCJUpdateStrategy.BATCH) - .setLastUpdateTime( new Date() ) - .build()) + .setLastUpdateTime( new Date() )) .addPCJDetails( PCJDetails.builder() .setId("pcj 2") - .setUpdateStrategy(PCJUpdateStrategy.INCREMENTAL) - .build()) - .build()) + .setUpdateStrategy(PCJUpdateStrategy.INCREMENTAL))) .setProspectorDetails( new ProspectorDetails(Optional.of(new Date())) ) .setJoinSelectivityDetails( new JoinSelectivityDetails(Optional.of(new Date())) ); @@ -128,14 +122,11 @@ public class RyaDetailsTest { PCJDetails.builder() .setId("pcj 1") .setUpdateStrategy(PCJUpdateStrategy.BATCH) - .setLastUpdateTime( new Date() ) - .build()) + .setLastUpdateTime( new Date() )) .addPCJDetails( PCJDetails.builder() .setId("pcj 2") - .setUpdateStrategy(PCJUpdateStrategy.INCREMENTAL) - .build()) - .build()) + .setUpdateStrategy(PCJUpdateStrategy.INCREMENTAL))) .setProspectorDetails( new ProspectorDetails(Optional.of(new Date())) ) .setJoinSelectivityDetails( new JoinSelectivityDetails(Optional.of(new Date())) ) .build(); http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/common/rya.api/src/test/java/mvm/rya/api/instance/RyaDetailsToConfigurationTest.java ---------------------------------------------------------------------- diff --git a/common/rya.api/src/test/java/mvm/rya/api/instance/RyaDetailsToConfigurationTest.java b/common/rya.api/src/test/java/mvm/rya/api/instance/RyaDetailsToConfigurationTest.java index 32b75cf..960e8a9 100644 --- a/common/rya.api/src/test/java/mvm/rya/api/instance/RyaDetailsToConfigurationTest.java +++ b/common/rya.api/src/test/java/mvm/rya/api/instance/RyaDetailsToConfigurationTest.java @@ -64,14 +64,11 @@ public class RyaDetailsToConfigurationTest { PCJDetails.builder() .setId("pcj 1") .setUpdateStrategy(PCJUpdateStrategy.BATCH) - .setLastUpdateTime( new Date() ) - .build()) + .setLastUpdateTime( new Date() )) .addPCJDetails( PCJDetails.builder() .setId("pcj 2") - .setUpdateStrategy(PCJUpdateStrategy.INCREMENTAL) - .build()) - .build()) + .setUpdateStrategy(PCJUpdateStrategy.INCREMENTAL))) .setProspectorDetails( new ProspectorDetails(Optional.of(new Date())) ) .setJoinSelectivityDetails( new JoinSelectivityDetails(Optional.of(new Date())) ); final Configuration conf = new Configuration(); http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/common/rya.api/src/test/java/mvm/rya/api/instance/RyaDetailsUpdaterTest.java ---------------------------------------------------------------------- diff --git a/common/rya.api/src/test/java/mvm/rya/api/instance/RyaDetailsUpdaterTest.java b/common/rya.api/src/test/java/mvm/rya/api/instance/RyaDetailsUpdaterTest.java new file mode 100644 index 0000000..596cc7b --- /dev/null +++ b/common/rya.api/src/test/java/mvm/rya/api/instance/RyaDetailsUpdaterTest.java @@ -0,0 +1,141 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 mvm.rya.api.instance; + +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.Date; + +import org.junit.Test; + +import com.google.common.base.Optional; + +import mvm.rya.api.instance.RyaDetails.EntityCentricIndexDetails; +import mvm.rya.api.instance.RyaDetails.FreeTextIndexDetails; +import mvm.rya.api.instance.RyaDetails.GeoIndexDetails; +import mvm.rya.api.instance.RyaDetails.JoinSelectivityDetails; +import mvm.rya.api.instance.RyaDetails.PCJIndexDetails; +import mvm.rya.api.instance.RyaDetails.ProspectorDetails; +import mvm.rya.api.instance.RyaDetails.TemporalIndexDetails; +import mvm.rya.api.instance.RyaDetailsRepository.ConcurrentUpdateException; +import mvm.rya.api.instance.RyaDetailsRepository.NotInitializedException; +import mvm.rya.api.instance.RyaDetailsRepository.RyaDetailsRepositoryException; +import mvm.rya.api.instance.RyaDetailsUpdater.RyaDetailsMutator; +import mvm.rya.api.instance.RyaDetailsUpdater.RyaDetailsMutator.CouldNotApplyMutationException; + +/** + * Tests the methods of {@link RyaDetailsUpdater}. + */ +public class RyaDetailsUpdaterTest { + + @Test + public void update() throws RyaDetailsRepositoryException, CouldNotApplyMutationException { + // Setup initial details and mock a repository that returns them. + final RyaDetails originalDetails = RyaDetails.builder() + .setRyaInstanceName("instanceName") + .setRyaVersion("0.0.0.0") + .setFreeTextDetails( new FreeTextIndexDetails(true) ) + .setEntityCentricIndexDetails( new EntityCentricIndexDetails(true) ) + .setGeoIndexDetails( new GeoIndexDetails(true) ) + .setTemporalIndexDetails( new TemporalIndexDetails(true) ) + .setPCJIndexDetails( + PCJIndexDetails.builder() + .setEnabled(true) ) + .setJoinSelectivityDetails( new JoinSelectivityDetails( Optional.<Date>absent() ) ) + .setProspectorDetails( new ProspectorDetails( Optional.<Date>absent() )) + .build(); + + final RyaDetailsRepository detailsRepo = mock( RyaDetailsRepository.class ); + when( detailsRepo.getRyaInstanceDetails() ).thenReturn( originalDetails ); + + // Use an updater to change the Rya version number. + new RyaDetailsUpdater(detailsRepo).update(new RyaDetailsMutator() { + @Override + public RyaDetails mutate(final RyaDetails old) { + return RyaDetails.builder(old) + .setRyaVersion("1.1.1.1") + .build(); + } + }); + + // Verify the repository was asked to update the details. + final RyaDetails mutatedDetails = RyaDetails.builder(originalDetails) + .setRyaVersion("1.1.1.1") + .build(); + verify(detailsRepo, times(1)).update( eq(originalDetails), eq(mutatedDetails) ); + } + + @Test + public void update_concurrentUpdateEncountered() throws NotInitializedException, RyaDetailsRepositoryException, CouldNotApplyMutationException { + // Setup initial details and mock a repository that returns them. + final RyaDetails originalDetails = RyaDetails.builder() + .setRyaInstanceName("instanceName") + .setRyaVersion("0.0.0.0") + .setFreeTextDetails( new FreeTextIndexDetails(true) ) + .setEntityCentricIndexDetails( new EntityCentricIndexDetails(true) ) + .setGeoIndexDetails( new GeoIndexDetails(true) ) + .setTemporalIndexDetails( new TemporalIndexDetails(true) ) + .setPCJIndexDetails( + PCJIndexDetails.builder() + .setEnabled(true) ) + .setJoinSelectivityDetails( new JoinSelectivityDetails( Optional.<Date>absent() ) ) + .setProspectorDetails( new ProspectorDetails( Optional.<Date>absent() )) + .build(); + + final RyaDetails otherUsersUpdate = RyaDetails.builder(originalDetails) + .setRyaVersion("1.1.1.1") + .build(); + + // The first time get detail is called, we get the original state for the details. + // When the mutator tries to update using those, it throws an exception. + // The second iteration, the other user's state is updated. + // When the mutator tries to update again, it succeeds. + final RyaDetailsRepository detailsRepo = mock( RyaDetailsRepository.class ); + + when( detailsRepo.getRyaInstanceDetails() ) + .thenReturn( originalDetails ) + .thenReturn( otherUsersUpdate ); + + doThrow( ConcurrentUpdateException.class ).when( detailsRepo ).update( eq(originalDetails), any(RyaDetails.class) ); + + // Run the test. + new RyaDetailsUpdater(detailsRepo).update(new RyaDetailsMutator() { + @Override + public RyaDetails mutate(final RyaDetails old) { + return RyaDetails.builder(old) + .setTemporalIndexDetails( new TemporalIndexDetails(false) ) + .build(); + } + }); + + // Verify the intended mutation eventually gets committed. + final RyaDetails finalDetails = RyaDetails.builder(originalDetails) + .setRyaVersion("1.1.1.1") + .setTemporalIndexDetails( new TemporalIndexDetails(false) ) + .build(); + + verify(detailsRepo, times(1)).update( eq(otherUsersUpdate), eq(finalDetails) ); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/dao/accumulo.rya/pom.xml ---------------------------------------------------------------------- diff --git a/dao/accumulo.rya/pom.xml b/dao/accumulo.rya/pom.xml index 1fa6f55..b837fa3 100644 --- a/dao/accumulo.rya/pom.xml +++ b/dao/accumulo.rya/pom.xml @@ -84,6 +84,20 @@ under the License. <build> <plugins> <plugin> + <!-- generate the test jar as well so it can be reused by dependent tools. + TODO this is messy. in the future, classes that provide this functionality + should be decoupled into reusable frameworks. --> + <artifactId>maven-jar-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>test-jar</goal> + </goals> + </execution> + </executions> + </plugin> + + <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-failsafe-plugin</artifactId> <executions> http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/dao/accumulo.rya/src/main/java/mvm/rya/accumulo/AccumuloRyaDAO.java ---------------------------------------------------------------------- diff --git a/dao/accumulo.rya/src/main/java/mvm/rya/accumulo/AccumuloRyaDAO.java b/dao/accumulo.rya/src/main/java/mvm/rya/accumulo/AccumuloRyaDAO.java index ed991e1..195030e 100644 --- a/dao/accumulo.rya/src/main/java/mvm/rya/accumulo/AccumuloRyaDAO.java +++ b/dao/accumulo.rya/src/main/java/mvm/rya/accumulo/AccumuloRyaDAO.java @@ -31,7 +31,6 @@ import static mvm.rya.api.RdfCloudTripleStoreConstants.NUM_THREADS; import static mvm.rya.api.RdfCloudTripleStoreConstants.RTS_SUBJECT_RYA; import static mvm.rya.api.RdfCloudTripleStoreConstants.RTS_VERSION_PREDICATE_RYA; import static mvm.rya.api.RdfCloudTripleStoreConstants.VERSION_RYA; -import info.aduna.iteration.CloseableIteration; import java.io.IOException; import java.util.Collection; @@ -41,18 +40,6 @@ import java.util.List; import java.util.Map; import java.util.concurrent.TimeUnit; -import mvm.rya.accumulo.experimental.AccumuloIndexer; -import mvm.rya.accumulo.query.AccumuloRyaQueryEngine; -import mvm.rya.api.RdfCloudTripleStoreConfiguration; -import mvm.rya.api.RdfCloudTripleStoreConstants.TABLE_LAYOUT; -import mvm.rya.api.domain.RyaStatement; -import mvm.rya.api.domain.RyaURI; -import mvm.rya.api.layout.TableLayoutStrategy; -import mvm.rya.api.persist.RyaDAO; -import mvm.rya.api.persist.RyaDAOException; -import mvm.rya.api.persist.RyaNamespaceManager; -import mvm.rya.api.resolver.RyaTripleContext; - import org.apache.accumulo.core.client.AccumuloException; import org.apache.accumulo.core.client.AccumuloSecurityException; import org.apache.accumulo.core.client.BatchDeleter; @@ -77,6 +64,19 @@ import org.openrdf.model.Namespace; import com.google.common.collect.Iterators; import com.google.common.collect.Lists; +import info.aduna.iteration.CloseableIteration; +import mvm.rya.accumulo.experimental.AccumuloIndexer; +import mvm.rya.accumulo.query.AccumuloRyaQueryEngine; +import mvm.rya.api.RdfCloudTripleStoreConfiguration; +import mvm.rya.api.RdfCloudTripleStoreConstants.TABLE_LAYOUT; +import mvm.rya.api.domain.RyaStatement; +import mvm.rya.api.domain.RyaURI; +import mvm.rya.api.layout.TableLayoutStrategy; +import mvm.rya.api.persist.RyaDAO; +import mvm.rya.api.persist.RyaDAOException; +import mvm.rya.api.persist.RyaNamespaceManager; +import mvm.rya.api.resolver.RyaTripleContext; + public class AccumuloRyaDAO implements RyaDAO<AccumuloRdfConfiguration>, RyaNamespaceManager<AccumuloRdfConfiguration> { private static final Log logger = LogFactory.getLog(AccumuloRyaDAO.class); http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/dao/accumulo.rya/src/main/java/mvm/rya/accumulo/instance/AccumuloRyaInstanceDetailsRepository.java ---------------------------------------------------------------------- diff --git a/dao/accumulo.rya/src/main/java/mvm/rya/accumulo/instance/AccumuloRyaInstanceDetailsRepository.java b/dao/accumulo.rya/src/main/java/mvm/rya/accumulo/instance/AccumuloRyaInstanceDetailsRepository.java index ec9f266..6e818b3 100644 --- a/dao/accumulo.rya/src/main/java/mvm/rya/accumulo/instance/AccumuloRyaInstanceDetailsRepository.java +++ b/dao/accumulo.rya/src/main/java/mvm/rya/accumulo/instance/AccumuloRyaInstanceDetailsRepository.java @@ -63,7 +63,7 @@ import mvm.rya.api.instance.RyaDetailsRepository; @ParametersAreNonnullByDefault public class AccumuloRyaInstanceDetailsRepository implements RyaDetailsRepository { - private static final String INSTANCE_DETAILS_TABLE_NAME = "instance_details"; + public static final String INSTANCE_DETAILS_TABLE_NAME = "instance_details"; private static final Text ROW_ID = new Text("instance metadata"); private static final Text COL_FAMILY = new Text("instance"); @@ -143,7 +143,7 @@ public class AccumuloRyaInstanceDetailsRepository implements RyaDetailsRepositor try { writer.close(); } catch (final MutationsRejectedException e) { - throw new RyaDetailsRepositoryException("", e); + throw new RyaDetailsRepositoryException("Could not initialize the Rya instance details for the instance named '" + instanceName + "'.", e); } } } http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/dao/accumulo.rya/src/test/java/mvm/rya/accumulo/AccumuloITBase.java ---------------------------------------------------------------------- diff --git a/dao/accumulo.rya/src/test/java/mvm/rya/accumulo/AccumuloITBase.java b/dao/accumulo.rya/src/test/java/mvm/rya/accumulo/AccumuloITBase.java new file mode 100644 index 0000000..2a1c384 --- /dev/null +++ b/dao/accumulo.rya/src/test/java/mvm/rya/accumulo/AccumuloITBase.java @@ -0,0 +1,107 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 mvm.rya.accumulo; + +import java.io.IOException; + +import org.apache.accumulo.core.client.AccumuloException; +import org.apache.accumulo.core.client.AccumuloSecurityException; +import org.apache.accumulo.core.client.Connector; +import org.apache.accumulo.minicluster.MiniAccumuloCluster; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.apache.zookeeper.ClientCnxn; +import org.junit.After; +import org.junit.Before; +import org.junit.BeforeClass; + +/** + * Boilerplate code for a unit test that uses a {@link MiniAccumuloCluster}. + * <p> + * It uses the same instance of {@link MiniAccumuloCluster} and just clears out + * any tables that were added between tests. + */ +public class AccumuloITBase { + + // Managed the MiniAccumuloCluster + private MiniAccumuloClusterInstance cluster = null; + + @BeforeClass + public static void killLoudLogs() { + Logger.getLogger(ClientCnxn.class).setLevel(Level.ERROR); + } + + @Before + public void initCluster() throws IOException, InterruptedException, AccumuloException, AccumuloSecurityException { + cluster = new MiniAccumuloClusterInstance(); + cluster.startMiniAccumulo(); + } + + + @After + public void tearDownCluster() throws IOException, InterruptedException { + cluster.stopMiniAccumulo(); + } + + /** + * @return The {@link MiniAccumuloClusterInstance} used by the tests. + */ + public MiniAccumuloClusterInstance getClusterInstance() { + return cluster; + } + + /** + * @return The root username. + */ + public String getUsername() { + return cluster.getUsername(); + } + + /** + * @return The root password. + */ + public String getPassword() { + return cluster.getPassword(); + } + + /** + * @return The MiniAccumulo's zookeeper instance name. + */ + public String getInstanceName() { + return cluster.getInstanceName(); + } + + /** + * @return The MiniAccumulo's zookeepers. + */ + public String getZookeepers() { + return cluster.getZookeepers(); + } + + /** + * TODO doc + * + * @return + * @throws AccumuloSecurityException + * @throws AccumuloException + */ + public Connector getConnector() throws AccumuloException, AccumuloSecurityException { + return cluster.getConnector(); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-rya/blob/fcc98bd9/dao/accumulo.rya/src/test/java/mvm/rya/accumulo/AccumuloRyaITBase.java ---------------------------------------------------------------------- diff --git a/dao/accumulo.rya/src/test/java/mvm/rya/accumulo/AccumuloRyaITBase.java b/dao/accumulo.rya/src/test/java/mvm/rya/accumulo/AccumuloRyaITBase.java new file mode 100644 index 0000000..dea227b --- /dev/null +++ b/dao/accumulo.rya/src/test/java/mvm/rya/accumulo/AccumuloRyaITBase.java @@ -0,0 +1,109 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 mvm.rya.accumulo; + +import java.io.IOException; +import java.util.Date; +import java.util.concurrent.atomic.AtomicInteger; + +import org.apache.accumulo.core.client.AccumuloException; +import org.apache.accumulo.core.client.AccumuloSecurityException; +import org.apache.accumulo.core.client.TableNotFoundException; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; + +import com.google.common.base.Optional; + +import mvm.rya.accumulo.instance.AccumuloRyaInstanceDetailsRepository; +import mvm.rya.api.instance.RyaDetails; +import mvm.rya.api.instance.RyaDetails.EntityCentricIndexDetails; +import mvm.rya.api.instance.RyaDetails.FreeTextIndexDetails; +import mvm.rya.api.instance.RyaDetails.GeoIndexDetails; +import mvm.rya.api.instance.RyaDetails.JoinSelectivityDetails; +import mvm.rya.api.instance.RyaDetails.PCJIndexDetails; +import mvm.rya.api.instance.RyaDetails.ProspectorDetails; +import mvm.rya.api.instance.RyaDetails.TemporalIndexDetails; +import mvm.rya.api.instance.RyaDetailsRepository; +import mvm.rya.api.instance.RyaDetailsRepository.AlreadyInitializedException; +import mvm.rya.api.instance.RyaDetailsRepository.RyaDetailsRepositoryException; + +/** + * Contains boilerplate code for spinning up a Mini Accumulo Cluster and initializing + * some of the Rya stuff. We can not actually initialize an instance of Rya here + * because Sail is not available to us. + */ +public class AccumuloRyaITBase { + + // Managed the MiniAccumuloCluster + private static final MiniAccumuloClusterInstance cluster = new MiniAccumuloClusterInstance(); + + // Manage the Rya instances that are hosted on the cluster + protected static final AtomicInteger ryaInstanceNameCounter = new AtomicInteger(1); + private String ryaInstanceName; + + @BeforeClass + public static void initCluster() throws IOException, InterruptedException, AccumuloException, AccumuloSecurityException { + cluster.startMiniAccumulo(); + } + + @Before + public void prepareForNextTest() throws AccumuloException, AccumuloSecurityException, TableNotFoundException, AlreadyInitializedException, RyaDetailsRepositoryException { + // Get the next Rya instance name. + ryaInstanceName = "testInstance" + ryaInstanceNameCounter.getAndIncrement() + "_"; + + // Create Rya Details for the instance name. + final RyaDetailsRepository detailsRepo = new AccumuloRyaInstanceDetailsRepository(cluster.getConnector(), ryaInstanceName); + + final RyaDetails details = RyaDetails.builder() + .setRyaInstanceName(ryaInstanceName) + .setRyaVersion("0.0.0.0") + .setFreeTextDetails( new FreeTextIndexDetails(true) ) + .setEntityCentricIndexDetails( new EntityCentricIndexDetails(true) ) + .setGeoIndexDetails( new GeoIndexDetails(true) ) + .setTemporalIndexDetails( new TemporalIndexDetails(true) ) + .setPCJIndexDetails( + PCJIndexDetails.builder() + .setEnabled(true) ) + .setJoinSelectivityDetails( new JoinSelectivityDetails( Optional.<Date>absent() ) ) + .setProspectorDetails( new ProspectorDetails( Optional.<Date>absent() )) + .build(); + + detailsRepo.initialize(details); + } + + @AfterClass + public static void tearDownCluster() throws IOException, InterruptedException { + cluster.stopMiniAccumulo(); + } + + /** + * @return The {@link MiniAccumuloClusterInstance} used by the tests. + */ + public MiniAccumuloClusterInstance getClusterInstance() { + return cluster; + } + + /** + * @return The name of the Rya instance that is being used for the current test. + */ + public String getRyaInstanceName() { + return ryaInstanceName; + } +} \ No newline at end of file
