You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by is...@apache.org on 2017/02/12 13:18:31 UTC

[07/18] lucene-solr:jira/solr-5944: Updating branch by merging latest changes from master

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/resources/apispec/core.config.Params.Commands.json
----------------------------------------------------------------------
diff --git a/solr/core/src/resources/apispec/core.config.Params.Commands.json b/solr/core/src/resources/apispec/core.config.Params.Commands.json
new file mode 100644
index 0000000..474f1a6
--- /dev/null
+++ b/solr/core/src/resources/apispec/core.config.Params.Commands.json
@@ -0,0 +1,31 @@
+{
+  "documentation": "https://cwiki.apache.org/confluence/display/solr/Request+Parameters+API",
+  "description": "Create, update and delete request parameter sets (paramsets) to override or replace parameters defined in solrconfig.xml. Parameter sets are used with request handlers by setting the useParams attribute to the paramset name in the definition of the request handler or with individual requests to Solr. Parameter sets defined with this API are stored in a file params.json in ZooKeeper or on the filesystem when not using SolrCloud. Note this API does not directly update solrconfig.xml. ",
+  "methods": [
+    "POST"
+  ],
+  "url": {
+    "paths": [
+      "/config/params"
+    ]
+  },
+  "commands": {
+    "set:": {
+      "type":"object",
+      "description":"Add or overwrite one or more paramsets. Each paramset definition includes a paramset name, followed by key-value pairs of the parameter and value to be set.",
+      "additionalProperties": true
+    },
+    "unset": {
+      "type":"array",
+      "description": "Delete one or more paramsets.",
+      "items": {
+        "type": "string"
+      }
+    },
+    "update": {
+      "type":"object",
+      "description": "Update one or more paramsets. This command will attempt to merge an existing paramset with the new values. Each paramset definition includes a paramset name, followed by key-value pairs of the parameters and values to be updated.",
+      "additionalProperties": true
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/resources/apispec/core.config.Params.json
----------------------------------------------------------------------
diff --git a/solr/core/src/resources/apispec/core.config.Params.json b/solr/core/src/resources/apispec/core.config.Params.json
new file mode 100644
index 0000000..cff0350
--- /dev/null
+++ b/solr/core/src/resources/apispec/core.config.Params.json
@@ -0,0 +1,13 @@
+{
+  "documentation": "https://cwiki.apache.org/confluence/display/solr/Request+Parameters+API",
+  "description": "List all parameter sets (paramsets). Individual paramsets can be requested by paramset name.",
+  "methods": [
+    "GET"
+  ],
+  "url": {
+    "paths": [
+      "/config/params",
+      "/config/params/{params_set}"
+    ]
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/resources/apispec/core.config.json
----------------------------------------------------------------------
diff --git a/solr/core/src/resources/apispec/core.config.json b/solr/core/src/resources/apispec/core.config.json
new file mode 100644
index 0000000..2633fd9
--- /dev/null
+++ b/solr/core/src/resources/apispec/core.config.json
@@ -0,0 +1,18 @@
+{
+  "documentation": "https://cwiki.apache.org/confluence/display/solr/Config+API",
+  "description": "Gets the Solr configuration for a collection.",
+  "methods": [
+    "GET"
+  ],
+  "url": {
+    "paths": [
+      "/config",
+      "/config/overlay",
+      "/config/query",
+      "/config/jmx",
+      "/config/requestDispatcher",
+      "/config/znodeVersion",
+      "/config/{plugin}"
+    ]
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/resources/apispec/core.system.blob.json
----------------------------------------------------------------------
diff --git a/solr/core/src/resources/apispec/core.system.blob.json b/solr/core/src/resources/apispec/core.system.blob.json
new file mode 100644
index 0000000..96fedcf
--- /dev/null
+++ b/solr/core/src/resources/apispec/core.system.blob.json
@@ -0,0 +1,20 @@
+{
+  "documentation": "https://cwiki.apache.org/confluence/display/solr/Blob+Store+API",
+  "description": "Lists blobs in the blob store (the .system collection). The list can be limited by name or name and version.",
+  "methods": [
+    "GET"
+  ],
+  "url": {
+    "paths": [
+      "/blob",
+      "/blob/{name}",
+      "/blob/{name}/{version}"
+    ],
+    "params": {
+      "wt": {
+        "type":"string",
+        "description": "Use the value 'filestream' to get the file content. Use other response writers (such as xml, or json) to fetch only the metadata."
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/resources/apispec/core.system.blob.upload.json
----------------------------------------------------------------------
diff --git a/solr/core/src/resources/apispec/core.system.blob.upload.json b/solr/core/src/resources/apispec/core.system.blob.upload.json
new file mode 100644
index 0000000..854e544
--- /dev/null
+++ b/solr/core/src/resources/apispec/core.system.blob.upload.json
@@ -0,0 +1,12 @@
+{
+  "documentation": "https://cwiki.apache.org/confluence/display/solr/Blob+Store+API",
+  "description": "Uploads a blob to the blob store. Note that the blob store is a specially named collection (which must be '.system') which must be created before uploading a blob to it.",
+  "methods": [
+    "POST"
+  ],
+  "url": {
+    "paths": [
+      "/blob/{name}"
+    ]
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/resources/apispec/cores.Commands.json
----------------------------------------------------------------------
diff --git a/solr/core/src/resources/apispec/cores.Commands.json b/solr/core/src/resources/apispec/cores.Commands.json
new file mode 100644
index 0000000..d6419cf
--- /dev/null
+++ b/solr/core/src/resources/apispec/cores.Commands.json
@@ -0,0 +1,85 @@
+{
+  "documentation": "https://cwiki.apache.org/confluence/display/solr/CoreAdmin+API",
+  "description": "Actions on non-specific cores. See the /cores/{core} endpoint for actions on specific, named, cores.",
+  "methods": [
+    "POST"
+  ],
+  "url": {
+    "paths": [
+      "/cores"
+    ]
+  },
+  "commands": {
+    "create": {
+      "type" : "object",
+      "documentation": "https://cwiki.apache.org/confluence/display/solr/CoreAdmin+API#CoreAdminAPI-CREATE",
+      "description": "Creates a new core. If you are using SolrCloud, you should use the Collections API instead. While a core for a SolrCloud cluster can be created with this API, it is considered an expert-level action. The Collections API has commands for creating new shards and replicas that ensure the safety of those actions within your cluster.",
+      "properties": {
+        "name": {
+          "type": "string",
+          "description": "The core name to create. If a core with this name already exists, an error will be returned."
+        },
+        "instanceDir": {
+          "type": "string",
+          "description": "The core instance directory, where files for this core should be stored. While this parameter is not required, if it is not defined it will default to a path relative to Solr Home that includes the name you've given the new core. This location MUST EXIST prior to creating the core, and it must include a conf directory that includes solrconfig.xml and your schema, either as a schema.xml file or using the managed schema feature."
+        },
+        "schema": {
+          "type": "string",
+          "description": "Name of the schema file to use for the core. Please note that if you are using a 'managed schema' (Solr's default behavior) then any value for this property that does not match the effective managedSchemaResourceName will be read once, backed up, and converted for managed schema use. If you are using the default name (schema.xml or the managed schema name), you do not need to define the schema file name."
+        },
+        "dataDir": {
+          "type": "string",
+          "description": "Name of the data directory relative to instanceDir. This is where the index files will be stored."
+        },
+        "config": {
+          "type": "string",
+          "description": "Name of the config file (i.e., solrconfig.xml) relative to instanceDir. If you are using the default name (solrconfig.xml), you do not need to define the config file name."
+        },
+        "configSet": {
+          "type": "string",
+          "documentation": "https://cwiki.apache.org/confluence/display/solr/Config+Sets",
+          "description": "The name of a config set to use. The config set must already exist. The solr.xml file defines the location of the configset base directory, and configuration files can be shared between cores by defining sub-directories. The files in the named configSet will be used for the schema and config properties instead of defining them explicitly."
+        },
+        "loadOnStartup": {
+          "type": "boolean",
+          "description": "If true, the core will be loaded on startup. Set to false to enable lazy loading, where the core will only be loaded if it is referenced or called.",
+          "default": "true"
+        },
+        "transient": {
+          "type": "boolean",
+          "description": "Allows Solr to unload the core if resources are required.",
+          "default": "false"
+        },
+        "shard": {
+          "type": "string",
+          "description": "In SolrCloud mode, the shard this core should belong to."
+        },
+        "collection": {
+          "type": "string",
+          "description": "The name of the collection this core belongs to."
+        },
+        "props": {
+          "type": "object",
+          "documentation": "https://cwiki.apache.org/confluence/display/solr/Defining+core.properties",
+          "description": "Allows adding core.properties for the collection.",
+          "additionalProperties": true
+        },
+        "coreNodeName": {
+          "type": "string",
+          "description": "The replica name."
+        },
+        "numShards": {
+          "type":"number",
+          "description":"The number of shards to create for this core."
+        },
+        "async": {
+          "type": "string",
+          "description": "Defines a request ID that can be used to track this action after it's submitted. The action will be processed asynchronously when this is defined."
+        }
+      },
+      "required": [
+        "name"
+      ]
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/resources/apispec/cores.Status.json
----------------------------------------------------------------------
diff --git a/solr/core/src/resources/apispec/cores.Status.json b/solr/core/src/resources/apispec/cores.Status.json
new file mode 100644
index 0000000..155bcf5
--- /dev/null
+++ b/solr/core/src/resources/apispec/cores.Status.json
@@ -0,0 +1,20 @@
+{
+  "documentation": "https://cwiki.apache.org/confluence/display/solr/CoreAdmin+API#CoreAdminAPI-STATUS",
+  "description": "Provides status and other information about the status of each core. Individual cores can be requested by core name.",
+  "methods": [
+    "GET"
+  ],
+  "url": {
+    "paths": [
+      "/cores",
+      "/cores/{core}"
+    ],
+    "params": {
+      "indexInfo": {
+        "type": "boolean",
+        "description": "If true, index information will be returned, such as information about number of documents, deletions, segments, etc. In a large cluster with more than hundreds of cores, this can take a long time to retrieve. If you have a large cluster, consider setting this to false.",
+        "default": true
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/resources/apispec/cores.core.Commands.json
----------------------------------------------------------------------
diff --git a/solr/core/src/resources/apispec/cores.core.Commands.json b/solr/core/src/resources/apispec/cores.core.Commands.json
new file mode 100644
index 0000000..5049a3a
--- /dev/null
+++ b/solr/core/src/resources/apispec/cores.core.Commands.json
@@ -0,0 +1,136 @@
+{
+  "documentation": "https://cwiki.apache.org/confluence/display/solr/CoreAdmin+API",
+  "description": "Actions that are peformed on individual cores, such as reloading, swapping cores, renaming, and others.",
+  "methods": [
+    "POST"
+  ],
+  "url": {
+    "paths": [
+      "/cores/{core}"
+    ]
+  },
+  "commands": {
+    "reload": {
+      "type":"object",
+      "documentation": "https://cwiki.apache.org/confluence/display/solr/CoreAdmin+API#CoreAdminAPI-RELOAD",
+      "description": "Reloads a core. This is useful when you have made changes on disk such as editing the schema or solrconfig.xml files. Most APIs reload cores automatically, so this should not be necessary if changes were made with those APIs."
+    },
+    "swap": {
+      "type":"object",
+      "documentation": "https://cwiki.apache.org/confluence/display/solr/CoreAdmin+API#CoreAdminAPI-SWAP",
+      "description": "Swaps the names of two existing Solr cores. This can be used to swap new content into production. The former core can be swapped back if necessary. Using this API is not supported in SolrCloud mode.",
+      "properties": {
+        "with": {
+          "type": "string",
+          "description": "The name of the other core to be swapped (the first core name is included in the request)."
+        },
+        "async": {
+          "type": "string",
+          "description": "Defines a request ID that can be used to track this action after it's submitted. The action will be processed asynchronously when this is defined."
+        }
+      },
+      "required": [
+        "with"
+      ]
+    },
+    "rename": {
+      "type": "object",
+      "documentation": "https://cwiki.apache.org/confluence/display/solr/CoreAdmin+API#CoreAdminAPI-RENAME",
+      "description": "Change the name of a core.",
+      "properties": {
+        "to": {
+          "type": "string",
+          "description": "The new name for the core."
+        },
+        "async": {
+          "type": "string",
+          "description": "Defines a request ID that can be used to track this action after it's submitted. The action will be processed asynchronously when this is defined."
+        }
+      },
+      "required": [
+        "to"
+      ]
+    },
+    "unload": {
+      "type": "object",
+      "documentation": "https://cwiki.apache.org/confluence/display/solr/CoreAdmin+API#CoreAdminAPI-UNLOAD",
+      "description": "Removes a core. Active requests would continue to be processed, but new requests will not be sent to the new core. If a core is registered under more than one name, only the name given in the request is removed.",
+      "properties": {
+        "deleteIndex": {
+          "type": "boolean",
+          "description": "If true, the index will be removed while unloading the core.",
+          "default": "false"
+        },
+        "deleteDataDir": {
+          "type": "boolean",
+          "description": "If true, the data directory and all sub-directories will be removed while unloading the core.",
+          "default": "false"
+        },
+        "deleteInstanceDir": {
+          "type": "boolean",
+          "description": "If true, everything related to the core, including the index, data, and conf directories, will be removed while unloading the core.",
+          "default": "false"
+        },
+        "async": {
+          "type": "string",
+          "description": "Defines a request ID that can be used to track this action after it's submitted. The action will be processed asynchronously when this is defined."
+        }
+      }
+    },
+    "merge-indexes": {
+      "type":"object",
+      "documentation": "https://cwiki.apache.org/confluence/display/solr/CoreAdmin+API#CoreAdminAPI-MERGEINDEXES",
+      "description":"Merges one or more indexes to another index. The indexes must have completed commits, and should be locked against writes until the merge is complete to avoid index corruption. The target core (which is the core that should be used as the endpoint for this command) must exist before using this command. A commit should also be performed on this core after the merge is complete.",
+      "properties": {
+        "indexDir": {
+          "type": "array",
+          "description": "A comma-separated list index directories for each source core that will be merged with the target core.",
+          "items": {
+            "type": "string"
+          }
+        },
+        "srcCore": {
+          "type": "array",
+          "description": "A comma-separated list of the names of each source core to be merged with the target core.",
+          "items": {
+            "type": "string"
+          }
+        },
+        "async": {
+          "type": "string",
+          "description": "Defines a request ID that can be used to track this action after it's submitted. The action will be processed asynchronously when this is defined."
+        }
+      }
+    },
+    "split":  { "#include": "cores.core.Commands.split"},
+    "request-recovery": {
+      "type":"object",
+      "documentation": "https://cwiki.apache.org/confluence/display/solr/CoreAdmin+API#CoreAdminAPI-REQUESTRECOVERY",
+      "description": "Manually asks a core to recover by synching with a leader. It may help SolrCloud clusters where a node refuses to come back up. However, it is considered an expert-level command, and should be used very carefully."
+    },
+    "force-prepare-for-leadership": {
+      "type": "object",
+      "description": "An internal API used by the Collections API to force leader election. This should not be used directly by end-users."
+    },
+    "prep-recovery": {
+      "type": "object",
+      "additionalProperties": true,
+      "description": "An internal API used by the Collections API. This should not be used directly by end-users."
+    },
+    "request-apply-updates": {
+      "type": "object",
+      "additionalProperties": true,
+      "description": "An internal API used by the Collections API. This should not be used directly by end-users."
+    },
+    "request-sync-shard": {
+      "type": "object",
+      "additionalProperties": true,
+      "description": "An internal API used by the Collections API. This should not be used directly by end-users."
+    },
+    "request-buffer-updates": {
+      "type": "object",
+      "additionalProperties": true,
+      "description": "An internal API used by the Collections API. This should not be used directly by end-users."
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/resources/apispec/cores.core.Commands.split.json
----------------------------------------------------------------------
diff --git a/solr/core/src/resources/apispec/cores.core.Commands.split.json b/solr/core/src/resources/apispec/cores.core.Commands.split.json
new file mode 100644
index 0000000..3aa0a91
--- /dev/null
+++ b/solr/core/src/resources/apispec/cores.core.Commands.split.json
@@ -0,0 +1,34 @@
+{
+  "documentation": "https://cwiki.apache.org/confluence/display/solr/CoreAdmin+API#CoreAdminAPI-SPLIT",
+  "description": "Allows splitting an index into two or more new indexes.",
+  "type": "object",
+  "properties": {
+    "path": {
+      "type": "array",
+      "description": "Directory path(s) in which a piece of the index will be written. This allows splitting the index before creating the cores to contain them. Note if using this approach that the indexes will not be able to receive updates until a new core has been created to handle the incoming updates. If you have already created the new cores, you should define the targetCore property instead.",
+      "items": {
+        "type": "string"
+      }
+    },
+    "targetCore": {
+      "type": "array",
+      "description": "The target Solr core(s) to which a piece of the index will be merged (if the target core already contains data). This requires that the cores have already been created. If the cores have not yet been created, use the path property instead.",
+      "items": {
+        "type": "string"
+      }
+    },
+    "splitKey": {
+      "type":"string",
+      "description": "A route key to use for splitting the index. This parameter is optional, but should not be defined if the ranges parameter is also defined."
+    },
+    "ranges": {
+      "type": "string",
+      "description": "A comma-separated list of hexadecimal hash ranges that will be used to split the core. This parameter is optional, but should not be defined if the splitKey parameter is also defined."
+    },
+    "async": {
+      "type": "string",
+      "description": "Defines a request ID that can be used to track this action after it's submitted. The action will be processed asynchronously when this is defined. This command can be long-running, so running it asynchronously is recommended."
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/resources/apispec/emptySpec.json
----------------------------------------------------------------------
diff --git a/solr/core/src/resources/apispec/emptySpec.json b/solr/core/src/resources/apispec/emptySpec.json
new file mode 100644
index 0000000..d95bff9
--- /dev/null
+++ b/solr/core/src/resources/apispec/emptySpec.json
@@ -0,0 +1,11 @@
+{
+  "methods": [
+    "GET",
+    "POST"
+  ],
+  "url": {
+    "paths": [
+      "$handlerName"
+    ]
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/resources/apispec/node.Commands.json
----------------------------------------------------------------------
diff --git a/solr/core/src/resources/apispec/node.Commands.json b/solr/core/src/resources/apispec/node.Commands.json
new file mode 100644
index 0000000..11b3c89
--- /dev/null
+++ b/solr/core/src/resources/apispec/node.Commands.json
@@ -0,0 +1,24 @@
+{
+  "methods": [
+    "POST"
+  ],
+  "url": {
+    "paths": [
+      "/node"
+    ]
+  },
+  "commands": {
+    "overseer-op": {
+      "type": "object",
+      "additionalProperties": true
+    },
+    "rejoin-leader-election": {
+      "type": "object",
+      "additionalProperties": true
+    },
+    "invoke":{
+      "type": "object",
+      "additionalProperties": true
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/resources/apispec/node.Info.json
----------------------------------------------------------------------
diff --git a/solr/core/src/resources/apispec/node.Info.json b/solr/core/src/resources/apispec/node.Info.json
new file mode 100644
index 0000000..e7752e6
--- /dev/null
+++ b/solr/core/src/resources/apispec/node.Info.json
@@ -0,0 +1,11 @@
+{
+   "description": "Provides information about system properties, threads, logging settings, and system details for a node.",
+  "methods": ["GET"],
+  "url": {
+    "paths": [
+      "/node/properties",
+      "/node/threads",
+      "/node/logging",
+      "/node/system"]
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/resources/apispec/node.invoke.json
----------------------------------------------------------------------
diff --git a/solr/core/src/resources/apispec/node.invoke.json b/solr/core/src/resources/apispec/node.invoke.json
new file mode 100644
index 0000000..c8a9f69
--- /dev/null
+++ b/solr/core/src/resources/apispec/node.invoke.json
@@ -0,0 +1,16 @@
+{
+  "methods": [
+    "GET"
+  ],
+  "url": {
+    "paths": [
+      "/node/invoke"
+    ],
+    "params": {
+      "class": {
+        "type": "string",
+        "description": "Name of the class that must be invoked. "
+      }
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/test-files/solr/collection1/conf/solrconfig-infixsuggesters.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-infixsuggesters.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-infixsuggesters.xml
new file mode 100644
index 0000000..8fc42ff
--- /dev/null
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-infixsuggesters.xml
@@ -0,0 +1,101 @@
+<?xml version="1.0" ?>
+<!--
+ 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.
+-->
+
+<config>
+  <xi:include href="solrconfig.snippet.randomindexconfig.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/>
+  <luceneMatchVersion>${tests.luceneMatchVersion:LATEST}</luceneMatchVersion>
+  <dataDir>${solr.data.dir:}</dataDir>
+  <directoryFactory name="DirectoryFactory" class="solr.NRTCachingDirectoryFactory"/>
+  <schemaFactory class="ClassicIndexSchemaFactory"/>
+
+  <updateHandler class="solr.DirectUpdateHandler2"/>
+
+  <requestHandler name="standard" class="solr.StandardRequestHandler" />
+
+  <searchComponent class="solr.SuggestComponent" name="analyzing_infix_suggester_random_short_dictionary">
+    <lst name="suggester">
+      <str name="name">shortRandomAnalyzingInfixSuggester</str>
+      <str name="lookupImpl">AnalyzingInfixLookupFactory</str>
+      <str name="dictionaryImpl">RandomTestDictionaryFactory</str>
+      <long name="randDictMaxItems">100</long>
+      <str name="indexPath">short_random_analyzing_infix_suggester</str>
+      <str name="suggestAnalyzerFieldType">text</str>
+      <str name="buildOnCommit">false</str>
+      <str name="buildOnStartup">false</str>
+    </lst>
+  </searchComponent>
+  <requestHandler name="/suggest_analyzing_infix_short_dictionary" class="solr.SearchHandler">
+    <lst name="defaults">
+      <str name="suggest">true</str>
+    </lst>
+    <arr name="components">
+      <str>analyzing_infix_suggester_random_short_dictionary</str>
+    </arr>
+  </requestHandler>
+
+  <searchComponent class="solr.SuggestComponent" name="analyzing_infix_suggester_random_long_dictionary">
+    <lst name="suggester">
+      <str name="name">longRandomAnalyzingInfixSuggester</str>
+      <str name="lookupImpl">AnalyzingInfixLookupFactory</str>
+      <str name="dictionaryImpl">RandomTestDictionaryFactory</str>
+      <long name="randDictMaxItems">100000</long>
+      <str name="indexPath">long_random_analyzing_infix_suggester</str>
+      <str name="suggestAnalyzerFieldType">text</str>
+      <str name="buildOnCommit">false</str>
+      <str name="buildOnStartup">false</str>
+    </lst>
+  </searchComponent>
+  <requestHandler name="/suggest_analyzing_infix_long_dictionary" class="solr.SearchHandler">
+    <lst name="defaults">
+      <str name="suggest">true</str>
+    </lst>
+    <arr name="components">
+      <str>analyzing_infix_suggester_random_long_dictionary</str>
+    </arr>
+  </requestHandler>
+
+  <searchComponent class="solr.SuggestComponent" name="blended_infix_suggester_random_short_dictionary">
+    <lst name="suggester">
+      <str name="name">shortRandomBlendedInfixSuggester</str>
+      <str name="lookupImpl">BlendedInfixLookupFactory</str>
+      <str name="dictionaryImpl">RandomTestDictionaryFactory</str>
+      <long name="randDictMaxItems">100</long>
+      <str name="blenderType">position_linear</str>
+      <str name="suggestAnalyzerFieldType">text</str>
+      <str name="indexPath">short_random_blended_infix_suggester</str>
+      <str name="highlight">true</str>
+      <str name="buildOnStartup">false</str>
+      <str name="buildOnCommit">false</str>
+    </lst>
+  </searchComponent>
+  <requestHandler name="/suggest_blended_infix_short_dictionary" class="solr.SearchHandler">
+    <lst name="defaults">
+      <str name="suggest">true</str>
+      <str name="suggest.dictionary">shortRandomBlendedInfixSuggester</str>
+      <str name="suggest.onlyMorePopular">true</str>
+      <str name="suggest.count">10</str>
+      <str name="suggest.collate">true</str>
+    </lst>
+    <arr name="components">
+      <str>blended_infix_suggester_random_short_dictionary</str>
+    </arr>
+  </requestHandler>
+
+  <query><useColdSearcher>false</useColdSearcher></query>
+
+</config>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/test-files/solr/collection1/conf/solrconfig-managed-schema.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-managed-schema.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-managed-schema.xml
index 467deca..31bbbb3 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-managed-schema.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-managed-schema.xml
@@ -40,7 +40,7 @@
   </requestHandler>
 
 
-  <requestHandler name="/dump" class="DumpRequestHandler" initParams="a">
+  <requestHandler name="/dump" class="DumpRequestHandler" initParams="a" registerPath="/,/v2">
     <lst name="defaults">
       <str name="a">${my.custom.variable.a:A}</str>
       <str name="b">${my.custom.variable.b:B}</str>

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/test-files/solr/collection1/conf/solrconfig-master-throttled.xml
----------------------------------------------------------------------
diff --git a/solr/core/src/test-files/solr/collection1/conf/solrconfig-master-throttled.xml b/solr/core/src/test-files/solr/collection1/conf/solrconfig-master-throttled.xml
index eac571c..5bc5ac7 100644
--- a/solr/core/src/test-files/solr/collection1/conf/solrconfig-master-throttled.xml
+++ b/solr/core/src/test-files/solr/collection1/conf/solrconfig-master-throttled.xml
@@ -34,7 +34,7 @@
 
   <requestHandler name="/replication" class="solr.ReplicationHandler">
     <lst name="defaults">
-      <str name="maxWriteMBPerSec">0.1</str>
+      <str name="maxWriteMBPerSec">0.05</str>
     </lst>
   </requestHandler>
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/test/org/apache/solr/TestRandomDVFaceting.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/TestRandomDVFaceting.java b/solr/core/src/test/org/apache/solr/TestRandomDVFaceting.java
index d088924..dc0f5c2 100644
--- a/solr/core/src/test/org/apache/solr/TestRandomDVFaceting.java
+++ b/solr/core/src/test/org/apache/solr/TestRandomDVFaceting.java
@@ -163,7 +163,7 @@ public class TestRandomDVFaceting extends SolrTestCaseJ4 {
       SchemaField sf = req.getSchema().getField(ftype.fname);
       boolean multiValued = sf.getType().multiValuedFieldCache();
       boolean indexed = sf.indexed();
-      boolean numeric = sf.getType().getNumericType() != null;
+      boolean numeric = sf.getType().getNumberType() != null;
 
       int offset = 0;
       if (rand.nextInt(100) < 20) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/test/org/apache/solr/api/TestPathTrie.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/api/TestPathTrie.java b/solr/core/src/test/org/apache/solr/api/TestPathTrie.java
new file mode 100644
index 0000000..d4cbf32
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/api/TestPathTrie.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.api;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+
+import com.google.common.collect.ImmutableSet;
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.util.PathTrie;
+
+import static java.util.Collections.emptyMap;
+import static java.util.Collections.singletonMap;
+import static org.apache.solr.api.ApiBag.HANDLER_NAME;
+
+public class TestPathTrie extends SolrTestCaseJ4 {
+
+  public void testPathTrie() {
+    PathTrie<String> pathTrie = new PathTrie<>(ImmutableSet.of("_introspect"));
+    pathTrie.insert("/", emptyMap(), "R");
+    pathTrie.insert("/aa", emptyMap(), "d");
+    pathTrie.insert("/aa/bb/{cc}/dd", emptyMap(), "a");
+    pathTrie.insert("/$handlerName/{cc}/dd", singletonMap(HANDLER_NAME, "test"), "test");
+    pathTrie.insert("/aa/bb/{cc}/{xx}", emptyMap(), "b");
+    pathTrie.insert("/aa/bb", emptyMap(), "c");
+
+    HashMap templateValues = new HashMap<>();
+    assertEquals("R", pathTrie.lookup("/", templateValues, null));
+    assertEquals("d", pathTrie.lookup("/aa", templateValues, null));
+    assertEquals("a", pathTrie.lookup("/aa/bb/hello/dd", templateValues, null));
+    templateValues.clear();
+    assertEquals("test", pathTrie.lookup("/test/hello/dd", templateValues, null));
+    assertEquals("hello", templateValues.get("cc"));
+    templateValues.clear();
+    assertEquals("b", pathTrie.lookup("/aa/bb/hello/world", templateValues, null));
+    assertEquals("hello", templateValues.get("cc"));
+    assertEquals("world", templateValues.get("xx"));
+    Set<String> subPaths =  new HashSet<>();
+    templateValues.clear();
+    pathTrie.lookup("/aa",templateValues, subPaths);
+    assertEquals(3, subPaths.size());
+
+
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/test/org/apache/solr/cloud/CdcrReplicationDistributedZkTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/CdcrReplicationDistributedZkTest.java b/solr/core/src/test/org/apache/solr/cloud/CdcrReplicationDistributedZkTest.java
index 3ba6186..35592ff 100644
--- a/solr/core/src/test/org/apache/solr/cloud/CdcrReplicationDistributedZkTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/CdcrReplicationDistributedZkTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.solr.cloud;
 
+import org.apache.lucene.util.LuceneTestCase.BadApple;
 import org.apache.lucene.util.LuceneTestCase.Nightly;
 import org.apache.solr.common.SolrInputDocument;
 import org.apache.solr.common.util.NamedList;
@@ -31,6 +32,7 @@ import java.util.List;
 import java.util.Map;
 
 @Nightly
+@BadApple(bugUrl = "https://issues.apache.org/jira/browse/SOLR-10107")
 public class CdcrReplicationDistributedZkTest extends BaseCdcrDistributedZkTest {
 
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/test/org/apache/solr/cloud/CleanupOldIndexTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/CleanupOldIndexTest.java b/solr/core/src/test/org/apache/solr/cloud/CleanupOldIndexTest.java
index 48243bb..006c3c9 100644
--- a/solr/core/src/test/org/apache/solr/cloud/CleanupOldIndexTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/CleanupOldIndexTest.java
@@ -38,6 +38,8 @@ public class CleanupOldIndexTest extends SolrCloudTestCase {
 
   @BeforeClass
   public static void setupCluster() throws Exception {
+    // we restart jetty and expect to find on disk data - need a local fs directory
+    useFactory(null);
     configureCluster(2)
         .addConfig("conf1", TEST_PATH().resolve("configsets").resolve("cloud-dynamic").resolve("conf"))
         .configure();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/test/org/apache/solr/cloud/CollectionsAPIDistributedZkTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/CollectionsAPIDistributedZkTest.java b/solr/core/src/test/org/apache/solr/cloud/CollectionsAPIDistributedZkTest.java
index 7586f2a..c3d1a86 100644
--- a/solr/core/src/test/org/apache/solr/cloud/CollectionsAPIDistributedZkTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/CollectionsAPIDistributedZkTest.java
@@ -86,6 +86,8 @@ public class CollectionsAPIDistributedZkTest extends SolrCloudTestCase {
 
   @BeforeClass
   public static void beforeCollectionsAPIDistributedZkTest() {
+    // we don't want this test to have zk timeouts
+    System.setProperty("zkClientTimeout", "240000");
     TestInjection.randomDelayInCoreCreation = "true:20";
     System.setProperty("validateAfterInactivity", "200");
   }
@@ -100,7 +102,11 @@ public class CollectionsAPIDistributedZkTest extends SolrCloudTestCase {
 
   @Before
   public void clearCluster() throws Exception {
-    cluster.deleteAllCollections();
+    try {
+      cluster.deleteAllCollections();
+    } finally {
+      System.clearProperty("zkClientTimeout");
+    }
   }
 
   @Test
@@ -366,7 +372,7 @@ public class CollectionsAPIDistributedZkTest extends SolrCloudTestCase {
       cluster.getSolrClient().request(createCmd);
     });
 
-    TimeUnit.MILLISECONDS.sleep(200);
+    TimeUnit.MILLISECONDS.sleep(1000);
     // in both cases, the collection should have default to the core name
     cloudClient.getZkStateReader().forceUpdateCollection("corewithnocollection3");
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/test/org/apache/solr/cloud/ConcurrentDeleteAndCreateCollectionTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/ConcurrentDeleteAndCreateCollectionTest.java b/solr/core/src/test/org/apache/solr/cloud/ConcurrentDeleteAndCreateCollectionTest.java
index 3e90759..151230d 100644
--- a/solr/core/src/test/org/apache/solr/cloud/ConcurrentDeleteAndCreateCollectionTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/ConcurrentDeleteAndCreateCollectionTest.java
@@ -17,6 +17,7 @@
 package org.apache.solr.cloud;
 
 import java.io.IOException;
+import java.lang.invoke.MethodHandles;
 import java.nio.file.Path;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
@@ -27,14 +28,19 @@ import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrQuery;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
 import org.apache.solr.client.solrj.response.CollectionAdminResponse;
+import org.apache.solr.common.util.IOUtils;
 import org.apache.solr.util.TimeOut;
 import org.apache.zookeeper.KeeperException;
 import org.junit.After;
 import org.junit.Before;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 @Nightly
 public class ConcurrentDeleteAndCreateCollectionTest extends SolrTestCaseJ4 {
   
+  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+  
   private MiniSolrCloudCluster solrCluster;
   
   @Override
@@ -54,7 +60,7 @@ public class ConcurrentDeleteAndCreateCollectionTest extends SolrTestCaseJ4 {
   public void testConcurrentCreateAndDeleteDoesNotFail() {
     final AtomicReference<Exception> failure = new AtomicReference<>();
     final int timeToRunSec = 30;
-    final Thread[] threads = new Thread[10];
+    final CreateDeleteCollectionThread[] threads = new CreateDeleteCollectionThread[10];
     for (int i = 0; i < threads.length; i++) {
       final String collectionName = "collection" + i;
       uploadConfig(configset("configset-2"), collectionName);
@@ -74,12 +80,12 @@ public class ConcurrentDeleteAndCreateCollectionTest extends SolrTestCaseJ4 {
     final String configName = "testconfig";
     uploadConfig(configset("configset-2"), configName); // upload config once, to be used by all collections
     final String baseUrl = solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString();
-    final SolrClient solrClient = getHttpSolrClient(baseUrl);
     final AtomicReference<Exception> failure = new AtomicReference<>();
     final int timeToRunSec = 30;
-    final Thread[] threads = new Thread[2];
+    final CreateDeleteCollectionThread[] threads = new CreateDeleteCollectionThread[2];
     for (int i = 0; i < threads.length; i++) {
       final String collectionName = "collection" + i;
+      final SolrClient solrClient = getHttpSolrClient(baseUrl);
       threads[i] = new CreateDeleteCollectionThread("create-delete-" + i, collectionName, configName,
                                                     timeToRunSec, solrClient, failure);
     }
@@ -88,12 +94,6 @@ public class ConcurrentDeleteAndCreateCollectionTest extends SolrTestCaseJ4 {
     joinAll(threads);
 
     assertNull("concurrent create and delete collection failed: " + failure.get(), failure.get());
-
-    try {
-      solrClient.close();
-    } catch (IOException e) {
-      throw new RuntimeException(e);
-    }
   }
   
   private void uploadConfig(Path configDir, String configName) {
@@ -104,10 +104,10 @@ public class ConcurrentDeleteAndCreateCollectionTest extends SolrTestCaseJ4 {
     }
   }
   
-  private void joinAll(final Thread[] threads) {
-    for (Thread t : threads) {
+  private void joinAll(final CreateDeleteCollectionThread[] threads) {
+    for (CreateDeleteCollectionThread t : threads) {
       try {
-        t.join();
+        t.joinAndClose();
       } catch (InterruptedException e) {
         Thread.interrupted();
         throw new RuntimeException(e);
@@ -152,6 +152,7 @@ public class ConcurrentDeleteAndCreateCollectionTest extends SolrTestCaseJ4 {
     }
     
     protected void addFailure(Exception e) {
+      log.error("Add Failure", e);
       synchronized (failure) {
         if (failure.get() != null) {
           failure.get().addSuppressed(e);
@@ -190,6 +191,14 @@ public class ConcurrentDeleteAndCreateCollectionTest extends SolrTestCaseJ4 {
         addFailure(e);
       }
     }
+    
+    public void joinAndClose() throws InterruptedException {
+      try {
+        super.join(60000);
+      } finally {
+        IOUtils.closeQuietly(solrClient);
+      }
+    }
   }
   
   private static class CreateDeleteSearchCollectionThread extends CreateDeleteCollectionThread {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/test/org/apache/solr/cloud/SharedFSAutoReplicaFailoverTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/SharedFSAutoReplicaFailoverTest.java b/solr/core/src/test/org/apache/solr/cloud/SharedFSAutoReplicaFailoverTest.java
index d7a1fb2..d87e82f 100644
--- a/solr/core/src/test/org/apache/solr/cloud/SharedFSAutoReplicaFailoverTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/SharedFSAutoReplicaFailoverTest.java
@@ -306,7 +306,7 @@ public class SharedFSAutoReplicaFailoverTest extends AbstractFullDistribZkTestBa
     request.setPath("/admin/collections");
     cloudClient.request(request);
 
-    assertTrue("Timeout waiting for all live and active", ClusterStateUtil.waitForAllActiveAndLiveReplicas(cloudClient.getZkStateReader(), collection1, 60000));
+    assertTrue("Timeout waiting for all live and active", ClusterStateUtil.waitForAllActiveAndLiveReplicas(cloudClient.getZkStateReader(), collection1, 90000));
     assertSliceAndReplicaCount(collection1);
 
     assertUlogDir(collections);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithDelegationTokens.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithDelegationTokens.java b/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithDelegationTokens.java
index c3fa813..f8f3f7e 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithDelegationTokens.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithDelegationTokens.java
@@ -282,6 +282,7 @@ public class TestSolrCloudWithDelegationTokens extends SolrTestCaseJ4 {
   }
 
   @Test
+  @AwaitsFix(bugUrl="https://issues.apache.org/jira/browse/HADOOP-14044")
   public void testDelegationTokenCancelFail() throws Exception {
     // cancel a bogus token
     cancelDelegationToken("BOGUS", ErrorCode.NOT_FOUND.code, solrClientPrimary);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/test/org/apache/solr/cloud/hdfs/HdfsBasicDistributedZkTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/hdfs/HdfsBasicDistributedZkTest.java b/solr/core/src/test/org/apache/solr/cloud/hdfs/HdfsBasicDistributedZkTest.java
index 70eaf90..97be823 100644
--- a/solr/core/src/test/org/apache/solr/cloud/hdfs/HdfsBasicDistributedZkTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/hdfs/HdfsBasicDistributedZkTest.java
@@ -39,12 +39,14 @@ public class HdfsBasicDistributedZkTest extends BasicDistributedZkTest {
   
   @BeforeClass
   public static void setupClass() throws Exception {
+    System.setProperty("tests.hdfs.numdatanodes", "1");
     dfsCluster = HdfsTestUtil.setupClass(createTempDir().toFile().getAbsolutePath());
   }
   
   @AfterClass
   public static void teardownClass() throws Exception {
     HdfsTestUtil.teardownClass(dfsCluster);
+    System.clearProperty("tests.hdfs.numdatanodes");
     dfsCluster = null;
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/test/org/apache/solr/cloud/hdfs/HdfsCollectionsAPIDistributedZkTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/hdfs/HdfsCollectionsAPIDistributedZkTest.java b/solr/core/src/test/org/apache/solr/cloud/hdfs/HdfsCollectionsAPIDistributedZkTest.java
index fc938a1..80aa78d 100644
--- a/solr/core/src/test/org/apache/solr/cloud/hdfs/HdfsCollectionsAPIDistributedZkTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/hdfs/HdfsCollectionsAPIDistributedZkTest.java
@@ -38,7 +38,7 @@ public class HdfsCollectionsAPIDistributedZkTest extends CollectionsAPIDistribut
   @BeforeClass
   public static void setupClass() throws Exception {
     dfsCluster = HdfsTestUtil.setupClass(createTempDir().toFile().getAbsolutePath());
-    System.setProperty("solr.hdfs.blockcache.blocksperbank", "2048");
+    System.setProperty("solr.hdfs.blockcache.blocksperbank", "1024");
 
     ZkConfigManager configManager = new ZkConfigManager(zkClient());
     configManager.uploadConfigDir(configset("cloud-hdfs"), "conf");

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/test/org/apache/solr/cloud/hdfs/HdfsTestUtil.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/hdfs/HdfsTestUtil.java b/solr/core/src/test/org/apache/solr/cloud/hdfs/HdfsTestUtil.java
index 12d5651..7038328 100644
--- a/solr/core/src/test/org/apache/solr/cloud/hdfs/HdfsTestUtil.java
+++ b/solr/core/src/test/org/apache/solr/cloud/hdfs/HdfsTestUtil.java
@@ -42,6 +42,8 @@ import org.apache.solr.util.HdfsUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import io.netty.util.internal.ThreadLocalRandom;
+
 public class HdfsTestUtil {
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
   
@@ -75,7 +77,11 @@ public class HdfsTestUtil {
     
     if (!HA_TESTING_ENABLED) haTesting = false;
     
-    int dataNodes = 2;
+    
+    // keep netty from using secure random on startup: SOLR-10098
+    ThreadLocalRandom.setInitialSeedUniquifier(1L);
+    
+    int dataNodes = Integer.getInteger("tests.hdfs.numdatanodes", 2);
     
     Configuration conf = new Configuration();
     conf.set("dfs.block.access.token.enable", "false");

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/test/org/apache/solr/cloud/hdfs/HdfsWriteToMultipleCollectionsTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/hdfs/HdfsWriteToMultipleCollectionsTest.java b/solr/core/src/test/org/apache/solr/cloud/hdfs/HdfsWriteToMultipleCollectionsTest.java
index 2005978..b345342 100644
--- a/solr/core/src/test/org/apache/solr/cloud/hdfs/HdfsWriteToMultipleCollectionsTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/hdfs/HdfsWriteToMultipleCollectionsTest.java
@@ -39,7 +39,9 @@ import org.apache.solr.client.solrj.impl.CloudSolrClient;
 import org.apache.solr.cloud.BasicDistributedZkTest;
 import org.apache.solr.cloud.StoppableIndexingThread;
 import org.apache.solr.core.CoreContainer;
+import org.apache.solr.core.DirectoryFactory;
 import org.apache.solr.core.HdfsDirectoryFactory;
+import org.apache.solr.core.MetricsDirectoryFactory;
 import org.apache.solr.core.SolrCore;
 import org.apache.solr.store.blockcache.BlockCache;
 import org.apache.solr.store.blockcache.BlockDirectory;
@@ -134,10 +136,14 @@ public class HdfsWriteToMultipleCollectionsTest extends BasicDistributedZkTest {
       for (SolrCore core : solrCores) {
         if (core.getCoreDescriptor().getCloudDescriptor().getCollectionName()
             .startsWith(ACOLLECTION)) {
-          assertTrue(core.getDirectoryFactory() instanceof HdfsDirectoryFactory);
-          Directory dir = core.getDirectoryFactory().get(core.getDataDir(), null, null);
+          DirectoryFactory factory = core.getDirectoryFactory();
+          if (factory instanceof MetricsDirectoryFactory) {
+            factory = ((MetricsDirectoryFactory) factory).getDelegate();
+          }
+          assertTrue("Found: " + core.getDirectoryFactory().getClass().getName(), factory instanceof HdfsDirectoryFactory);
+          Directory dir = factory.get(core.getDataDir(), null, null);
           try {
-            long dataDirSize = core.getDirectoryFactory().size(dir);
+            long dataDirSize = factory.size(dir);
             FileSystem fileSystem = null;
             
             fileSystem = FileSystem.newInstance(
@@ -153,8 +159,8 @@ public class HdfsWriteToMultipleCollectionsTest extends BasicDistributedZkTest {
               .getSolrCoreState().getIndexWriter(core);
           try {
             IndexWriter iw = iwRef.get();
-            NRTCachingDirectory directory = (NRTCachingDirectory) iw
-                .getDirectory();
+            NRTCachingDirectory directory = (NRTCachingDirectory) ((MetricsDirectoryFactory.MetricsDirectory)iw
+                .getDirectory()).getDelegate();
             BlockDirectory blockDirectory = (BlockDirectory) directory
                 .getDelegate();
             assertTrue(blockDirectory.isBlockCacheReadEnabled());

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/test/org/apache/solr/cloud/rule/RulesTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/rule/RulesTest.java b/solr/core/src/test/org/apache/solr/cloud/rule/RulesTest.java
index 6955418..13649e1 100644
--- a/solr/core/src/test/org/apache/solr/cloud/rule/RulesTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/rule/RulesTest.java
@@ -22,10 +22,12 @@ import java.util.List;
 import java.util.Map;
 
 import org.apache.lucene.util.LuceneTestCase;
+import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.embedded.JettySolrRunner;
 import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
 import org.apache.solr.client.solrj.request.GenericSolrRequest;
+import org.apache.solr.client.solrj.response.SimpleSolrResponse;
 import org.apache.solr.cloud.SolrCloudTestCase;
 import org.apache.solr.common.cloud.DocCollection;
 import org.apache.solr.common.params.ModifiableSolrParams;
@@ -36,6 +38,7 @@ import org.junit.rules.ExpectedException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.solr.client.solrj.SolrRequest.METHOD.GET;
 import static org.apache.solr.client.solrj.SolrRequest.METHOD.POST;
 import static org.apache.solr.common.params.CommonParams.COLLECTIONS_HANDLER_PATH;
 import static org.junit.matchers.JUnitMatchers.containsString;
@@ -161,6 +164,21 @@ public class RulesTest extends SolrCloudTestCase {
 
   }
 
+  @Test
+  public void testInvokeApi() throws Exception {
+    JettySolrRunner jetty = cluster.getRandomJetty(random());
+    try (SolrClient client = getHttpSolrClient(jetty.getBaseUrl().toString())) {
+      GenericSolrRequest req =  new GenericSolrRequest(GET, "/v2/node/invoke", new ModifiableSolrParams()
+          .add("class", ImplicitSnitch.class.getName())
+          .add("cores", "1")
+          .add("freedisk", "1")
+      );
+      SimpleSolrResponse rsp = req.process(client);
+      assertNotNull(((Map) rsp.getResponse().get(ImplicitSnitch.class.getName())).get("cores"));
+      assertNotNull(((Map) rsp.getResponse().get(ImplicitSnitch.class.getName())).get("freedisk"));
+    }
+  }
+
 
   @Test
   public void testModifyColl() throws Exception {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/test/org/apache/solr/core/BlobStoreTestRequestHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/BlobStoreTestRequestHandler.java b/solr/core/src/test/org/apache/solr/core/BlobStoreTestRequestHandler.java
index ff5e1cb..dda1eb3 100644
--- a/solr/core/src/test/org/apache/solr/core/BlobStoreTestRequestHandler.java
+++ b/solr/core/src/test/org/apache/solr/core/BlobStoreTestRequestHandler.java
@@ -58,4 +58,5 @@ public class BlobStoreTestRequestHandler extends DumpRequestHandler implements R
     run();
 
   }
+
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/test/org/apache/solr/core/HdfsDirectoryFactoryTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/HdfsDirectoryFactoryTest.java b/solr/core/src/test/org/apache/solr/core/HdfsDirectoryFactoryTest.java
index 49315be..75f6c9b 100644
--- a/solr/core/src/test/org/apache/solr/core/HdfsDirectoryFactoryTest.java
+++ b/solr/core/src/test/org/apache/solr/core/HdfsDirectoryFactoryTest.java
@@ -165,7 +165,7 @@ public class HdfsDirectoryFactoryTest extends SolrTestCaseJ4 {
     hdfs.mkdirs(oldIndexDirPath);
     assertTrue(hdfs.isDirectory(oldIndexDirPath));
 
-    hdfsFactory.cleanupOldIndexDirectories(dataHomePath.toString(), currentIndexDirPath.toString());
+    hdfsFactory.cleanupOldIndexDirectories(dataHomePath.toString(), currentIndexDirPath.toString(), false);
 
     assertTrue(hdfs.isDirectory(currentIndexDirPath));
     assertTrue(!hdfs.isDirectory(oldIndexDirPath));

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/test/org/apache/solr/core/SolrCoreTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/SolrCoreTest.java b/solr/core/src/test/org/apache/solr/core/SolrCoreTest.java
index 004039c..695e869 100644
--- a/solr/core/src/test/org/apache/solr/core/SolrCoreTest.java
+++ b/solr/core/src/test/org/apache/solr/core/SolrCoreTest.java
@@ -112,6 +112,7 @@ public class SolrCoreTest extends SolrTestCaseJ4 {
       ++ihCount; assertEquals(pathToClassMap.get("/analysis/document"), "solr.DocumentAnalysisRequestHandler");
       ++ihCount; assertEquals(pathToClassMap.get("/analysis/field"), "solr.FieldAnalysisRequestHandler");
       ++ihCount; assertEquals(pathToClassMap.get("/debug/dump"), "solr.DumpRequestHandler");
+      ++ihCount; assertEquals(pathToClassMap.get("update"), "solr.UpdateRequestHandlerApi");
     }
     assertEquals("wrong number of implicit handlers", ihCount, implicitHandlers.size());
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/test/org/apache/solr/core/TestDynamicLoading.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/TestDynamicLoading.java b/solr/core/src/test/org/apache/solr/core/TestDynamicLoading.java
index bd20b1e..8479ae4 100644
--- a/solr/core/src/test/org/apache/solr/core/TestDynamicLoading.java
+++ b/solr/core/src/test/org/apache/solr/core/TestDynamicLoading.java
@@ -88,7 +88,7 @@ public class TestDynamicLoading extends AbstractFullDistribZkTestBase {
 
 
     payload = "{\n" +
-        "'create-requesthandler' : { 'name' : '/test1', 'class': 'org.apache.solr.core.BlobStoreTestRequestHandler' , 'runtimeLib' : true }\n" +
+        "'create-requesthandler' : { 'name' : '/test1', 'class': 'org.apache.solr.core.BlobStoreTestRequestHandler' ,registerPath: '/,/v2',  'runtimeLib' : true }\n" +
         "}";
 
     client = restTestHarnesses.get(random().nextInt(restTestHarnesses.size()));

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/test/org/apache/solr/core/TestLazyCores.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/TestLazyCores.java b/solr/core/src/test/org/apache/solr/core/TestLazyCores.java
index 34cd306..0c0845b 100644
--- a/solr/core/src/test/org/apache/solr/core/TestLazyCores.java
+++ b/solr/core/src/test/org/apache/solr/core/TestLazyCores.java
@@ -42,12 +42,20 @@ import org.apache.solr.update.AddUpdateCommand;
 import org.apache.solr.update.CommitUpdateCommand;
 import org.apache.solr.update.UpdateHandler;
 import org.apache.solr.util.ReadOnlyCoresLocator;
+import org.junit.BeforeClass;
 import org.junit.Test;
 
 public class TestLazyCores extends SolrTestCaseJ4 {
 
   private File solrHomeDirectory;
 
+  @BeforeClass
+  public static void setupClass() throws Exception {
+    // Need to use a disk-based directory because there are tests that close a core after adding documents
+    // then expect to be able to re-open that core and execute a search
+    useFactory("solr.StandardDirectoryFactory");
+  }
+
   private static CoreDescriptor makeCoreDescriptor(CoreContainer cc, String coreName, String isTransient, String loadOnStartup) {
     return new CoreDescriptor(cc, coreName, cc.getCoreRootDirectory().resolve(coreName),
         CoreDescriptor.CORE_TRANSIENT, isTransient,
@@ -721,4 +729,72 @@ public class TestLazyCores extends SolrTestCaseJ4 {
     }
   }
 
+  @BadApple(bugUrl = "https://issues.apache.org/jira/browse/SOLR-10101")
+  // Insure that when a core is aged out of the transient cache, any uncommitted docs are preserved.
+  // Note, this needs FS-based indexes to persist!
+  // Cores 2, 3, 6, 7, 8, 9 are transient
+  @Test
+  public void testNoCommit() throws Exception {
+    CoreContainer cc = init();
+    String[] coreList = new String[]{
+        "collection2",
+        "collection3",
+        "collection6",
+        "collection7",
+        "collection8",
+        "collection9"
+    };
+    try {
+      // First, go through all the transient cores and add some docs. DO NOT COMMIT!
+      // The aged-out core should commit the docs when it gets closed.
+      List<SolrCore> openCores = new ArrayList<>();
+      for (String coreName : coreList) {
+        SolrCore core = cc.getCore(coreName);
+        openCores.add(core);
+        add10(core);
+      }
+      
+      // Just proving that some cores have been aged out.
+      checkNotInCores(cc, "collection2", "collection3");
+
+      // Close our get of all cores above.
+      for (SolrCore core : openCores) core.close();
+      openCores.clear();
+      
+      // We still should have 6, 7, 8, 9 loaded, their reference counts have NOT dropped to zero 
+      checkInCores(cc, "collection6", "collection7", "collection8", "collection9");
+
+      for (String coreName : coreList) {
+        // The point of this test is to insure that when cores are aged out and re-opened
+        // that the docs are there, so insure that the core we're testing is gone, gone, gone. 
+        checkNotInCores(cc, coreName);
+        
+        // Load the core up again.
+        SolrCore core = cc.getCore(coreName);
+        openCores.add(core);
+        
+        // Insure docs are still there.
+        check10(core);
+      }
+      for (SolrCore core : openCores) core.close();
+    } finally {
+      cc.shutdown();
+    }
+  }
+
+  private void add10(SolrCore core) throws IOException {
+    for (int idx = 0; idx < 10; ++idx) {
+      addLazy(core, "id", "0" + idx);
+    }
+    SolrQueryRequest req = makeReq(core);
+
+  }
+
+  private void check10(SolrCore core) {
+    // Just get a couple of searches to work!
+    assertQ("test closing core without committing",
+        makeReq(core, "q", "*:*")
+        , "//result[@numFound='10']"
+    );
+  }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/test/org/apache/solr/core/TestSolrConfigHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/TestSolrConfigHandler.java b/solr/core/src/test/org/apache/solr/core/TestSolrConfigHandler.java
index c182495..3f85a79 100644
--- a/solr/core/src/test/org/apache/solr/core/TestSolrConfigHandler.java
+++ b/solr/core/src/test/org/apache/solr/core/TestSolrConfigHandler.java
@@ -36,12 +36,14 @@ import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
 import org.apache.solr.common.util.StrUtils;
 import org.apache.solr.common.util.Utils;
+import org.apache.solr.common.util.ValidatingJsonMap;
 import org.apache.solr.handler.DumpRequestHandler;
 import org.apache.solr.handler.TestBlobHandler;
 import org.apache.solr.handler.TestSolrConfigHandlerConcurrent;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.response.SolrQueryResponse;
 import org.apache.solr.search.SolrCache;
+import org.apache.solr.util.RESTfulServerProvider;
 import org.apache.solr.util.RestTestBase;
 import org.apache.solr.util.RestTestHarness;
 import org.eclipse.jetty.servlet.ServletHolder;
@@ -82,6 +84,10 @@ public class TestSolrConfigHandler extends RestTestBase {
 
     createJettyAndHarness(tmpSolrHome.getAbsolutePath(), "solrconfig-managed-schema.xml", "schema-rest.xml",
         "/solr", true, extraServlets);
+    if (random().nextBoolean()) {
+      log.info("These tests are run with V2 API");
+      restTestHarness.setServerProvider(() -> jetty.getBaseUrl().toString() + "/v2/cores/" + DEFAULT_TEST_CORENAME);
+    }
   }
 
   @After
@@ -195,7 +201,8 @@ public class TestSolrConfigHandler extends RestTestBase {
         10);
 
     payload = "{\n" +
-        "'update-requesthandler' : { 'name' : '/x', 'class': 'org.apache.solr.handler.DumpRequestHandler' , 'startup' : 'lazy' , 'a':'b' , 'defaults': {'def_a':'def A val', 'multival':['a','b','c']}}\n" +
+        "'update-requesthandler' : { 'name' : '/x', 'class': 'org.apache.solr.handler.DumpRequestHandler' ,registerPath :'/,/v2', " +
+        " 'startup' : 'lazy' , 'a':'b' , 'defaults': {'def_a':'def A val', 'multival':['a','b','c']}}\n" +
         "}";
     runConfigCommand(writeHarness, "/config?wt=json", payload);
 
@@ -435,7 +442,8 @@ public class TestSolrConfigHandler extends RestTestBase {
     payload = "{\n" +
         "    'add-requesthandler': {\n" +
         "        name : '/dump100',\n" +
-        "        class : 'org.apache.solr.handler.DumpRequestHandler'," +
+        "       registerPath :'/,/v2',"+
+    "        class : 'org.apache.solr.handler.DumpRequestHandler'," +
         "        suggester: [{name: s1,lookupImpl: FuzzyLookupFactory, dictionaryImpl : DocumentDictionaryFactory}," +
         "                    {name: s2,lookupImpl: FuzzyLookupFactory , dictionaryImpl : DocumentExpressionDictionaryFactory}]" +
         "    }\n" +
@@ -451,13 +459,15 @@ public class TestSolrConfigHandler extends RestTestBase {
 
     map = getRespMap("/dump100?wt=json&json.nl=arrmap&initArgs=true", writeHarness);
     List initArgs = (List) map.get("initArgs");
-    assertEquals(2, initArgs.size());
-    assertTrue(((Map)initArgs.get(0)).containsKey("suggester"));
+    assertNotNull(initArgs);
+    assertTrue(initArgs.size() >= 2);
+    assertTrue(((Map)initArgs.get(2)).containsKey("suggester"));
     assertTrue(((Map)initArgs.get(1)).containsKey("suggester"));
 
     payload = "{\n" +
         "'add-requesthandler' : { 'name' : '/dump101', 'class': " +
-        "'" + CacheTest.class.getName() + "' " +
+        "'" + CacheTest.class.getName() + "', " +
+        "    registerPath :'/,/v2'"+
         ", 'startup' : 'lazy'}\n" +
         "}";
     runConfigCommand(writeHarness, "/config?wt=json", payload);
@@ -525,9 +535,20 @@ public class TestSolrConfigHandler extends RestTestBase {
         continue;
 
       }
-      if (Objects.equals(expected, Utils.getObjectByPath(m, false, jsonPath))) {
-        success = true;
-        break;
+      Object actual = Utils.getObjectByPath(m, false, jsonPath);
+
+      if (expected instanceof ValidatingJsonMap.PredicateWithErrMsg) {
+        ValidatingJsonMap.PredicateWithErrMsg predicate = (ValidatingJsonMap.PredicateWithErrMsg) expected;
+        if (predicate.test(actual) == null) {
+          success = true;
+          break;
+        }
+
+      } else {
+        if (Objects.equals(expected, actual)) {
+          success = true;
+          break;
+        }
       }
       Thread.sleep(100);
 
@@ -568,7 +589,7 @@ public class TestSolrConfigHandler extends RestTestBase {
         10);
 
     payload = "{\n" +
-        "'create-requesthandler' : { 'name' : '/d', 'class': 'org.apache.solr.handler.DumpRequestHandler' }\n" +
+        "'create-requesthandler' : { 'name' : '/d', registerPath :'/,/v2' , 'class': 'org.apache.solr.handler.DumpRequestHandler' }\n" +
         "}";
 
     TestSolrConfigHandler.runConfigCommand(harness, "/config?wt=json", payload);
@@ -598,7 +619,7 @@ public class TestSolrConfigHandler extends RestTestBase {
         5);
 
     payload = "{\n" +
-        "'create-requesthandler' : { 'name' : '/dump1', 'class': 'org.apache.solr.handler.DumpRequestHandler', 'useParams':'x' }\n" +
+        "'create-requesthandler' : { 'name' : '/dump1', registerPath :'/,/v2' , 'class': 'org.apache.solr.handler.DumpRequestHandler', 'useParams':'x' }\n" +
         "}";
 
     TestSolrConfigHandler.runConfigCommand(harness, "/config?wt=json", payload);
@@ -643,7 +664,7 @@ public class TestSolrConfigHandler extends RestTestBase {
 
     TestSolrConfigHandler.testForResponseElement(harness,
         null,
-        "/dump?wt=json&useParams=y",
+        "/dump1?wt=json&useParams=y",
         null,
         Arrays.asList("params", "c"),
         "CY val",
@@ -745,6 +766,60 @@ public class TestSolrConfigHandler extends RestTestBase {
         null,
         10);
 
+    payload = "{\n" +
+        "  'create-requesthandler': {\n" +
+        "    'name': 'aRequestHandler',\n" +
+        "    'registerPath': '/v2',\n" +
+        "    'class': 'org.apache.solr.handler.DumpRequestHandler',\n" +
+        "    'spec': {\n" +
+        "      'methods': [\n" +
+        "        'GET',\n" +
+        "        'POST'\n" +
+        "      ],\n" +
+        "      'url': {\n" +
+        "        'paths': [\n" +
+        "          '/something/{part1}/fixed/{part2}'\n" +
+        "        ]\n" +
+        "      }\n" +
+        "    }\n" +
+        "  }\n" +
+        "}";
+
+    TestSolrConfigHandler.runConfigCommand(harness, "/config?wt=json", payload);
+    TestSolrConfigHandler.testForResponseElement(harness,
+        null,
+        "/config/overlay?wt=json",
+        null,
+        Arrays.asList("overlay", "requestHandler", "aRequestHandler", "class"),
+        "org.apache.solr.handler.DumpRequestHandler",
+        10);
+    RESTfulServerProvider oldProvider = restTestHarness.getServerProvider();
+    restTestHarness.setServerProvider(() -> jetty.getBaseUrl().toString() + "/v2/cores/" + DEFAULT_TEST_CORENAME);
+
+    Map rsp = TestSolrConfigHandler.testForResponseElement(
+        harness,
+        null,
+        "/something/part1_Value/fixed/part2_Value?urlTemplateValues=part1&urlTemplateValues=part2",
+        null,
+        Arrays.asList("urlTemplateValues"),
+        new ValidatingJsonMap.PredicateWithErrMsg() {
+          @Override
+          public String test(Object o) {
+            if (o instanceof Map) {
+              Map m = (Map) o;
+              if ("part1_Value".equals(m.get("part1"))  && "part2_Value".equals(m.get("part2"))) return null;
+
+            }
+            return "no match";
+          }
+
+          @Override
+          public String toString() {
+            return "{part1:part1_Value, part2 : part2_Value]";
+          }
+        },
+        10);
+    restTestHarness.setServerProvider(oldProvider);
 
   }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/test/org/apache/solr/core/snapshots/TestSolrCloudSnapshots.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/snapshots/TestSolrCloudSnapshots.java b/solr/core/src/test/org/apache/solr/core/snapshots/TestSolrCloudSnapshots.java
index 65f74ca..bb56a94 100644
--- a/solr/core/src/test/org/apache/solr/core/snapshots/TestSolrCloudSnapshots.java
+++ b/solr/core/src/test/org/apache/solr/core/snapshots/TestSolrCloudSnapshots.java
@@ -249,6 +249,24 @@ public class TestSolrCloudSnapshots extends SolrCloudTestCase {
     // Verify all core-level snapshots are deleted.
     assertTrue("The cores remaining " + snapshotByCoreName, snapshotByCoreName.isEmpty());
     assertTrue(listCollectionSnapshots(solrClient, collectionName).isEmpty());
+
+    // Verify if the collection deletion result in proper cleanup of snapshot metadata.
+    {
+      String commitName_2 = commitName + "_2";
+
+      CollectionAdminRequest.CreateSnapshot createSnap_2 = new CollectionAdminRequest.CreateSnapshot(collectionName, commitName_2);
+      assertEquals(0, createSnap_2.process(solrClient).getStatus());
+
+      Collection<CollectionSnapshotMetaData> collectionSnaps_2 = listCollectionSnapshots(solrClient, collectionName);
+      assertEquals(1, collectionSnaps.size());
+      assertEquals(commitName_2, collectionSnaps_2.iterator().next().getName());
+
+      // Delete collection
+      CollectionAdminRequest.Delete deleteCol = CollectionAdminRequest.deleteCollection(collectionName);
+      assertEquals(0, deleteCol.process(solrClient).getStatus());
+      assertTrue(SolrSnapshotManager.listSnapshots(solrClient.getZkStateReader().getZkClient(), collectionName).isEmpty());
+    }
+
   }
 
   private Collection<CollectionSnapshotMetaData> listCollectionSnapshots(SolrClient adminClient, String collectionName) throws Exception {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/test/org/apache/solr/handler/TestBlobHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/TestBlobHandler.java b/solr/core/src/test/org/apache/solr/handler/TestBlobHandler.java
index 4fda926..c395d20 100644
--- a/solr/core/src/test/org/apache/solr/handler/TestBlobHandler.java
+++ b/solr/core/src/test/org/apache/solr/handler/TestBlobHandler.java
@@ -90,27 +90,33 @@ public class TestBlobHandler extends AbstractFullDistribZkTestBase {
           "field",
           "type")));
 
-      byte[] bytarr = new byte[1024];
-      for (int i = 0; i < bytarr.length; i++) bytarr[i] = (byte) (i % 127);
-      byte[] bytarr2 = new byte[2048];
-      for (int i = 0; i < bytarr2.length; i++) bytarr2[i] = (byte) (i % 127);
-      String blobName = "test";
-      postAndCheck(cloudClient, baseUrl, blobName, ByteBuffer.wrap(bytarr), 1);
-      postAndCheck(cloudClient, baseUrl, blobName, ByteBuffer.wrap(bytarr2), 2);
-
-      url = baseUrl + "/.system/blob/test/1";
-      map = TestSolrConfigHandlerConcurrent.getAsMap(url, cloudClient);
-      List l = (List) Utils.getObjectByPath(map, false, Arrays.asList("response", "docs"));
-      assertNotNull("" + map, l);
-      assertTrue("" + map, l.size() > 0);
-      map = (Map) l.get(0);
-      assertEquals("" + bytarr.length, String.valueOf(map.get("size")));
-
-      compareInputAndOutput(baseUrl + "/.system/blob/test?wt=filestream", bytarr2);
-      compareInputAndOutput(baseUrl + "/.system/blob/test/1?wt=filestream", bytarr);
+      checkBlobPost(baseUrl, cloudClient);
     }
   }
 
+  static void checkBlobPost(String baseUrl, CloudSolrClient cloudClient) throws Exception {
+    String url;
+    Map map;
+    byte[] bytarr = new byte[1024];
+    for (int i = 0; i < bytarr.length; i++) bytarr[i] = (byte) (i % 127);
+    byte[] bytarr2 = new byte[2048];
+    for (int i = 0; i < bytarr2.length; i++) bytarr2[i] = (byte) (i % 127);
+    String blobName = "test";
+    postAndCheck(cloudClient, baseUrl, blobName, ByteBuffer.wrap(bytarr), 1);
+    postAndCheck(cloudClient, baseUrl, blobName, ByteBuffer.wrap(bytarr2), 2);
+
+    url = baseUrl + "/.system/blob/test/1";
+    map = TestSolrConfigHandlerConcurrent.getAsMap(url, cloudClient);
+    List l = (List) Utils.getObjectByPath(map, false, Arrays.asList("response", "docs"));
+    assertNotNull("" + map, l);
+    assertTrue("" + map, l.size() > 0);
+    map = (Map) l.get(0);
+    assertEquals("" + bytarr.length, String.valueOf(map.get("size")));
+
+    compareInputAndOutput(baseUrl + "/.system/blob/test?wt=filestream", bytarr2, cloudClient);
+    compareInputAndOutput(baseUrl + "/.system/blob/test/1?wt=filestream", bytarr, cloudClient);
+  }
+
   public static void createSystemCollection(SolrClient client) throws SolrServerException, IOException {
     CollectionAdminResponse response1;
     CollectionAdminRequest.Create createCollectionRequest = new CollectionAdminRequest.Create()
@@ -152,7 +158,7 @@ public class TestBlobHandler extends AbstractFullDistribZkTestBase {
     return new String(Utils.toJSON(map), StandardCharsets.UTF_8);
   }
 
-  private void compareInputAndOutput(String url, byte[] bytarr) throws IOException {
+  static void compareInputAndOutput(String url, byte[] bytarr, CloudSolrClient cloudClient) throws IOException {
 
     HttpClient httpClient = cloudClient.getLbClient().getHttpClient();
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java b/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java
index 345b86d..9deb51d 100644
--- a/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java
+++ b/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java
@@ -125,6 +125,8 @@ public class TestReplicationHandler extends SolrTestCaseJ4 {
     slave.setUp();
     slaveJetty = createJetty(slave);
     slaveClient = createNewSolrClient(slaveJetty.getLocalPort());
+    
+    System.setProperty("solr.indexfetcher.sotimeout2", "45000");
   }
 
   public void clearIndexWithReplication() throws Exception {
@@ -147,6 +149,7 @@ public class TestReplicationHandler extends SolrTestCaseJ4 {
     masterClient.close();
     slaveClient.close();
     masterClient = slaveClient = null;
+    System.clearProperty("solr.indexfetcher.sotimeout");
   }
 
   private static JettySolrRunner createJetty(SolrInstance instance) throws Exception {
@@ -165,7 +168,7 @@ public class TestReplicationHandler extends SolrTestCaseJ4 {
       final String baseUrl = buildUrl(port) + "/" + DEFAULT_TEST_CORENAME;
       HttpSolrClient client = getHttpSolrClient(baseUrl);
       client.setConnectionTimeout(15000);
-      client.setSoTimeout(60000);
+      client.setSoTimeout(90000);
       return client;
     }
     catch (Exception ex) {
@@ -292,6 +295,16 @@ public class TestReplicationHandler extends SolrTestCaseJ4 {
 
   @Test
   public void doTestDetails() throws Exception {
+    slaveJetty.stop();
+    
+    slave.copyConfigFile(CONF_DIR + "solrconfig-slave.xml", "solrconfig.xml");
+    slaveJetty = createJetty(slave);
+    
+    slaveClient.close();
+    masterClient.close();
+    masterClient = createNewSolrClient(masterJetty.getLocalPort());
+    slaveClient = createNewSolrClient(slaveJetty.getLocalPort());
+    
     clearIndexWithReplication();
     { 
       NamedList<Object> details = getDetails(masterClient);
@@ -307,22 +320,34 @@ public class TestReplicationHandler extends SolrTestCaseJ4 {
     // check details on the slave a couple of times before & after fetching
     for (int i = 0; i < 3; i++) {
       NamedList<Object> details = getDetails(slaveClient);
-      List replicatedAtCount = (List) ((NamedList) details.get("slave")).get("indexReplicatedAtList");
+      assertNotNull(i + ": " + details);
+      assertNotNull(i + ": " + details.toString(), details.get("slave"));
+
       if (i > 0) {
-        assertEquals(i, replicatedAtCount.size());
+        rQuery(i, "*:*", slaveClient);
+        List replicatedAtCount = (List) ((NamedList) details.get("slave")).get("indexReplicatedAtList");
+        int tries = 0;
+        while ((replicatedAtCount == null || replicatedAtCount.size() < i) && tries++ < 5) {
+          Thread.currentThread().sleep(1000);
+          details = getDetails(slaveClient);
+          replicatedAtCount = (List) ((NamedList) details.get("slave")).get("indexReplicatedAtList");
+        }
+        
+        assertNotNull("Expected to see that the slave has replicated" + i + ": " + details.toString(), replicatedAtCount);
+        
+        // we can have more replications than we added docs because a replication can legally fail and try 
+        // again (sometimes we cannot merge into a live index and have to try again)
+        assertTrue("i:" + i + " replicationCount:" + replicatedAtCount.size(), replicatedAtCount.size() >= i); 
       }
 
-      assertEquals("slave isMaster?", 
-                   "false", details.get("isMaster"));
-      assertEquals("slave isSlave?", 
-                   "true", details.get("isSlave"));
-      assertNotNull("slave has slave section", 
-                    details.get("slave"));
+      assertEquals(i + ": " + "slave isMaster?", "false", details.get("isMaster"));
+      assertEquals(i + ": " + "slave isSlave?", "true", details.get("isSlave"));
+      assertNotNull(i + ": " + "slave has slave section", details.get("slave"));
       // SOLR-2677: assert not false negatives
       Object timesFailed = ((NamedList)details.get("slave")).get(IndexFetcher.TIMES_FAILED);
       // SOLR-7134: we can have a fail because some mock index files have no checksum, will
       // always be downloaded, and may not be able to be moved into the existing index
-      assertTrue("slave has fetch error count: " + (String)timesFailed, timesFailed == null || ((String) timesFailed).equals("1"));
+      assertTrue(i + ": " + "slave has fetch error count: " + (String)timesFailed, timesFailed == null || ((String) timesFailed).equals("1"));
 
       if (3 != i) {
         // index & fetch
@@ -544,7 +569,7 @@ public class TestReplicationHandler extends SolrTestCaseJ4 {
     assertTrue(slaveXsl.exists());
     
     checkForSingleIndex(masterJetty);
-    checkForSingleIndex(slaveJetty);
+    checkForSingleIndex(slaveJetty, true);
     
   }
 
@@ -907,6 +932,10 @@ public class TestReplicationHandler extends SolrTestCaseJ4 {
   }
 
   private void checkForSingleIndex(JettySolrRunner jetty) {
+    checkForSingleIndex(jetty, false);
+  }
+  
+  private void checkForSingleIndex(JettySolrRunner jetty, boolean afterReload) {
     CoreContainer cores = jetty.getCoreContainer();
     Collection<SolrCore> theCores = cores.getCores();
     for (SolrCore core : theCores) {
@@ -914,13 +943,27 @@ public class TestReplicationHandler extends SolrTestCaseJ4 {
       CachingDirectoryFactory dirFactory = getCachingDirectoryFactory(core);
       synchronized (dirFactory) {
         Set<String> livePaths = dirFactory.getLivePaths();
-        // one for data, one for hte index under data and one for the snapshot metadata.
-        assertEquals(livePaths.toString(), 3, livePaths.size());
+        // one for data, one for the index under data and one for the snapshot metadata.
+        // we also allow one extra index dir - it may not be removed until the core is closed
+        if (afterReload) {
+          assertTrue(livePaths.toString() + ":" + livePaths.size(), 3 == livePaths.size() || 4 == livePaths.size());
+        } else {
+          assertTrue(livePaths.toString() + ":" + livePaths.size(), 3 == livePaths.size());
+        }
+
         // :TODO: assert that one of the paths is a subpath of hte other
       }
       if (dirFactory instanceof StandardDirectoryFactory) {
         System.out.println(Arrays.asList(new File(ddir).list()));
-        assertEquals(Arrays.asList(new File(ddir).list()).toString(), 1, indexDirCount(ddir));
+        // we also allow one extra index dir - it may not be removed until the core is closed
+        int cnt = indexDirCount(ddir);
+        // if after reload, there may be 2 index dirs while the reloaded SolrCore closes.
+        if (afterReload) {
+          assertTrue("found:" + cnt + Arrays.asList(new File(ddir).list()).toString(), 1 == cnt || 2 == cnt);
+        } else {
+          assertTrue("found:" + cnt + Arrays.asList(new File(ddir).list()).toString(), 1 == cnt);
+        }
+
       }
     }
   }
@@ -1337,17 +1380,8 @@ public class TestReplicationHandler extends SolrTestCaseJ4 {
     SolrDocumentList slaveQueryResult2 = (SolrDocumentList) slaveQueryRsp2.get("response");
     assertEquals(1, slaveQueryResult2.getNumFound());
     
-    index(slaveClient, "id", "2001", "name", "name = " + 2001, "newname", "n2001");
-    slaveClient.commit();
-
-    slaveQueryRsp = rQuery(1, "id:2001", slaveClient);
-    final SolrDocumentList sdl = (SolrDocumentList) slaveQueryRsp.get("response");
-    assertEquals(1, sdl.getNumFound());
-    final SolrDocument d = sdl.get(0);
-    assertEquals("n2001", (String) d.getFieldValue("newname"));
-    
     checkForSingleIndex(masterJetty);
-    checkForSingleIndex(slaveJetty);
+    checkForSingleIndex(slaveJetty, true);
   }
 
   @Test
@@ -1424,6 +1458,22 @@ public class TestReplicationHandler extends SolrTestCaseJ4 {
     assertTrue(timeTakenInSeconds - approximateTimeInSeconds > 0);
   }
 
+  @Test
+  public void doTestIllegalFilePaths() throws Exception {
+    // Loop through the file=, cf=, tlogFile= params and prove that it throws exception for path traversal attempts
+    String absFile = Paths.get("foo").toAbsolutePath().toString();
+    List<String> illegalFilenames = Arrays.asList(absFile, "../dir/traversal", "illegal\rfile\nname\t");
+    List<String> params = Arrays.asList(ReplicationHandler.FILE, ReplicationHandler.CONF_FILE_SHORT, ReplicationHandler.TLOG_FILE);
+    for (String param : params) {
+      for (String filename : illegalFilenames) {
+        try {
+          invokeReplicationCommand(masterJetty.getLocalPort(), "filecontent&" + param + "=" + filename);
+          fail("Should have thrown exception on illegal path for param " + param + " and file name " + filename);
+        } catch (Exception e) {}
+      }
+    }
+  }
+  
   private class AddExtraDocs implements Runnable {
 
     SolrClient masterClient;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/4fc5a9f0/solr/core/src/test/org/apache/solr/handler/TestSystemCollAutoCreate.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/TestSystemCollAutoCreate.java b/solr/core/src/test/org/apache/solr/handler/TestSystemCollAutoCreate.java
new file mode 100644
index 0000000..cadda58
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/handler/TestSystemCollAutoCreate.java
@@ -0,0 +1,29 @@
+/*
+ * 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.handler;
+
+
+import org.apache.solr.cloud.AbstractFullDistribZkTestBase;
+import org.apache.solr.common.cloud.DocCollection;
+
+public class TestSystemCollAutoCreate extends AbstractFullDistribZkTestBase {
+  public void testAutoCreate() throws Exception {
+    TestBlobHandler.checkBlobPost(cloudJettys.get(0).jetty.getBaseUrl().toExternalForm(), cloudClient);
+    DocCollection sysColl = cloudClient.getZkStateReader().getClusterState().getCollection(".system");
+  }
+}