### Description

`SearchResponse.Clusters` currently uses a `HashMap<String, AtomicReference>` for storing Cluster objects. The AtomicReference CAS swaps are done in a do/while loop in most cases (e.g., in `CCSSingleCoordinatorSearchProgressListener`).

This can be replaced with a `ConcurrentHashMap` in conjunction with either `compute()` method or the `replace(key, assumed_previous_value, value)` method for atomically swapping in a new Cluster object with a CAS operation, assuring that the updates don't lose data from competing threads doing separate Cluster object updates.

See: https://github.com/elastic/elasticsearch/pull/98457/files#r1310467586 
server/src/main/java/org/elasticsearch/action/search/CCSSingleCoordinatorSearchProgressListener.java
SearchResponse.Cluster curr = clusterRef.get();
            SearchResponse.Cluster.Status status = SearchResponse.Cluster.Status.RUNNING;
            int numFailedShards = curr.getFailedShards() == null ? 1 : curr.getFailedShards() + 1;
            assert curr.getTotalShards() != null : "total shards should be set on the Cluster but not for " + clusterAlias;
            if (curr.getTotalShards() == numFailedShards) {
                if (curr.isSkipUnavailable()) {
                    status = SearchResponse.Cluster.Status.SKIPPED;
                } else {
                    status = SearchResponse.Cluster.Status.FAILED;
                    
                }
            } else if (curr.getTotalShards() == numFailedShards + curr.getSuccessfulShards()) {
                status = SearchResponse.Cluster.Status.PARTIAL;
                took = new TimeValue(timeProvider.buildTookInMillis());
            }
            
            List<ShardSearchFailure> failures = CollectionUtils.appendToCopy(curr.getFailures(), new ShardSearchFailure(e, shardTarget));
            SearchResponse.Cluster updated = new SearchResponse.Cluster.Builder(curr).setStatus(status)
                .setFailedShards(numFailedShards)
                .setFailures(failures)
                .setTook(took)
                .build();
            swapped = clusterRef.compareAndSet(curr, updated);
        } while (swapped == false);
    }
    /**
     * Executed when a partial reduce is created. The number of partial reduce can be controlled via
     * {@link SearchRequest#setBatchedReduceSize(int)}.
     *
     * Note that onPartialReduce and onFinalReduce are called with cumulative data so far.