1010
1111import org .opensearch .common .annotation .ExperimentalApi ;
1212
13+ import java .util .Collections ;
1314import java .util .List ;
1415import java .util .concurrent .locks .Lock ;
1516import java .util .concurrent .locks .ReentrantLock ;
@@ -46,9 +47,9 @@ public class StatsHolder {
4647 private final String storeName ;
4748
4849 public StatsHolder (List <String > dimensionNames , String storeName ) {
49- this .dimensionNames = dimensionNames ;
50+ this .dimensionNames = Collections . unmodifiableList ( dimensionNames ) ;
5051 this .storeName = storeName ;
51- this .statsRoot = new DimensionNode (null , true ); // The root node has no dimension value associated with it, only children
52+ this .statsRoot = new DimensionNode ("" , true ); // The root node has the empty string as its dimension value
5253 }
5354
5455 public List <String > getDimensionNames () {
@@ -110,7 +111,17 @@ public long count() {
110111
111112 private void internalIncrement (List <String > dimensionValues , Consumer <DimensionNode > adder , boolean createNodesIfAbsent ) {
112113 assert dimensionValues .size () == dimensionNames .size ();
113- internalIncrementHelper (dimensionValues , statsRoot , 0 , adder , createNodesIfAbsent );
114+ // First try to increment without creating nodes
115+ boolean didIncrement = internalIncrementHelper (dimensionValues , statsRoot , 0 , adder , false );
116+ // If we failed to increment, because nodes had to be created, obtain the lock and run again while creating nodes if needed
117+ if (!didIncrement ) {
118+ try {
119+ lock .lock ();
120+ internalIncrementHelper (dimensionValues , statsRoot , 0 , adder , createNodesIfAbsent );
121+ } finally {
122+ lock .unlock ();
123+ }
124+ }
114125 }
115126
116127 /**
@@ -134,14 +145,8 @@ private boolean internalIncrementHelper(
134145 DimensionNode child = node .getChild (dimensionValues .get (depth ));
135146 if (child == null ) {
136147 if (createNodesIfAbsent ) {
137- // If we have to create a new node, obtain the lock first
138148 boolean createMapInChild = depth < dimensionValues .size () - 1 ;
139- lock .lock ();
140- try {
141- child = node .createChild (dimensionValues .get (depth ), createMapInChild );
142- } finally {
143- lock .unlock ();
144- }
149+ child = node .createChild (dimensionValues .get (depth ), createMapInChild );
145150 } else {
146151 return false ;
147152 }
@@ -158,7 +163,7 @@ private boolean internalIncrementHelper(
158163 * Produce an immutable CacheStats representation of these stats.
159164 */
160165 public CacheStats getCacheStats () {
161- MDCSDimensionNode snapshot = new MDCSDimensionNode (null , true , statsRoot .getStatsSnapshot ());
166+ MDCSDimensionNode snapshot = new MDCSDimensionNode ("" , true , statsRoot .getStatsSnapshot ());
162167 // Traverse the tree and build a corresponding tree of MDCSDimensionNode, to pass to MultiDimensionCacheStats.
163168 if (statsRoot .getChildren () != null ) {
164169 for (DimensionNode child : statsRoot .getChildren ().values ()) {
0 commit comments