19
19
20
20
import org .apache .mnemonic .EntityFactoryProxy ;
21
21
import org .apache .mnemonic .DurableType ;
22
+ import org .apache .mnemonic .Durable ;
22
23
import org .apache .mnemonic .MemChunkHolder ;
23
24
import org .apache .mnemonic .MemoryDurableEntity ;
24
25
import org .apache .mnemonic .OutOfHybridMemory ;
@@ -81,7 +82,7 @@ public void setCapacityHint(long capacity) {
81
82
* @return previous value with key else return null
82
83
*/
83
84
@ Override
84
- public V put (K key , V value ) {
85
+ public V put (K key , V value ) throws OutOfHybridMemory {
85
86
int hash = hash (key .hashCode ());
86
87
long bucketIndex = getBucketIndex (hash );
87
88
long bucketAddr = holder .get () + MAX_OBJECT_SIZE * bucketIndex ;
@@ -106,13 +107,24 @@ public V put(K key, V value) {
106
107
*
107
108
* @return previous value with key else return null
108
109
*/
109
- public V addEntry (K key , V value , long bucketAddr ) {
110
+ protected V addEntry (K key , V value , long bucketAddr ) throws OutOfHybridMemory {
110
111
V retValue = null ;
111
112
long handler = unsafe .getAddress (bucketAddr );
112
113
if (0L == handler ) {
113
- DurableSinglyLinkedList <MapEntry <K , V >> head = DurableSinglyLinkedListFactory .create (allocator ,
114
- listefproxies , listgftypes , false );
115
- MapEntry <K , V > entry = MapEntryFactory .create (allocator , factoryProxy , genericField , false );
114
+ DurableSinglyLinkedList <MapEntry <K , V >> head = null ;
115
+ MapEntry <K , V > entry = null ;
116
+ try {
117
+ head = DurableSinglyLinkedListFactory .create (allocator , listefproxies , listgftypes , false );
118
+ entry = MapEntryFactory .create (allocator , factoryProxy , genericField , false );
119
+ } catch (OutOfHybridMemory fe ) {
120
+ if (null != head ) {
121
+ head .destroy ();
122
+ }
123
+ if (null != entry ) {
124
+ entry .destroy ();
125
+ }
126
+ throw fe ;
127
+ }
116
128
entry .setKey (key , false );
117
129
entry .setValue (value , false );
118
130
head .setItem (entry , false );
@@ -128,17 +140,32 @@ public V addEntry(K key, V value, long bucketAddr) {
128
140
K entryKey = mapEntry .getKey ();
129
141
if (entryKey == key || entryKey .equals (key )) {
130
142
retValue = mapEntry .getValue ();
131
- mapEntry .setValue (value , false );
143
+ if (retValue instanceof Durable ) {
144
+ mapEntry .setValue (value , false );
145
+ } else {
146
+ mapEntry .setValue (value , true );
147
+ }
132
148
found = true ;
133
149
break ;
134
150
}
135
151
prev = head ;
136
152
head = head .getNext ();
137
153
}
138
154
if (true != found ) {
139
- DurableSinglyLinkedList <MapEntry <K , V >> newNode = DurableSinglyLinkedListFactory .create (allocator ,
140
- listefproxies , listgftypes , false );
141
- MapEntry <K , V > entry = MapEntryFactory .create (allocator , factoryProxy , genericField , false );
155
+ DurableSinglyLinkedList <MapEntry <K , V >> newNode = null ;
156
+ MapEntry <K , V > entry = null ;
157
+ try {
158
+ newNode = DurableSinglyLinkedListFactory .create (allocator , listefproxies , listgftypes , false );
159
+ entry = MapEntryFactory .create (allocator , factoryProxy , genericField , false );
160
+ } catch (OutOfHybridMemory fe ) {
161
+ if (null != newNode ) {
162
+ newNode .destroy ();
163
+ }
164
+ if (null != entry ) {
165
+ entry .destroy ();
166
+ }
167
+ throw fe ;
168
+ }
142
169
entry .setKey (key , false );
143
170
entry .setValue (value , false );
144
171
newNode .setItem (entry , false );
@@ -176,7 +203,7 @@ public V get(K key) {
176
203
*
177
204
* @return previous value with key else return null
178
205
*/
179
- public V getEntry (K key , long bucketAddr ) {
206
+ protected V getEntry (K key , long bucketAddr ) {
180
207
V retValue = null ;
181
208
long handler = unsafe .getAddress (bucketAddr );
182
209
if (0L != handler ) {
@@ -222,7 +249,7 @@ public V remove(K key) {
222
249
*
223
250
* @return previous value with key else return null
224
251
*/
225
- public V removeEntry (K key , long bucketAddr ) {
252
+ protected V removeEntry (K key , long bucketAddr ) {
226
253
V retValue = null ;
227
254
long handler = unsafe .getAddress (bucketAddr );
228
255
if (0L != handler ) {
@@ -248,13 +275,11 @@ public V removeEntry(K key, long bucketAddr) {
248
275
head .destroy ();
249
276
} else {
250
277
unsafe .putAddress (bucketAddr , head .getNext ().getHandler ());
251
- head .setNext (null , false );
252
- head .destroy (); // #TODO: better way to delete one node
278
+ head .destroy ();
253
279
}
254
280
} else {
255
281
prev .setNext (head .getNext (), false );
256
- head .setNext (null , false );
257
- head .destroy (); // #TODO: better way to delete one node
282
+ head .destroy ();
258
283
}
259
284
mapSize --;
260
285
}
@@ -272,9 +297,14 @@ public void resize(long newCapacity) {
272
297
MemChunkHolder <A > prevHolder = holder ;
273
298
long bucketAddr = prevHolder .get ();
274
299
long maxbucketAddr = bucketAddr + MAX_OBJECT_SIZE * totalCapacity ;
300
+ holder = allocator .createChunk (MAX_OBJECT_SIZE * newCapacity , autoReclaim );
301
+ if (null == holder ) {
302
+ autoResize = false ;
303
+ holder = prevHolder ;
304
+ return ;
305
+ }
275
306
totalCapacity = newCapacity ;
276
307
threshold = (long ) (totalCapacity * DEFAULT_MAP_LOAD_FACTOR );
277
- holder = allocator .createChunk (MAX_OBJECT_SIZE * totalCapacity , autoReclaim );
278
308
unsafe .putLong (chunkAddr .get (), allocator .getChunkHandler (holder ));
279
309
while (bucketAddr < maxbucketAddr ) {
280
310
long handler = unsafe .getAddress (bucketAddr );
@@ -299,7 +329,7 @@ public void resize(long newCapacity) {
299
329
* @param elem
300
330
* the item in the old map
301
331
*/
302
- public void transfer (DurableSinglyLinkedList <MapEntry <K , V >> elem ) {
332
+ protected void transfer (DurableSinglyLinkedList <MapEntry <K , V >> elem ) {
303
333
int hash = hash (elem .getItem ().getKey ().hashCode ());
304
334
long bucketIndex = getBucketIndex (hash );
305
335
long bucketAddr = holder .get () + MAX_OBJECT_SIZE * bucketIndex ;
@@ -318,7 +348,7 @@ public void transfer(DurableSinglyLinkedList<MapEntry<K, V>> elem) {
318
348
* Recomputes the size of the map during restore without persistence
319
349
*
320
350
*/
321
- public long recomputeMapSize () {
351
+ protected long recomputeMapSize () {
322
352
long size = 0 ;
323
353
long bucketAddr = holder .get ();
324
354
long maxbucketAddr = bucketAddr + MAX_OBJECT_SIZE * totalCapacity ;
@@ -351,13 +381,19 @@ public long[][] getNativeFieldInfo() {
351
381
public void destroy () throws RetrieveDurableEntityError {
352
382
long bucketAddr = holder .get ();
353
383
long maxbucketAddr = bucketAddr + MAX_OBJECT_SIZE * totalCapacity ;
384
+ DurableSinglyLinkedList <MapEntry <K , V >> head , prev ;
354
385
while (bucketAddr < maxbucketAddr ) {
355
386
long handler = unsafe .getAddress (bucketAddr );
356
387
if (0L != handler ) {
357
- DurableSinglyLinkedList < MapEntry < K , V >> head = DurableSinglyLinkedListFactory .restore (allocator ,
388
+ head = DurableSinglyLinkedListFactory .restore (allocator ,
358
389
listefproxies , listgftypes , handler , false );
359
- head .destroy ();
390
+ prev = head ;
391
+ while (null != head ) {
392
+ head = head .getNext ();
393
+ prev .destroy (); //TODO: Destroy head in a cascading way
394
+ prev = head ;
360
395
}
396
+ }
361
397
bucketAddr += MAX_OBJECT_SIZE ;
362
398
}
363
399
holder .destroy ();
@@ -383,12 +419,12 @@ public long getHandler() {
383
419
384
420
@ Override
385
421
public void restoreDurableEntity (A allocator , EntityFactoryProxy [] factoryProxy ,
386
- DurableType [] gField , long phandler , boolean autoreclaim ) throws RestoreDurableEntityError {
387
- initializeDurableEntity (allocator , factoryProxy , gField , autoreclaim );
422
+ DurableType [] gField , long phandler , boolean autoReclaim ) throws RestoreDurableEntityError {
423
+ initializeDurableEntity (allocator , factoryProxy , gField , autoReclaim );
388
424
if (0L == phandler ) {
389
425
throw new RestoreDurableEntityError ("Input handler is null on restoreDurableEntity." );
390
426
}
391
- chunkAddr = allocator .retrieveChunk (phandler , autoreclaim );
427
+ chunkAddr = allocator .retrieveChunk (phandler , autoReclaim );
392
428
long chunkHandler = unsafe .getLong (chunkAddr .get ());
393
429
holder = allocator .retrieveChunk (chunkHandler , autoReclaim );
394
430
if (null == holder || null == chunkAddr ) {
@@ -436,10 +472,10 @@ public <A extends RestorableAllocator<A>> MapEntry<K, V> create(
436
472
437
473
@ Override
438
474
public void createDurableEntity (A allocator , EntityFactoryProxy [] factoryProxy ,
439
- DurableType [] gField , boolean autoreclaim ) throws OutOfHybridMemory {
440
- initializeDurableEntity (allocator , factoryProxy , gField , autoreclaim );
441
- this .holder = allocator .createChunk (MAX_OBJECT_SIZE * totalCapacity , autoreclaim );
442
- this .chunkAddr = allocator .createChunk (MAX_OBJECT_SIZE , autoreclaim );
475
+ DurableType [] gField , boolean autoReclaim ) throws OutOfHybridMemory {
476
+ initializeDurableEntity (allocator , factoryProxy , gField , autoReclaim );
477
+ this .holder = allocator .createChunk (MAX_OBJECT_SIZE * totalCapacity , autoReclaim );
478
+ this .chunkAddr = allocator .createChunk (MAX_OBJECT_SIZE , autoReclaim );
443
479
unsafe .putLong (chunkAddr .get (), allocator .getChunkHandler (holder ));
444
480
if (null == this .holder || null == this .chunkAddr ) {
445
481
throw new OutOfHybridMemory ("Create Durable Entity Error!" );
@@ -515,13 +551,13 @@ public void remove() {
515
551
prevNode .destroy ();
516
552
} else {
517
553
unsafe .putAddress (prevBucketAddr , prevNode .getNext ().getHandler ());
518
- prevNode .setNext ( null , false );
519
- prevNode . destroy (); // #TODO: better way to delete one node
554
+ prevNode .destroy ( );
555
+ prevNode = null ;
520
556
}
521
557
} else {
522
558
prevPrevNode .setNext (prevNode .getNext (), false );
523
- prevNode .setNext ( null , false );
524
- prevNode . destroy (); // #TODO: better way to delete one node
559
+ prevNode .destroy ( );
560
+ prevNode = prevPrevNode ;
525
561
}
526
562
map .mapSize --;
527
563
}
0 commit comments