diff --git a/solr/core/src/java/org/apache/solr/handler/CollectionsAPI.java b/solr/core/src/java/org/apache/solr/handler/CollectionsAPI.java index df45b4a636c4..56fa9cfe059d 100644 --- a/solr/core/src/java/org/apache/solr/handler/CollectionsAPI.java +++ b/solr/core/src/java/org/apache/solr/handler/CollectionsAPI.java @@ -102,8 +102,8 @@ public void restoreBackup(PayloadObj obj) throws Excep final Map v1Params = v2Body.toMap(new HashMap<>()); v1Params.put(ACTION, CollectionAction.RESTORE.toLower()); - if (v2Body.createCollectionParams != null && !v2Body.createCollectionParams.isEmpty()) { - final Map createCollParams = (Map) v1Params.remove(V2ApiConstants.CREATE_COLLECTION_KEY); + if (v2Body.createCollectionParams != null) { + final Map createCollParams = v2Body.createCollectionParams.toMap(new HashMap<>()); convertV2CreateCollectionMapToV1ParamMap(createCollParams); v1Params.putAll(createCollParams); } diff --git a/solr/core/src/test/org/apache/solr/cloud/api/collections/ShardSplitTest.java b/solr/core/src/test/org/apache/solr/cloud/api/collections/ShardSplitTest.java index ad07a356c4e3..ad655e9c0b88 100644 --- a/solr/core/src/test/org/apache/solr/cloud/api/collections/ShardSplitTest.java +++ b/solr/core/src/test/org/apache/solr/cloud/api/collections/ShardSplitTest.java @@ -633,8 +633,7 @@ private void doSplitShardWithRule(SolrIndexSplitter.SplitMethod splitMethod) thr log.info("Starting testSplitShardWithRule"); String collectionName = "shardSplitWithRule_" + splitMethod.toLower(); - CollectionAdminRequest.Create createRequest = CollectionAdminRequest.createCollection(collectionName, "conf1", 1, 2) - .setRule("shard:*,replica:<2,node:*"); + CollectionAdminRequest.Create createRequest = CollectionAdminRequest.createCollection(collectionName, "conf1", 1, 2); CollectionAdminResponse response = createRequest.process(cloudClient); assertEquals(0, response.getStatus()); diff --git a/solr/core/src/test/org/apache/solr/handler/admin/V2CollectionsAPIMappingTest.java b/solr/core/src/test/org/apache/solr/handler/admin/V2CollectionsAPIMappingTest.java index 689073c9ca3c..f6d6eda17871 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/V2CollectionsAPIMappingTest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/V2CollectionsAPIMappingTest.java @@ -216,6 +216,7 @@ public void testBackupAllProperties() throws Exception { "'indexBackup': 'copy-files', " + "'commitName': 'someSnapshotName', " + "'incremental': true, " + + "'maxNumBackupPoints': 3, " + "'async': 'requestTrackingId' " + "}}"); @@ -228,6 +229,7 @@ public void testBackupAllProperties() throws Exception { assertEquals("copy-files", v1Params.get(CollectionAdminParams.INDEX_BACKUP_STRATEGY)); assertEquals("someSnapshotName", v1Params.get(CoreAdminParams.COMMIT_NAME)); assertEquals(true, v1Params.getPrimitiveBool(CoreAdminParams.BACKUP_INCREMENTAL)); + assertEquals(3, v1Params.getPrimitiveInt(CoreAdminParams.MAX_NUM_BACKUP_POINTS)); assertEquals("requestTrackingId", v1Params.get(CommonAdminParams.ASYNC)); } @@ -242,7 +244,6 @@ public void testRestoreAllProperties() throws Exception { "'backupId': 123, " + "'async': 'requestTrackingId', " + "'create-collection': {" + - " 'numShards': 1, " + " 'properties': {'foo': 'bar', 'foo2': 'bar2'}, " + " 'replicationFactor': 3 " + "}" + @@ -257,10 +258,9 @@ public void testRestoreAllProperties() throws Exception { assertEquals("requestTrackingId", v1Params.get(CommonAdminParams.ASYNC)); // NOTE: Unlike other v2 APIs that have a nested object for collection-creation params, restore's v1 equivalent // for these properties doesn't have a "create-collection." prefix. - assertEquals(1, v1Params.getPrimitiveInt(CollectionAdminParams.NUM_SHARDS)); + assertEquals(3, v1Params.getPrimitiveInt(ZkStateReader.REPLICATION_FACTOR)); assertEquals("bar", v1Params.get("property.foo")); assertEquals("bar2", v1Params.get("property.foo2")); - assertEquals(3, v1Params.getPrimitiveInt(ZkStateReader.REPLICATION_FACTOR)); } private SolrParams captureConvertedV1Params(String path, String method, String v2RequestBody) throws Exception { diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java b/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java index 7d1f977f24db..c6741d79c3a7 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java @@ -21,8 +21,14 @@ import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.SolrResponse; import org.apache.solr.client.solrj.SolrServerException; +import org.apache.solr.client.solrj.request.beans.BackupCollectionPayload; +import org.apache.solr.client.solrj.request.beans.CreateAliasPayload; +import org.apache.solr.client.solrj.request.beans.CreatePayload; +import org.apache.solr.client.solrj.request.beans.DeleteAliasPayload; import org.apache.solr.client.solrj.request.beans.DeleteBackupPayload; import org.apache.solr.client.solrj.request.beans.ListBackupPayload; +import org.apache.solr.client.solrj.request.beans.RestoreCollectionPayload; +import org.apache.solr.client.solrj.request.beans.SetAliasPropertyPayload; import org.apache.solr.client.solrj.response.CollectionAdminResponse; import org.apache.solr.client.solrj.response.RequestStatusState; import org.apache.solr.client.solrj.util.SolrIdentifierValidator; @@ -95,12 +101,37 @@ public SolrParams getParams() { return params; } + protected Properties convertToProperties(Map propMap) { + final Properties properties = new Properties(); + for (Map.Entry entry : propMap.entrySet()) { + properties.put(entry.getKey(), entry.getValue()); + } + + return properties; + } + + protected Map convertToMap(Properties properties) { + final Map propMap = new HashMap<>(); + for (String propertyName : properties.stringPropertyNames()) { + propMap.put(propertyName, properties.getProperty(propertyName)); + } + + return propMap; + } + protected void addProperties(ModifiableSolrParams params, Properties props) { for (String propertyName : props.stringPropertyNames()) { params.set(PROPERTY_PREFIX + propertyName, props.getProperty(propertyName)); } } + protected void addProperties(ModifiableSolrParams params, Map propMap) { + if (propMap == null || propMap.isEmpty()) + for (String propertyName : propMap.keySet()) { + params.set(PROPERTY_PREFIX + propertyName, propMap.get(propertyName).toString()); + } + } + @Override public void writeMap(EntryWriter ew) throws IOException { ew.put("class", this.getClass().getName()); @@ -408,21 +439,7 @@ public static Modify modifyCollection(String collection, Map pro // CREATE request public static class Create extends AsyncCollectionSpecificAdminRequest { - protected String configName = null; - protected String createNodeSet = null; - protected String routerName; - protected String policy; - protected String shards; - protected String routerField; - protected Integer numShards; - protected Integer nrtReplicas; - protected Integer pullReplicas; - protected Integer tlogReplicas; - protected Boolean perReplicaState; - - protected Properties properties; - protected String alias; - protected String[] rule , snitch; + protected final CreatePayload createParams; /** Constructor intended for typical use cases */ protected Create(String collection, String config, Integer numShards, Integer numNrtReplicas, Integer numTlogReplicas, Integer numPullReplicas) { // TODO: maybe add other constructors @@ -440,43 +457,49 @@ private Create(String collection, String config, String routerName, Integer numS if ((null != shards) && (null != numShards)) { throw new IllegalArgumentException("Can not specify both a numShards and a list of shards"); } - this.configName = config; - this.routerName = routerName; - this.numShards = numShards; - this.setShards(shards); - this.nrtReplicas = numNrtReplicas; - this.tlogReplicas = numTlogReplicas; - this.pullReplicas = numPullReplicas; - } - - public Create setCreateNodeSet(String nodeSet) { this.createNodeSet = nodeSet; return this; } - public Create setRouterName(String routerName) { this.routerName = routerName; return this; } - public Create setRouterField(String routerField) { this.routerField = routerField; return this; } - public Create setNrtReplicas(Integer nrtReplicas) { this.nrtReplicas = nrtReplicas; return this;} - public Create setTlogReplicas(Integer tlogReplicas) { this.tlogReplicas = tlogReplicas; return this;} - public Create setPullReplicas(Integer pullReplicas) { this.pullReplicas = pullReplicas; return this;} - public Create setReplicationFactor(Integer repl) { this.nrtReplicas = repl; return this; } - public Create setRule(String... s){ this.rule = s; return this; } - public Create setSnitch(String... s){ this.snitch = s; return this; } - public Create setPerReplicaState(Boolean b) {this.perReplicaState = b; return this; } + this.createParams = new CreatePayload(); + this.createParams.name = collection; + this.createParams.config = config; + this.createParams.numShards = numShards; + this.createParams.nrtReplicas = numNrtReplicas; + this.createParams.tlogReplicas = numTlogReplicas; + this.createParams.pullReplicas = numPullReplicas; + setRouterName(routerName); + setShards(shards); + } - public Create setAlias(String alias) { - this.alias = alias; + public Create setCreateNodeSet(String nodeSet) { this.createParams.nodeSet = Arrays.asList(nodeSet.split(",")); return this; } + public Create setNrtReplicas(Integer nrtReplicas) { this.createParams.nrtReplicas = nrtReplicas; return this;} + public Create setTlogReplicas(Integer tlogReplicas) { this.createParams.tlogReplicas = tlogReplicas; return this;} + public Create setPullReplicas(Integer pullReplicas) { this.createParams.pullReplicas = pullReplicas; return this;} + public Create setRouterName(String routerName) { + if (routerName != null) createParams.router.put(CommonParams.NAME, routerName); return this; } + public Create setRouterField(String routerField) { + if (routerField != null) createParams.router.put("field", routerField); + return this; + } + + public Create setReplicationFactor(Integer repl) { this.createParams.nrtReplicas = repl; return this; } + public Create setPerReplicaState(Boolean b) { createParams.perReplicaState = b; return this; } + + public Create setAlias(String alias) { createParams.alias = alias; return this; } + + public String getConfigName() { return createParams.config; } + public String getCreateNodeSet() { return (createParams.nodeSet == null) ? null : String.join(",", createParams.nodeSet); } + public String getRouterName() { return (String) createParams.router.get(CommonParams.NAME); } + public String getRouterField() { return (String) createParams.router.get("field"); } - public String getConfigName() { return configName; } - public String getCreateNodeSet() { return createNodeSet; } - public String getRouterName() { return routerName; } - public String getShards() { return shards; } - public Integer getNumShards() { return numShards; } + public String getShards() { return createParams.shards; } + public Integer getNumShards() { return createParams.numShards; } public Integer getReplicationFactor() { return getNumNrtReplicas(); } - public Integer getNumNrtReplicas() { return nrtReplicas; } - public Integer getNumTlogReplicas() {return tlogReplicas;} - public Integer getNumPullReplicas() {return pullReplicas;} - public Boolean getPerReplicaState() {return perReplicaState;} + public Integer getNumNrtReplicas() { return createParams.nrtReplicas; } + public Integer getNumTlogReplicas() {return createParams.tlogReplicas;} + public Integer getNumPullReplicas() {return createParams.pullReplicas;} + public Boolean getPerReplicaState() {return createParams.perReplicaState;} /** * Provide the name of the shards to be created, separated by commas @@ -486,34 +509,33 @@ public Create setAlias(String alias) { * @throws IllegalArgumentException if any of the shard names contain invalid characters. */ public Create setShards(String shards) { - if (null != shards) { + if (null == shards) { for (String shard : shards.split(",")) { SolrIdentifierValidator.validateShardName(shard); } } - this.shards = shards; + createParams.shards = shards; return this; } public Properties getProperties() { - return properties; + return convertToProperties(createParams.properties); } public Create setProperties(Properties properties) { - this.properties = properties; + createParams.properties = convertToMap(properties); return this; } public Create setProperties(Map properties) { - this.properties = new Properties(); - this.properties.putAll(properties); + properties.forEach((k, v) -> { + createParams.properties.put(k, v); + }); return this; } public Create withProperty(String key, String value) { - if (this.properties == null) - this.properties = new Properties(); - this.properties.setProperty(key, value); + createParams.properties.put(key, value); return this; } @@ -521,43 +543,23 @@ public Create withProperty(String key, String value) { public SolrParams getParams() { ModifiableSolrParams params = (ModifiableSolrParams) super.getParams(); - if (configName != null) - params.set("collection.configName", configName); - if (createNodeSet != null) - params.set(CREATE_NODE_SET_PARAM, createNodeSet); - if (numShards != null) { - params.set( ZkStateReader.NUM_SHARDS_PROP, numShards); - } - if (routerName != null) - params.set( "router.name", routerName); - if (shards != null) - params.set("shards", shards); - if (routerField != null) { - params.set("router.field", routerField); - } - if (nrtReplicas != null) { - params.set( ZkStateReader.NRT_REPLICAS, nrtReplicas); - } - if (properties != null) { - addProperties(params, properties); - } - if (pullReplicas != null) { - params.set(ZkStateReader.PULL_REPLICAS, pullReplicas); - } - if (tlogReplicas != null) { - params.set(ZkStateReader.TLOG_REPLICAS, tlogReplicas); + // Collection name handled by parent class, all other params are optional. + params.setNonNull(COLL_CONF, createParams.config); + params.setNonNull(ZkStateReader.NUM_SHARDS_PROP, createParams.numShards); + params.setNonNull(ZkStateReader.NRT_REPLICAS, createParams.nrtReplicas); + params.setNonNull(ZkStateReader.PULL_REPLICAS, createParams.pullReplicas); + params.setNonNull(ZkStateReader.TLOG_REPLICAS, createParams.tlogReplicas); + params.setNonNull(CREATE_NODE_SET_PARAM, getCreateNodeSet()); + params.setNonNull("shards", createParams.shards); + params.setNonNull("router.name", getRouterName()); + params.setNonNull("router.field", getRouterField()); + params.setNonNull(ALIAS, createParams.alias); + addProperties(params, createParams.properties); + if(Boolean.TRUE.equals(createParams.perReplicaState)) { + params.set(PER_REPLICA_STATE, createParams.perReplicaState); } - if(Boolean.TRUE.equals(perReplicaState)) { - params.set(PER_REPLICA_STATE, perReplicaState); - } - params.setNonNull(ALIAS, alias); return params; } - - public Create setPolicy(String policy) { - this.policy = policy; - return this; - } } /** @@ -961,53 +963,49 @@ public static Backup backupCollection(String collection, String backupName) { // BACKUP request public static class Backup extends AsyncCollectionSpecificAdminRequest { - protected final String name; - protected Optional repositoryName = Optional.empty(); - protected String location; - protected Optional commitName = Optional.empty(); - protected Optional indexBackupStrategy = Optional.empty(); - protected boolean incremental = true; - protected Optional maxNumBackupPoints = Optional.empty(); + protected final BackupCollectionPayload backupParams; public Backup(String collection, String name) { super(CollectionAction.BACKUP, collection); - this.name = name; - this.repositoryName = Optional.empty(); + + this.backupParams = new BackupCollectionPayload(); + this.backupParams.collection = collection; + this.backupParams.name = name; } public String getLocation() { - return location; + return backupParams.location; } public Backup setLocation(String location) { - this.location = location; + this.backupParams.location = location; return this; } public Optional getRepositoryName() { - return repositoryName; + return Optional.ofNullable(backupParams.repository); } public Backup setRepositoryName(String repositoryName) { - this.repositoryName = Optional.ofNullable(repositoryName); + this.backupParams.repository = repositoryName; return this; } public Optional getCommitName() { - return commitName; + return Optional.ofNullable(this.backupParams.commitName); } public Backup setCommitName(String commitName) { - this.commitName = Optional.ofNullable(commitName); + this.backupParams.commitName = commitName; return this; } public Optional getIndexBackupStrategy() { - return indexBackupStrategy; + return Optional.ofNullable(this.backupParams.indexBackup); } public Backup setIndexBackupStrategy(String indexBackupStrategy) { - this.indexBackupStrategy = Optional.ofNullable(indexBackupStrategy); + this.backupParams.indexBackup = indexBackupStrategy; return this; } @@ -1025,7 +1023,7 @@ public Backup setIndexBackupStrategy(String indexBackupStrategy) { */ @Deprecated public Backup setIncremental(boolean incremental) { - this.incremental = incremental; + this.backupParams.incremental = incremental; return this; } @@ -1039,29 +1037,21 @@ public Backup setIncremental(boolean incremental) { * @param maxNumBackupPoints the number of backup points to retain after the current backup */ public Backup setMaxNumberBackupPoints(int maxNumBackupPoints) { - this.maxNumBackupPoints = Optional.of(maxNumBackupPoints); + this.backupParams.maxNumBackupPoints = maxNumBackupPoints; return this; } @Override public SolrParams getParams() { ModifiableSolrParams params = (ModifiableSolrParams) super.getParams(); - params.set(CoreAdminParams.COLLECTION, collection); - params.set(CoreAdminParams.NAME, name); - params.set(CoreAdminParams.BACKUP_LOCATION, location); //note: optional - if (repositoryName.isPresent()) { - params.set(CoreAdminParams.BACKUP_REPOSITORY, repositoryName.get()); - } - if (commitName.isPresent()) { - params.set(CoreAdminParams.COMMIT_NAME, commitName.get()); - } - if (indexBackupStrategy.isPresent()) { - params.set(CollectionAdminParams.INDEX_BACKUP_STRATEGY, indexBackupStrategy.get()); - } - if (maxNumBackupPoints.isPresent()) { - params.set(CoreAdminParams.MAX_NUM_BACKUP_POINTS, maxNumBackupPoints.get()); - } - params.set(CoreAdminParams.BACKUP_INCREMENTAL, incremental); + params.set(CoreAdminParams.COLLECTION, backupParams.collection); + params.set(CoreAdminParams.NAME, backupParams.name); + params.setNonNull(CoreAdminParams.BACKUP_LOCATION, backupParams.location); + params.setNonNull(CoreAdminParams.BACKUP_REPOSITORY, backupParams.repository); + params.setNonNull(CoreAdminParams.COMMIT_NAME, backupParams.commitName); + params.setNonNull(CollectionAdminParams.INDEX_BACKUP_STRATEGY, backupParams.indexBackup); + params.setNonNull(CoreAdminParams.BACKUP_INCREMENTAL, backupParams.incremental); + params.setNonNull(CoreAdminParams.MAX_NUM_BACKUP_POINTS, backupParams.maxNumBackupPoints); return params; } @@ -1073,94 +1063,75 @@ public static Restore restoreCollection(String collection, String backupName) { // RESTORE request public static class Restore extends AsyncCollectionSpecificAdminRequest { - protected final String backupName; - protected Optional repositoryName = Optional.empty(); - protected String location; + protected final RestoreCollectionPayload restoreParams; // in common with collection creation: - protected String configName; - protected Integer replicationFactor; - protected Integer nrtReplicas; - protected Integer tlogReplicas; - protected Integer pullReplicas; - protected Optional createNodeSet = Optional.empty(); - protected Optional createNodeSetShuffle = Optional.empty(); - protected Properties properties; protected Integer backupId; public Restore(String collection, String backupName) { super(CollectionAction.RESTORE, collection); - this.backupName = backupName; - } - - public String getLocation() { - return location; - } - public Restore setLocation(String location) { - this.location = location; - return this; + restoreParams = new RestoreCollectionPayload(); + restoreParams.collection = collection; + restoreParams.name = backupName; } - public Optional getRepositoryName() { - return repositoryName; - } + public String getLocation() { return this.restoreParams.location; } + public Restore setLocation(String location) { this.restoreParams.location = location; return this; } - public Restore setRepositoryName(String repositoryName) { - this.repositoryName = Optional.ofNullable(repositoryName); - return this; - } + public Optional getRepositoryName() { return Optional.ofNullable(this.restoreParams.repository); } + public Restore setRepositoryName(String repositoryName) { this.restoreParams.repository = repositoryName; return this; } - public void setCreateNodeSet(String createNodeSet) { - this.createNodeSet = Optional.of(createNodeSet); - } + /** + * Specify the ID of the backup-point to restore from. + * + * '-1' is used by default to have Solr restore from the most recent backup-point. + * + * Solr can store multiple backup points for a given collection - each identified by a unique backup ID. Users who + * want to restore a particular backup-point can specify it using this method. + * + * @param backupId the ID of the backup-point to restore from + */ + public Restore setBackupId(int backupId) { restoreParams.backupId = backupId; return this; } + public Integer getBackupId() { return restoreParams.backupId; } - public Optional getCreateNodeSet() { - return createNodeSet; - } + // Collection creation params in common: + public Restore setConfigName(String config) { this.restoreParams.createCollectionParams.config = config; return this; } + public String getConfigName() { return restoreParams.createCollectionParams.config; } - public Optional getCreateNodeSetShuffle() { - return createNodeSetShuffle; - } + public Integer getReplicationFactor() { return restoreParams.createCollectionParams.replicationFactor; } + public Restore setReplicationFactor(Integer replicationFactor) { restoreParams.createCollectionParams.replicationFactor = replicationFactor; return this; } - public void setCreateNodeSetShuffle(boolean createNodeSetShuffle) { - this.createNodeSetShuffle = Optional.of(createNodeSetShuffle); - } + public Integer getNrtReplicas() { return restoreParams.createCollectionParams.nrtReplicas; } + public Restore setNrtReplicas(Integer nrtReplicas) { restoreParams.createCollectionParams.nrtReplicas = nrtReplicas; return this; }; - // Collection creation params in common: - public Restore setConfigName(String config) { this.configName = config; return this; } - public String getConfigName() { return configName; } + public Integer getTlogReplicas() { return restoreParams.createCollectionParams.tlogReplicas; } + public Restore setTlogReplicas(Integer tlogReplicas) { restoreParams.createCollectionParams.tlogReplicas = tlogReplicas; return this; } - public Integer getReplicationFactor() { return replicationFactor; } - public Restore setReplicationFactor(Integer replicationFactor) { this.replicationFactor = replicationFactor; return this; } + public Integer getPullReplicas() { return restoreParams.createCollectionParams.pullReplicas; } + public Restore setPullReplicas(Integer pullReplicas) { restoreParams.createCollectionParams.pullReplicas = pullReplicas; return this; } - public Integer getNrtReplicas() { return nrtReplicas; } - public Restore setNrtReplicas(Integer nrtReplicas) { this.nrtReplicas= nrtReplicas; return this; }; + public Properties getProperties() { return convertToProperties(restoreParams.createCollectionParams.properties); } + public Restore setProperties(Properties properties) { restoreParams.createCollectionParams.properties = convertToMap(properties); return this; } - public Integer getTlogReplicas() { return tlogReplicas; } - public Restore setTlogReplicas(Integer tlogReplicas) { this.tlogReplicas = tlogReplicas; return this; } + public void setCreateNodeSet(String createNodeSet) { + if (createNodeSet != null) { + this.restoreParams.createCollectionParams.nodeSet = Arrays.asList(createNodeSet.split(",")); + } + } - public Integer getPullReplicas() { return pullReplicas; } - public Restore setPullReplicas(Integer pullReplicas) { this.pullReplicas = pullReplicas; return this; } + public Optional getCreateNodeSet() { + final String combinedString = (restoreParams.createCollectionParams.nodeSet == null) ? + null : String.join(",", restoreParams.createCollectionParams.nodeSet); + return Optional.ofNullable(combinedString); + } - public Properties getProperties() { - return properties; + public Optional getCreateNodeSetShuffle() { + return Optional.ofNullable(restoreParams.createCollectionParams.shuffleNodes); } - public Restore setProperties(Properties properties) { this.properties = properties; return this;} - /** - * Specify the ID of the backup-point to restore from. - * - * '-1' is used by default to have Solr restore from the most recent backup-point. - * - * Solr can store multiple backup points for a given collection - each identified by a unique backup ID. Users who - * want to restore a particular backup-point can specify it using this method. - * - * @param backupId the ID of the backup-point to restore from - */ - public Restore setBackupId(int backupId) { - this.backupId = backupId; - return this; + public void setCreateNodeSetShuffle(boolean createNodeSetShuffle) { + restoreParams.createCollectionParams.shuffleNodes = createNodeSetShuffle; } // TODO support rule, snitch @@ -1168,41 +1139,27 @@ public Restore setBackupId(int backupId) { @Override public SolrParams getParams() { ModifiableSolrParams params = (ModifiableSolrParams) super.getParams(); - params.set(CoreAdminParams.COLLECTION, collection); - params.set(CoreAdminParams.NAME, backupName); - params.set(CoreAdminParams.BACKUP_LOCATION, location); //note: optional - params.set("collection.configName", configName); //note: optional - if (replicationFactor != null && nrtReplicas != null) { + params.set(CoreAdminParams.COLLECTION, this.restoreParams.collection); + params.set(CoreAdminParams.NAME, this.restoreParams.name); + params.setNonNull(CoreAdminParams.BACKUP_LOCATION, this.restoreParams.location); + params.setNonNull(CoreAdminParams.BACKUP_REPOSITORY, restoreParams.repository); + params.setNonNull(CoreAdminParams.BACKUP_ID, restoreParams.backupId); + + // Collection-creation parameters + params.setNonNull(COLL_CONF, restoreParams.createCollectionParams.config); + if (restoreParams.createCollectionParams.replicationFactor != null && restoreParams.createCollectionParams.nrtReplicas != null) { throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Cannot set both replicationFactor and nrtReplicas as they mean the same thing"); } - if (replicationFactor != null) { - params.set(ZkStateReader.REPLICATION_FACTOR, replicationFactor); - } - if (nrtReplicas != null) { - params.set(ZkStateReader.NRT_REPLICAS, nrtReplicas); - } - if (pullReplicas != null) { - params.set(ZkStateReader.PULL_REPLICAS, pullReplicas); - } - if (tlogReplicas != null) { - params.set(ZkStateReader.TLOG_REPLICAS, tlogReplicas); - } - if (properties != null) { - addProperties(params, properties); - } - if (repositoryName.isPresent()) { - params.set(CoreAdminParams.BACKUP_REPOSITORY, repositoryName.get()); - } - if (createNodeSet.isPresent()) { - params.set(CREATE_NODE_SET_PARAM, createNodeSet.get()); - } - if (createNodeSetShuffle.isPresent()) { - params.set(CREATE_NODE_SET_SHUFFLE_PARAM, createNodeSetShuffle.get()); - } - if (backupId != null) { - params.set(CoreAdminParams.BACKUP_ID, backupId); + params.setNonNull(REPLICATION_FACTOR, restoreParams.createCollectionParams.replicationFactor); + params.setNonNull(NRT_REPLICAS, restoreParams.createCollectionParams.nrtReplicas); + params.setNonNull(PULL_REPLICAS, restoreParams.createCollectionParams.pullReplicas); + params.setNonNull(TLOG_REPLICAS, restoreParams.createCollectionParams.tlogReplicas); + params.setNonNull(CREATE_NODE_SET_SHUFFLE_PARAM, restoreParams.createCollectionParams.shuffleNodes); + if (getCreateNodeSet().isPresent()) { + params.setNonNull(CREATE_NODE_SET_PARAM, getCreateNodeSet().get()); } + addProperties(params, restoreParams.createCollectionParams.properties); return params; } @@ -1669,24 +1626,25 @@ public static SetAliasProperty setAliasProperty(String aliasName) { public static class SetAliasProperty extends AsyncCollectionAdminRequest { - private final String aliasName; - private Map properties = new HashMap<>(); + private final SetAliasPropertyPayload setAliasPropertyParams; public SetAliasProperty(String aliasName) { super(CollectionAction.ALIASPROP); - this.aliasName = SolrIdentifierValidator.validateAliasName(aliasName); + + this.setAliasPropertyParams = new SetAliasPropertyPayload(); + this.setAliasPropertyParams.name = SolrIdentifierValidator.validateAliasName(aliasName); } public SetAliasProperty addProperty(String key, String value) { - properties.put(key,value); + setAliasPropertyParams.properties.put(key, value); return this; } @Override public SolrParams getParams() { ModifiableSolrParams params = (ModifiableSolrParams) super.getParams(); - params.set(CoreAdminParams.NAME, aliasName); - properties.forEach((key, value) -> params.set("property." + key, value)); + params.set(CoreAdminParams.NAME, setAliasPropertyParams.name); + setAliasPropertyParams.properties.forEach((key, value) -> params.set("property." + key, value.toString())); return params; } } @@ -1703,28 +1661,33 @@ public static CreateAlias createAlias(String aliasName, String aliasedCollection // CREATEALIAS request public static class CreateAlias extends AsyncCollectionAdminRequest { + protected final CreateAliasPayload aliasParams; protected String aliasName; protected String aliasedCollections; private CreateAlias(String aliasName, String aliasedCollections) { super(CollectionAction.CREATEALIAS); - this.aliasName = SolrIdentifierValidator.validateAliasName(aliasName); - this.aliasedCollections = checkNotNull("aliasedCollections",aliasedCollections); + + aliasParams = new CreateAliasPayload(); + aliasParams.name = SolrIdentifierValidator.validateAliasName(aliasName); + + checkNotNull("aliasedCollections",aliasedCollections); + aliasParams.collections = Arrays.asList(aliasedCollections.split(",")); } public String getAliasName() { - return aliasName; + return aliasParams.name; } public String getAliasedCollections() { - return this.aliasedCollections; + return String.join(",", aliasParams.collections); } @Override public SolrParams getParams() { ModifiableSolrParams params = (ModifiableSolrParams) super.getParams(); - params.set(CoreAdminParams.NAME, aliasName); - params.set("collections", aliasedCollections); + params.set(CoreAdminParams.NAME, aliasParams.name); + params.set("collections", getAliasedCollections()); return params; } @@ -1759,71 +1722,61 @@ public static class CreateTimeRoutedAlias extends AsyncCollectionAdminRequest im public static final String ROUTER_PREEMPTIVE_CREATE_WINDOW = "router.preemptiveCreateMath"; public static final String ROUTER_AUTO_DELETE_AGE = "router.autoDeleteAge"; - private final String aliasName; - private final String routerField; - private final String start; - private final String interval; - //Optional: - private TimeZone tz; - private Integer maxFutureMs; - private String preemptiveCreateMath; - private String autoDeleteAge; - - private final Create createCollTemplate; + protected final CreateAliasPayload aliasParams; + protected final Create createCollTemplate; public CreateTimeRoutedAlias(String aliasName, String routerField, String start, String interval, Create createCollTemplate) { super(CollectionAction.CREATEALIAS); - this.aliasName = aliasName; - this.start = start; - this.interval = interval; - this.routerField = routerField; + aliasParams = new CreateAliasPayload(); + + aliasParams.name = aliasName; + aliasParams.router.start = start; + aliasParams.router.interval = interval; + aliasParams.router.field = routerField; + this.createCollTemplate = createCollTemplate; } /** Sets the timezone for interpreting any Solr "date math. */ public CreateTimeRoutedAlias setTimeZone(TimeZone tz) { - this.tz = tz; + aliasParams.tz = tz.getID(); return this; } /** Sets how long into the future (millis) that we will allow a document to pass. */ public CreateTimeRoutedAlias setMaxFutureMs(Integer maxFutureMs) { - this.maxFutureMs = maxFutureMs; + aliasParams.router.maxFutureMs = maxFutureMs; return this; } public CreateTimeRoutedAlias setPreemptiveCreateWindow(String preemptiveCreateMath) { - this.preemptiveCreateMath = preemptiveCreateMath; + aliasParams.router.preemptiveCreateMath = preemptiveCreateMath; return this; } public CreateTimeRoutedAlias setAutoDeleteAge(String autoDeleteAge) { - this.autoDeleteAge = autoDeleteAge; + aliasParams.router.autoDeleteAge = autoDeleteAge; return this; } @Override public SolrParams getParams() { ModifiableSolrParams params = (ModifiableSolrParams) super.getParams(); - params.add(CommonParams.NAME, aliasName); + + // Mandatory params + params.add(CommonParams.NAME, aliasParams.name); params.add(ROUTER_TYPE_NAME, "time"); - params.add(ROUTER_FIELD, routerField); - params.add(ROUTER_START, start); - params.add(ROUTER_INTERVAL, interval); - if (tz != null) { - params.add(CommonParams.TZ, tz.getID()); - } - if (maxFutureMs != null) { - params.add(ROUTER_MAX_FUTURE, ""+maxFutureMs); - } - if (preemptiveCreateMath != null) { - params.add(ROUTER_PREEMPTIVE_CREATE_WINDOW, preemptiveCreateMath); - } - if (autoDeleteAge != null) { - params.add(ROUTER_AUTO_DELETE_AGE, autoDeleteAge); - } + params.add(ROUTER_FIELD, aliasParams.router.field); + params.add(ROUTER_START, aliasParams.router.start); + params.add(ROUTER_INTERVAL, aliasParams.router.interval); - // merge the above with collectionParams. Above takes precedence. + // Optional params + params.setNonNull(CommonParams.TZ, aliasParams.tz); + params.setNonNull(ROUTER_MAX_FUTURE, aliasParams.router.maxFutureMs); + params.setNonNull(ROUTER_PREEMPTIVE_CREATE_WINDOW, aliasParams.router.preemptiveCreateMath); + params.setNonNull(ROUTER_AUTO_DELETE_AGE, aliasParams.router.autoDeleteAge); + + // Collection-creation template params (values above take precedence where overlap occurs) ModifiableSolrParams createCollParams = mergeCollParams(createCollTemplate); return SolrParams.wrapDefaults(params, createCollParams); } @@ -1835,12 +1788,13 @@ public RoutedAliasTypes getType() { @Override public String getRouterField() { - return routerField; + return aliasParams.router.field; } @Override public java.util.List getParamNames() { - return java.util.List.of(ROUTER_TYPE_NAME, ROUTER_FIELD, ROUTER_START, ROUTER_INTERVAL,ROUTER_MAX_FUTURE, ROUTER_PREEMPTIVE_CREATE_WINDOW, ROUTER_AUTO_DELETE_AGE, CommonParams.TZ); + return java.util.List.of(ROUTER_TYPE_NAME, ROUTER_FIELD, ROUTER_START, ROUTER_INTERVAL,ROUTER_MAX_FUTURE, + ROUTER_PREEMPTIVE_CREATE_WINDOW, ROUTER_AUTO_DELETE_AGE, CommonParams.TZ); } @Override @@ -1869,37 +1823,35 @@ public static class CreateCategoryRoutedAlias extends AsyncCollectionAdminReques public static final String ROUTER_MAX_CARDINALITY = "router.maxCardinality"; public static final String ROUTER_MUST_MATCH = "router.mustMatch"; - private final String aliasName; - private final String routerField; - private Integer maxCardinality; + private final CreateAliasPayload aliasParams; private String mustMatch; private final Create createCollTemplate; public CreateCategoryRoutedAlias(String aliasName, String routerField, int maxCardinality, Create createCollTemplate) { super(CollectionAction.CREATEALIAS); - this.aliasName = aliasName; - this.routerField = routerField; - this.maxCardinality = maxCardinality; + + aliasParams = new CreateAliasPayload(); + aliasParams.name = aliasName; + aliasParams.router.field = routerField; + aliasParams.router.maxCardinality = maxCardinality; this.createCollTemplate = createCollTemplate; } public CreateCategoryRoutedAlias setMustMatch(String regex) { - this.mustMatch = regex; + aliasParams.router.mustMatch = regex; return this; } @Override public SolrParams getParams() { ModifiableSolrParams params = (ModifiableSolrParams) super.getParams(); - params.add(CommonParams.NAME, aliasName); + params.add(CommonParams.NAME, aliasParams.name); params.add(ROUTER_TYPE_NAME, RoutedAliasTypes.CATEGORY.name()); - params.add(ROUTER_FIELD, routerField); - params.add(ROUTER_MAX_CARDINALITY, maxCardinality.toString()); + params.add(ROUTER_FIELD, aliasParams.router.field); + params.add(ROUTER_MAX_CARDINALITY, aliasParams.router.maxCardinality.toString()); - if (mustMatch != null) { - params.add(ROUTER_MUST_MATCH, mustMatch); - } + params.setNonNull(ROUTER_MUST_MATCH, aliasParams.router.mustMatch); // merge the above with collectionParams. Above takes precedence. ModifiableSolrParams createCollParams = mergeCollParams(createCollTemplate); @@ -1913,7 +1865,7 @@ public RoutedAliasTypes getType() { @Override public String getRouterField() { - return routerField; + return aliasParams.router.field; } @Override @@ -2054,18 +2006,19 @@ public static DeleteAlias deleteAlias(String aliasName) { // DELETEALIAS request public static class DeleteAlias extends AsyncCollectionAdminRequest { - - protected String aliasName; + protected final DeleteAliasPayload deleteAliasParams; private DeleteAlias(String aliasName) { super(CollectionAction.DELETEALIAS); - this.aliasName = checkNotNull("aliasName",aliasName); + + this.deleteAliasParams = new DeleteAliasPayload(); + this.deleteAliasParams.name = checkNotNull("aliasName",aliasName); } @Override public SolrParams getParams() { ModifiableSolrParams params = new ModifiableSolrParams(super.getParams()); - params.set(CoreAdminParams.NAME, aliasName); + params.set(CoreAdminParams.NAME, deleteAliasParams.name); return params; } } diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/AsyncPayloadBase.java b/solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/AsyncPayloadBase.java new file mode 100644 index 000000000000..add22f0d2001 --- /dev/null +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/AsyncPayloadBase.java @@ -0,0 +1,26 @@ +/* + * 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 org.apache.solr.client.solrj.request.beans; + +import org.apache.solr.common.annotation.JsonProperty; +import org.apache.solr.common.util.ReflectMapWriter; + +public class AsyncPayloadBase implements ReflectMapWriter { + + @JsonProperty + public String async; +} diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/BackupCollectionPayload.java b/solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/BackupCollectionPayload.java index 5d5e7ce753e6..bb2b9103e970 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/BackupCollectionPayload.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/BackupCollectionPayload.java @@ -24,7 +24,7 @@ * * Analogous to the request parameters for v1 /admin/collections?action=BACKUP API. */ -public class BackupCollectionPayload implements ReflectMapWriter { +public class BackupCollectionPayload extends AsyncPayloadBase implements ReflectMapWriter { @JsonProperty(required = true) public String collection; @@ -50,5 +50,5 @@ public class BackupCollectionPayload implements ReflectMapWriter { public Boolean incremental; @JsonProperty - public String async; + public Integer maxNumBackupPoints; } diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/CommonCreateCollectionPayloadBase.java b/solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/CommonCreateCollectionPayloadBase.java new file mode 100644 index 000000000000..fc0f171ccccb --- /dev/null +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/CommonCreateCollectionPayloadBase.java @@ -0,0 +1,61 @@ +/* + * 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 org.apache.solr.client.solrj.request.beans; + +import org.apache.solr.common.annotation.JsonProperty; +import org.apache.solr.common.util.ReflectMapWriter; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Collection creation parameters shared by all APIs that create a collection. + * + * While collection creation has its own dedicated API it also occurs in the process of several other API commands (e.g. + * "restore-backup"). This class defines a base class with only these shared parameters to enable reuse. + */ +public class CommonCreateCollectionPayloadBase implements ReflectMapWriter { + + public CommonCreateCollectionPayloadBase() { + this.properties = new HashMap<>(); + } + + @JsonProperty + public String config; + + @JsonProperty + public Integer replicationFactor; + + @JsonProperty + public Integer nrtReplicas; + + @JsonProperty + public Integer tlogReplicas; + + @JsonProperty + public Integer pullReplicas; + + @JsonProperty + public List nodeSet; + + @JsonProperty + public Boolean shuffleNodes; + + @JsonProperty + public Map properties; +} diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/CreateAliasPayload.java b/solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/CreateAliasPayload.java index b84b49c0bfca..cce5a97c2570 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/CreateAliasPayload.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/CreateAliasPayload.java @@ -24,7 +24,12 @@ import static org.apache.solr.client.solrj.request.beans.V2ApiConstants.CREATE_COLLECTION_KEY; -public class CreateAliasPayload implements ReflectMapWriter { +public class CreateAliasPayload extends AsyncPayloadBase implements ReflectMapWriter { + + public CreateAliasPayload() { + this.router = new AliasRouter(); + } + @JsonProperty(required = true) public String name; @@ -40,9 +45,6 @@ public class CreateAliasPayload implements ReflectMapWriter { @JsonProperty(CREATE_COLLECTION_KEY) public Map createCollectionParams; - @JsonProperty - public String async; - public static class AliasRouter implements ReflectMapWriter { @JsonProperty(required = true) public String name; diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/CreatePayload.java b/solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/CreatePayload.java index 403af4d77e49..53fcf8b171e3 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/CreatePayload.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/CreatePayload.java @@ -19,16 +19,19 @@ import org.apache.solr.common.annotation.JsonProperty; import org.apache.solr.common.util.ReflectMapWriter; +import java.util.HashMap; import java.util.List; import java.util.Map; -public class CreatePayload implements ReflectMapWriter { +public class CreatePayload extends CommonCreateCollectionPayloadBase implements ReflectMapWriter { + public CreatePayload() { + super(); + this.router = new HashMap<>(); + } + @JsonProperty(required = true) public String name; - @JsonProperty - public String config; - @JsonProperty public Map router; @@ -38,27 +41,6 @@ public class CreatePayload implements ReflectMapWriter { @JsonProperty public String shards; - @JsonProperty - public Integer replicationFactor; - - @JsonProperty - public Integer nrtReplicas; - - @JsonProperty - public Integer tlogReplicas; - - @JsonProperty - public Integer pullReplicas; - - @JsonProperty - public List nodeSet; - - @JsonProperty - public Boolean shuffleNodes; - - @JsonProperty - public Map properties; - @JsonProperty public String async; @@ -67,4 +49,7 @@ public class CreatePayload implements ReflectMapWriter { @JsonProperty public Boolean perReplicaState; + + @JsonProperty + public String alias; } diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/RestoreCollectionPayload.java b/solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/RestoreCollectionPayload.java index 26348025dfac..af0aba881589 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/RestoreCollectionPayload.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/RestoreCollectionPayload.java @@ -28,7 +28,11 @@ * * Analogous to the request parameters for v1 /admin/collections?action=RESTORE API. */ -public class RestoreCollectionPayload implements ReflectMapWriter { +public class RestoreCollectionPayload extends AsyncPayloadBase implements ReflectMapWriter { + + public RestoreCollectionPayload() { + this.createCollectionParams = new CommonCreateCollectionPayloadBase(); + } @JsonProperty(required = true) public String collection; @@ -46,8 +50,5 @@ public class RestoreCollectionPayload implements ReflectMapWriter { public Integer backupId; @JsonProperty(CREATE_COLLECTION_KEY) - public Map createCollectionParams; - - @JsonProperty - public String async; + public CommonCreateCollectionPayloadBase createCollectionParams; } diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/SetAliasPropertyPayload.java b/solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/SetAliasPropertyPayload.java index c3c85858e947..0547970bf175 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/SetAliasPropertyPayload.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/request/beans/SetAliasPropertyPayload.java @@ -19,9 +19,15 @@ import org.apache.solr.common.annotation.JsonProperty; import org.apache.solr.common.util.ReflectMapWriter; +import java.util.HashMap; import java.util.Map; public class SetAliasPropertyPayload implements ReflectMapWriter { + + public SetAliasPropertyPayload() { + this.properties = new HashMap<>(); + } + @JsonProperty(required = true) public String name;