### 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
this.clusters = clusters;
        this.timeProvider = timeProvider;
        
        Map<String, Integer> skippedByClusterAlias = partitionCountsByClusterAlias(skipped);
        
        Map<String, Integer> totalByClusterAlias = partitionCountsByClusterAlias(shards);
        skippedByClusterAlias.forEach((cluster, count) -> totalByClusterAlias.merge(cluster, count, Integer::sum));
        for (Map.Entry<String, Integer> entry : totalByClusterAlias.entrySet()) {
            String clusterAlias = entry.getKey();
            AtomicReference<SearchResponse.Cluster> clusterRef = clusters.getCluster(clusterAlias);
            assert clusterRef.get().getTotalShards() == null : "total shards should not be set on a Cluster before onListShards";
            int totalCount = entry.getValue();
            int skippedCount = skippedByClusterAlias.getOrDefault(clusterAlias, 0);
            TimeValue took = null;
            boolean swapped;
            do {
                SearchResponse.Cluster curr = clusterRef.get();
                SearchResponse.Cluster.Status status = curr.getStatus();
                assert status == SearchResponse.Cluster.Status.RUNNING : "should have RUNNING status during onListShards but has " + status;
                
                if (skippedCount == totalCount) {
                    took = new TimeValue(timeProvider.buildTookInMillis());
                    status = SearchResponse.Cluster.Status.SUCCESSFUL;
                }
                SearchResponse.Cluster updated = new SearchResponse.Cluster.Builder(curr).setStatus(status)
                    .setTotalShards(totalCount)
                    .setSuccessfulShards(skippedCount)
                    .setSkippedShards(skippedCount)
                    .setFailedShards(0)
                    .setTook(took)