wave13: 514/239 — flink/nifi/artemis + K8s/cilium/linkerd2 + ES/OpenSearch/Solr + hadoop/hbase/spark
This commit is contained in:
parent
424a2a7787
commit
8f0bc73afa
32 changed files with 3977 additions and 5 deletions
|
|
@ -0,0 +1,55 @@
|
|||
# solr-003: SplitShardCmd O(n²) subSlices.contains in loop over all collection slices
|
||||
|
||||
## Classification
|
||||
- **CWE**: CWE-407 (Inefficient Algorithmic Complexity)
|
||||
- **Severity**: MEDIUM
|
||||
- **Path**: Shard split rollback cleanup — `SplitShardCmd.cleanupAfterFailedSplit()`
|
||||
|
||||
## Location
|
||||
`solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java:985`
|
||||
|
||||
## Defect
|
||||
|
||||
```java
|
||||
List<String> subSlices = new ArrayList<>();
|
||||
// subSlices is populated with the newly created sub-shard names (at most MAX_NUM_SUB_SHARDS = 8)
|
||||
|
||||
// In cleanupAfterFailedSplit() — called during shard split failure/rollback:
|
||||
for (Slice s : coll.getSlices()) { // O(S) — all slices in collection
|
||||
if (!subSlices.contains(s.getName())) { // O(n) — linear scan each time
|
||||
continue;
|
||||
}
|
||||
propMap.put(s.getName(), Slice.State.CONSTRUCTION.toString());
|
||||
sendUpdateState = true;
|
||||
}
|
||||
```
|
||||
|
||||
**Total complexity:** O(S × n) where S = total slices in the collection, n = subSlices count.
|
||||
|
||||
For a large SolrCloud collection with many shards (S = 1000+), each cleanup scan costs O(S × 8)
|
||||
comparisons rather than O(S). While subSlices is capped at 8, the outer loop is not. In a
|
||||
large collection during a failed split this runs at O(8,000) comparisons vs O(1,008) with a Set.
|
||||
|
||||
## Fix
|
||||
|
||||
Convert to `HashSet<String>` before the loop:
|
||||
|
||||
```java
|
||||
Set<String> subSliceSet = new HashSet<>(subSlices);
|
||||
|
||||
for (Slice s : coll.getSlices()) {
|
||||
if (!subSliceSet.contains(s.getName())) { // O(1)
|
||||
continue;
|
||||
}
|
||||
propMap.put(s.getName(), Slice.State.CONSTRUCTION.toString());
|
||||
sendUpdateState = true;
|
||||
}
|
||||
```
|
||||
|
||||
**Result:** O(S) — single pass with O(1) lookup.
|
||||
|
||||
## Severity Rationale
|
||||
|
||||
The `cleanupAfterFailedSplit` path is not called on every request, but it is invoked during
|
||||
split operations which can be triggered frequently in large automated cluster management
|
||||
pipelines. The larger the collection, the more expensive the cleanup.
|
||||
Loading…
Add table
Add a link
Reference in a new issue