@@ -52,15 +52,14 @@ public boolean isTransient() {
5252 }
5353 }
5454
55- private record PendingWrite (String key , HashIndex index , BytesWithFlag bytes ) {}
56-
57- private Map <String , Map <String , Map <HashIndex , BytesWithFlag >>> instanceMaps = new HashMap <>();
55+ private record PendingWrite (HashItem key , HashIndex index , BytesWithFlag bytes ) {}
5856
5957 private final Supplier <HashIndex > hashIndexSupplier ;
6058 private final LRUCache <String , Map <String , Map <HashIndex , BytesWithFlag >>> mappingInfo ;
6159
6260 private final Function <String , Map <String , Map <HashIndex , byte []>>> retriever ;
6361 private final Consumer <Map <String , List <HashMappingInfo >>> writer ;
62+ private final Map <String , List <PendingWrite >> pending = new HashMap <>();
6463
6564 protected HashMappingCoordinator (
6665 LRUCache <String , Map <String , Map <HashIndex , BytesWithFlag >>> mappingInfo ,
@@ -73,58 +72,53 @@ protected HashMappingCoordinator(
7372 this .writer = writer ;
7473 }
7574
76- private Map <String , List <PendingWrite >> pending = new HashMap <>();
77-
7875 private HashMappingInfo from (PendingWrite pending ) {
7976 return new HashMappingInfo (pending .key , pending .index , pending .bytes .bytes );
8077 }
8178
8279 public HashIndex calculateIndex (String instanceId , HashItem item , byte [] bytes ) {
83- Map <String , Map <HashIndex , BytesWithFlag >> instanceMap = getCachedInstanceMap (instanceId );
80+ List <PendingWrite > list =
81+ pending .computeIfAbsent (
82+ instanceId ,
83+ k -> {
84+ mappingInfo .pin (k );
85+ return new ArrayList <>();
86+ });
87+ Map <String , Map <HashIndex , BytesWithFlag >> instanceMap = getInstanceMap (instanceId );
8488 String key = item .key ();
8589 synchronized (instanceMap ) {
8690 Map <HashIndex , BytesWithFlag > duplicateMap =
8791 instanceMap .computeIfAbsent (key , __ -> new HashMap <>());
88-
8992 for (Entry <HashIndex , BytesWithFlag > entry : duplicateMap .entrySet ()) {
9093 if (Arrays .equals (entry .getValue ().bytes , bytes )) {
9194 if (entry .getValue ().isTransient ()) {
92- addWrite (instanceId , key , entry .getKey (), entry .getValue ());
95+ addWrite (list , item , entry .getKey (), entry .getValue ());
9396 }
9497 return entry .getKey ();
9598 }
9699 }
97100 HashIndex index = hashIndexSupplier .get ();
98101 BytesWithFlag bytesWithFlag = new BytesWithFlag (bytes );
99102 duplicateMap .put (index , bytesWithFlag );
100- addWrite (instanceId , key , index , bytesWithFlag );
103+ addWrite (list , item , index , bytesWithFlag );
101104 return index ;
102105 }
103106 }
104107
105- private void addWrite (String instanceId , String key , HashIndex index , BytesWithFlag bytes ) {
106- pending
107- .computeIfAbsent (instanceId , __ -> new ArrayList <>())
108- .add (new PendingWrite (key , index , bytes ));
108+ private void addWrite (
109+ List <PendingWrite > list , HashItem key , HashIndex index , BytesWithFlag bytes ) {
110+ list .add (new PendingWrite (key , index , bytes ));
109111 }
110112
111113 public Optional <byte []> readBytes (String instanceId , HashItem item , HashIndex index ) {
112114 Map <String , Map <HashIndex , BytesWithFlag >> instanceMap = getInstanceMap (instanceId );
113- try {
114- synchronized (instanceMap ) {
115- return Optional .ofNullable (instanceMap .get (item .key ()))
116- .map (m -> m .get (index ))
117- .map (bytes -> bytes .bytes );
118- }
119- } finally {
120- mappingInfo .unpin (instanceId );
115+ synchronized (instanceMap ) {
116+ return Optional .ofNullable (instanceMap .get (item .key ()))
117+ .map (m -> m .get (index ))
118+ .map (bytes -> bytes .bytes );
121119 }
122120 }
123121
124- private Map <String , Map <HashIndex , BytesWithFlag >> getCachedInstanceMap (String instanceId ) {
125- return instanceMaps .computeIfAbsent (instanceId , k -> getInstanceMap (instanceId ));
126- }
127-
128122 private Map <String , Map <HashIndex , BytesWithFlag >> getInstanceMap (String instanceId ) {
129123 return mappingInfo .computeIfAbsent (
130124 instanceId ,
@@ -146,7 +140,6 @@ public void persist() {
146140 for (Map .Entry <String , List <PendingWrite >> item : pending .entrySet ()) {
147141 String instanceId = item .getKey ();
148142 List <HashMappingInfo > list = new ArrayList <>();
149- result .put (instanceId , list );
150143 Map <String , Map <HashIndex , BytesWithFlag >> instanceMap = mappingInfo .get (instanceId );
151144 if (instanceMap != null ) {
152145 synchronized (instanceMap ) {
@@ -159,6 +152,9 @@ public void persist() {
159152 });
160153 }
161154 }
155+ if (!list .isEmpty ()) {
156+ result .put (instanceId , list );
157+ }
162158 }
163159 writer .accept (result );
164160 }
@@ -181,14 +177,12 @@ public void afterRollback() {
181177 }
182178
183179 private void cleanUp () {
184- instanceMaps .keySet ().forEach (mappingInfo ::unpin );
185- instanceMaps .clear ();
180+ pending .keySet ().forEach (mappingInfo ::unpin );
186181 pending .clear ();
187182 }
188183
189184 public void afterRemove (String instanceId ) {
190185 pending .remove (instanceId );
191- instanceMaps .remove (instanceId );
192186 mappingInfo .remove (instanceId );
193187 }
194188}
0 commit comments