-
Notifications
You must be signed in to change notification settings - Fork 46
DeletedMemoryAccessException is Exception #210
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
ccd7b5d
486e578
b840c75
57047d2
7343569
8209e13
192a236
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -297,9 +297,13 @@ boolean isEntrySetValidAfterRebalance() { | |
| return true; | ||
| } | ||
|
|
||
| //This method is called by only one thread on a release chunk. | ||
| void releaseAllDeletedKeys() { | ||
| KeyBuffer key = new KeyBuffer(config.keysMemoryManager.getEmptySlice()); | ||
| for (int i = 0; i < numOfEntries.get() ; i++) { | ||
| for (int i = 0; i < nextFreeIndex.get() - 1 && i < numOfEntries.get() ; i++) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks to me very weird condition and comment.
|
||
| //the second condition is for case where multiple threads increment the nextfreeIndex | ||
| //which results in being bigger than the array size, this happens when multiple threads try | ||
| // to increase the nextFreeIndex | ||
| if (!config.valuesMemoryManager.isReferenceDeleted(getValueReference(i))) { | ||
| continue; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -165,8 +165,16 @@ V replace(K key, V value, OakTransformer<V> valueDeserializeTransformer) { | |
| ThreadContext ctx = getThreadContext(); | ||
|
|
||
| for (int i = 0; i < MAX_RETRIES; i++) { | ||
| BasicChunk<K, V> chunk = findChunk(key, ctx); // find orderedChunk matching key | ||
| chunk.lookUp(ctx, key); | ||
| BasicChunk<K, V> chunk = findChunk(key, ctx); // find Chunk matching key | ||
| try { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The comment above speaks about orderedChunk, do we know it is not going to happen for hash?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you please add an explanatory comment here? |
||
| chunk.lookUp(ctx, key); | ||
| //the look up method might encounter a chunk which is released, while using Nova as a memory manager | ||
| //as a result we might access an already deleted key, thus the need to catch the exception | ||
| } catch (DeletedMemoryAccessException e) { | ||
| assert !(chunk instanceof HashChunk); | ||
| //Hash deals with deleted keys in an earlier stage | ||
| continue; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we add an assert that chunk is not hashChunk? As a sanity check...
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this opened to be discussed |
||
| } | ||
| if (!ctx.isValueValid()) { | ||
| return null; | ||
| } | ||
|
|
@@ -184,29 +192,7 @@ V replace(K key, V value, OakTransformer<V> valueDeserializeTransformer) { | |
| throw new RuntimeException("replace failed: reached retry limit (1024)."); | ||
| } | ||
|
|
||
| boolean replace(K key, V oldValue, V newValue, OakTransformer<V> valueDeserializeTransformer) { | ||
| ThreadContext ctx = getThreadContext(); | ||
|
|
||
| for (int i = 0; i < MAX_RETRIES; i++) { | ||
| // find chunk matching key, puts this key hash into ctx.operationKeyHash | ||
| BasicChunk<K, V> c = findChunk(key, ctx); // find orderedChunk matching key | ||
| c.lookUp(ctx, key); | ||
| if (!ctx.isValueValid()) { | ||
| return false; | ||
| } | ||
|
|
||
| ValueUtils.ValueResult res = getValueOperator().compareExchange(c, ctx, oldValue, newValue, | ||
| valueDeserializeTransformer, getValueSerializer()); | ||
| if (res == ValueUtils.ValueResult.RETRY) { | ||
| // it might be that this chunk is proceeding with rebalance -> help | ||
| helpRebalanceIfInProgress(c); | ||
| continue; | ||
| } | ||
| return res == ValueUtils.ValueResult.TRUE; | ||
| } | ||
|
|
||
| throw new RuntimeException("replace failed: reached retry limit (1024)."); | ||
| } | ||
| abstract boolean replace(K key, V oldValue, V newValue, OakTransformer<V> valueDeserializeTransformer); | ||
|
|
||
| abstract boolean putIfAbsentComputeIfPresent(K key, V value, Consumer<OakScopedWriteBuffer> computer); | ||
|
|
||
|
|
@@ -355,6 +341,9 @@ public boolean hasNext() { | |
| return (state != null); | ||
| } | ||
|
|
||
| // for more detail on this method see implementation | ||
| protected abstract void initStateWithMinKey(BasicChunk<K, V> chunk); | ||
|
|
||
| protected abstract void initAfterRebalance(); | ||
|
|
||
| // the actual next() | ||
|
|
@@ -471,7 +460,8 @@ protected void invalidatePrevState() { | |
|
|
||
| protected abstract BasicChunk<K, V> getNextChunk(BasicChunk<K, V> current); | ||
|
|
||
| protected abstract BasicChunk.BasicChunkIter getChunkIter(BasicChunk<K, V> current); | ||
| protected abstract BasicChunk.BasicChunkIter getChunkIter(BasicChunk<K, V> current) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be good to explain in which cases the exception is thrown. As I remember we were asking ourselves as well. Please add a comment.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. to be discussed |
||
| throws DeletedMemoryAccessException; | ||
|
|
||
| /** | ||
| * advance state to the new position | ||
|
|
@@ -483,21 +473,27 @@ protected boolean advanceState() { | |
| BasicChunk.BasicChunkIter chunkIter = getState().getChunkIter(); | ||
|
|
||
| updatePreviousState(); | ||
|
|
||
| while (!chunkIter.hasNext()) { // skip empty chunks | ||
| chunk = getNextChunk(chunk); | ||
| if (chunk == null) { | ||
| //End of iteration | ||
| setState(null); | ||
| return false; | ||
| } | ||
| chunkIter = getChunkIter(chunk); | ||
| try { | ||
| chunkIter = getChunkIter(chunk); | ||
| } catch (DeletedMemoryAccessException e) { | ||
| assert chunk.state.get() == BasicChunk.State.RELEASED; | ||
| initStateWithMinKey(chunk); | ||
| return true; | ||
| } | ||
| } | ||
|
|
||
| int nextIndex = chunkIter.next(ctx); | ||
| getState().set(chunk, chunkIter, nextIndex); | ||
|
|
||
| return true; | ||
| return true; | ||
| } | ||
|
|
||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.