5353import static org .elasticsearch .repositories .gcs .GoogleCloudStorageClientSettings .PROJECT_ID_SETTING ;
5454import static org .elasticsearch .repositories .gcs .GoogleCloudStorageClientSettings .READ_TIMEOUT_SETTING ;
5555import static org .elasticsearch .repositories .gcs .GoogleCloudStorageOperationsStats .Operation ;
56+ import static org .elasticsearch .repositories .gcs .GoogleCloudStorageOperationsStats .Operation .GET_METADATA ;
5657import static org .elasticsearch .repositories .gcs .GoogleCloudStorageOperationsStats .Operation .GET_OBJECT ;
58+ import static org .elasticsearch .repositories .gcs .GoogleCloudStorageOperationsStats .Operation .LIST_OBJECTS ;
5759import static org .elasticsearch .repositories .gcs .GoogleCloudStorageOperationsStats .Operation .MULTIPART_UPLOAD ;
5860import static org .elasticsearch .repositories .gcs .GoogleCloudStorageOperationsStats .Operation .RESUMABLE_UPLOAD ;
5961
@@ -129,12 +131,12 @@ public void testSingleMultipartWrite() throws Exception {
129131 final BytesArray blobContents = new BytesArray (randomByteArrayOfLength (blobLength ));
130132 container .writeBlob (purpose , blobName , blobContents , true );
131133
132- var wantStats = new StatsMap ();
133- assertStatsEquals (wantStats .add (purpose , MULTIPART_UPLOAD , 1 , 1 ), store .stats ());
134+ final StatsMap wantStats = new StatsMap (purpose );
135+ assertStatsEquals (wantStats .add (MULTIPART_UPLOAD , 1 , 1 ), store .stats ());
134136 try (InputStream is = container .readBlob (purpose , blobName )) {
135137 assertEquals (blobContents , Streams .readFully (is ));
136138 }
137- assertStatsEquals (wantStats .add (purpose , GET_OBJECT , 1 , 1 ), store .stats ());
139+ assertStatsEquals (wantStats .add (GET_OBJECT , 1 , 1 ), store .stats ());
138140 }
139141
140142 @ Test
@@ -153,14 +155,14 @@ public void testResumableWrite() throws Exception {
153155
154156 // a resumable upload sends at least 2 requests, a POST with metadata only and multiple PUTs with SDK_DEFAULT_CHUNK_SIZE
155157 // the +1 means a POST request with metadata without PAYLOAD
156- var totalRequests = parts + 1 ;
157- var wantStats = new StatsMap ();
158- assertStatsEquals (wantStats .add (purpose , RESUMABLE_UPLOAD , 1 , totalRequests ), store .stats ());
158+ final int totalRequests = parts + 1 ;
159+ final StatsMap wantStats = new StatsMap (purpose );
160+ assertStatsEquals (wantStats .add (RESUMABLE_UPLOAD , 1 , totalRequests ), store .stats ());
159161
160162 try (InputStream is = container .readBlob (purpose , blobName )) {
161163 assertEquals (blobContents , Streams .readFully (is ));
162164 }
163- assertStatsEquals (wantStats .add (purpose , GET_OBJECT , 1 , 1 ), store .stats ());
165+ assertStatsEquals (wantStats .add (GET_OBJECT , 1 , 1 ), store .stats ());
164166 }
165167
166168 @ Test
@@ -171,14 +173,16 @@ public void testDeleteDirectory() throws Exception {
171173 final String directoryName = randomIdentifier ();
172174 final BytesArray contents = new BytesArray (randomByteArrayOfLength (50 ));
173175 final int numberOfFiles = randomIntBetween (1 , 20 );
176+ final OperationPurpose purpose = randomPurpose ();
174177 for (int i = 0 ; i < numberOfFiles ; i ++) {
175- container .writeBlob (randomPurpose () , String .format ("%s/file_%d" , directoryName , i ), contents , true );
178+ container .writeBlob (purpose , String .format ("%s/file_%d" , directoryName , i ), contents , true );
176179 }
177- assertEquals (createStats (numberOfFiles , 0 , 0 ), store .stats ());
180+ final StatsMap wantStats = new StatsMap (purpose );
181+ assertStatsEquals (wantStats .add (MULTIPART_UPLOAD , numberOfFiles , numberOfFiles ), store .stats ());
178182
179- container .delete (randomPurpose () );
183+ container .delete (purpose );
180184 // We only count the list because we can't track the bulk delete
181- assertEquals ( createStats ( numberOfFiles , 1 , 0 ), store .stats ());
185+ assertStatsEquals ( wantStats . add ( LIST_OBJECTS , 1 , 1 ), store .stats ());
182186 }
183187
184188 @ Test
@@ -191,15 +195,18 @@ public void testListBlobsAccountsForPaging() throws Exception {
191195 final int numberOfPages = randomIntBetween (1 , 10 );
192196 final int numberOfObjects = randomIntBetween ((numberOfPages - 1 ) * pageSize , numberOfPages * pageSize - 1 );
193197 final BytesArray contents = new BytesArray (randomByteArrayOfLength (50 ));
198+ final OperationPurpose purpose = randomPurpose ();
194199 for (int i = 0 ; i < numberOfObjects ; i ++) {
195- container .writeBlob (randomPurpose () , String .format ("file_%d" , i ), contents , true );
200+ container .writeBlob (purpose , String .format ("file_%d" , i ), contents , true );
196201 }
197- assertEquals (createStats (numberOfObjects , 0 , 0 ), store .stats ());
202+ final StatsMap wantStats = new StatsMap (purpose );
203+ assertStatsEquals (wantStats .add (MULTIPART_UPLOAD , numberOfObjects , numberOfObjects ), store .stats ());
198204
199- final Map <String , BlobMetadata > stringBlobMetadataMap = container .listBlobs (randomPurpose () );
205+ final Map <String , BlobMetadata > stringBlobMetadataMap = container .listBlobs (purpose );
200206 assertEquals (numberOfObjects , stringBlobMetadataMap .size ());
207+
201208 // There should be {numberOfPages} pages of blobs
202- assertEquals ( createStats ( numberOfObjects , numberOfPages , 0 ), store .stats ());
209+ assertStatsEquals ( wantStats . add ( LIST_OBJECTS , numberOfPages , numberOfPages ), store .stats ());
203210 }
204211
205212 public void testCompareAndSetRegister () {
@@ -209,32 +216,23 @@ public void testCompareAndSetRegister() {
209216 // update from empty (adds a single insert)
210217 final BytesArray contents = new BytesArray (randomByteArrayOfLength (BlobContainerUtils .MAX_REGISTER_CONTENT_LENGTH ));
211218 final String registerName = randomIdentifier ();
212- assertTrue (safeAwait (l -> container .compareAndSetRegister (randomPurpose (), registerName , BytesArray .EMPTY , contents , l )));
213- assertEquals (createStats (1 , 0 , 0 ), store .stats ());
219+ final OperationPurpose purpose = randomPurpose ();
220+ assertTrue (safeAwait (l -> container .compareAndSetRegister (purpose , registerName , BytesArray .EMPTY , contents , l )));
221+ final StatsMap wantStat = new StatsMap (purpose );
222+ assertStatsEquals (wantStat .add (GET_METADATA , 1 , 1 ).add (MULTIPART_UPLOAD , 1 , 1 ), store .stats ());
214223
215224 // successful update from non-null (adds two gets, one insert)
216225 final BytesArray nextContents = new BytesArray (randomByteArrayOfLength (BlobContainerUtils .MAX_REGISTER_CONTENT_LENGTH ));
217- assertTrue (safeAwait (l -> container .compareAndSetRegister (randomPurpose () , registerName , contents , nextContents , l )));
218- assertEquals ( createStats ( 2 , 0 , 2 ), store .stats ());
226+ assertTrue (safeAwait (l -> container .compareAndSetRegister (purpose , registerName , contents , nextContents , l )));
227+ assertStatsEquals ( wantStat . add ( GET_METADATA , 1 , 1 ). add ( GET_OBJECT , 1 , 1 ). add ( MULTIPART_UPLOAD , 1 , 1 ), store .stats ());
219228
220229 // failed update (adds two gets, zero inserts)
221230 final BytesArray wrongContents = randomValueOtherThan (
222231 nextContents ,
223232 () -> new BytesArray (randomByteArrayOfLength (BlobContainerUtils .MAX_REGISTER_CONTENT_LENGTH ))
224233 );
225- assertFalse (safeAwait (l -> container .compareAndSetRegister (randomPurpose (), registerName , wrongContents , contents , l )));
226- assertEquals (createStats (2 , 0 , 4 ), store .stats ());
227- }
228-
229- private Map <String , BlobStoreActionStats > createStats (int insertCount , int listCount , int getCount ) {
230- return Map .of (
231- "GetObject" ,
232- new BlobStoreActionStats (getCount , getCount ),
233- "ListObjects" ,
234- new BlobStoreActionStats (listCount , listCount ),
235- "InsertObject" ,
236- new BlobStoreActionStats (insertCount , insertCount )
237- );
234+ assertFalse (safeAwait (l -> container .compareAndSetRegister (purpose , registerName , wrongContents , contents , l )));
235+ assertStatsEquals (wantStat .add (GET_METADATA , 1 , 1 ).add (GET_OBJECT , 1 , 1 ), store .stats ());
238236 }
239237
240238 private ContainerAndBlobStore createBlobContainer (final String repositoryName ) throws Exception {
@@ -276,18 +274,37 @@ protected String getEndpointForServer(final HttpServer server) {
276274 }
277275
278276 static class StatsMap extends HashMap <String , BlobStoreActionStats > {
277+ private final OperationPurpose purpose ;
278+
279279 StatsMap () {
280- for (var purpose : OperationPurpose .values ()) {
281- for (var operation : Operation .values ()) {
282- put (purpose + "_" + operation , new BlobStoreActionStats (0 , 0 ));
280+ this (null );
281+ }
282+
283+ StatsMap (OperationPurpose purpose ) {
284+ this .purpose = purpose ;
285+ for (var p : OperationPurpose .values ()) {
286+ for (var o : Operation .values ()) {
287+ put (p + "_" + o , new BlobStoreActionStats (0 , 0 ));
283288 }
284289 }
285290 }
286291
287292 StatsMap add (OperationPurpose purpose , Operation operation , long ops , long reqs ) {
288- put (purpose + "_" + operation , new BlobStoreActionStats (ops , reqs ));
293+ compute (purpose + "_" + operation , (k , v ) -> {
294+ BlobStoreActionStats stats ;
295+ if (v == null ) {
296+ stats = new BlobStoreActionStats (ops , reqs );
297+ } else {
298+ stats = new BlobStoreActionStats (v .operations () + ops , v .requests () + reqs );
299+ }
300+ return stats ;
301+ });
289302 return this ;
290303 }
304+
305+ StatsMap add (Operation operation , long ops , long reqs ) {
306+ return add (purpose , operation , ops , reqs );
307+ }
291308 }
292309
293310 private record ContainerAndBlobStore (GoogleCloudStorageBlobContainer blobContainer , GoogleCloudStorageBlobStore blobStore )
0 commit comments