Skip to content
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

Avoid side-effect in VersionMap when assertion enabled #29585

Merged
merged 8 commits into from
Apr 19, 2018

Conversation

dnhatn
Copy link
Member

@dnhatn dnhatn commented Apr 18, 2018

Today when a version map does not require safe access, we will skip that document. However, if the assertion is enabled, we remove the delete tombstone of that document if existed. This side-effect may accidentally hide bugs in which stale delete tombstones can be accessed.

This change makes sure that putAssertionMap does not modify the tombstone maps.

Today when a version map does not require safe access, we will skip that
document. However, if the assertion is enabled, we remove the delete
tombstone of that document if existed. This may accidentally hide bugs
in which stale delete tombstone can be accessed.

This change folds a tombstone map into the version map so that each
version map will have a separate tombstone map.
@dnhatn dnhatn added >enhancement v7.0.0 v6.3.0 :Distributed/Engine Anything around managing Lucene and the Translog in an open shard. labels Apr 18, 2018
@dnhatn dnhatn requested review from s1monw and bleskes April 18, 2018 14:29
@elasticmachine
Copy link
Collaborator

Pinging @elastic/es-distributed

@dnhatn
Copy link
Member Author

dnhatn commented Apr 18, 2018

/cc @DaveCTurner

Copy link
Contributor

@DaveCTurner DaveCTurner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like a good move. I suggested moving some methods around and a bit of renaming.

this.current = current;
this.old = old;
this.previousMapsNeededSafeAccess = previousMapsNeededSafeAccess;
this.tombstones = tombstones; // transfer the tombstone
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this comment isn't needed, WDYT?

/**
* Removes this uid from the pending deletes map.
*/
// For testing
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This -- and the number of times we do maps.tombstones.doStuff() -- feels a little strange. What do you think about moving methods like this onto Maps instead?

@@ -389,7 +397,8 @@ private boolean canRemoveTombstone(long maxTimestampToPrune, long maxSeqNoToPrun
* Try to prune tombstones whose timestamp is less than maxTimestampToPrune and seqno at most the maxSeqNoToPrune.
*/
void pruneTombstones(long maxTimestampToPrune, long maxSeqNoToPrune) {
for (Map.Entry<BytesRef, DeleteVersionValue> entry : tombstones.entrySet()) {
final Tombstones tombstones = maps.tombstones;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similarly - this feels like it could move onto Maps or even Tombstones - AFAICT the only other thing it needs is maps.getMinDeleteTimestamp().

}
assert putAssertionMap(uid, version);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that this has moved, but I think it changes things a little. The thing that's currently called unsafeKeysMap is now a proper copy of the version map that's always safe, so deserves renaming (and the comment above its field declaration needs fixing). Also I suspect getVersionForAssert could be changed to assert that the value in unsafeKeysMap is the value in the main map, when non-null.

Copy link
Contributor

@bleskes bleskes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm +1 on not having the assertion logic in maybePutUnderLock change anything but the assertion map. I'm doubtful about how this is currently done. The current semantics of the extra map is just to keep operations that were skipped from the main map. Now it becomes a full copy and I'm not sure we need this. What we are really trying to solve is the maybePutUnderLock doesn't trim the tombstone, and for that we don't need a full shadow copy.

An alternative is to make maybePutUnderLock only accept a new IndexVersionValue and rename putUnderLock to deleteUnderLock which only accept DeleteVersionValue. Then each of these methods can do what they need to do - i.e., remove/add from the maps and add/remove from the tombstone. That way we can have dedicated paths to the two API and we will untangle the if in putUnderLock(BytesRef, VersionValue, Maps) . Then we won't touch the tombstone where we only intend to update the maps.

I think we can also rename TranslogVersionValue to IndexVersionValue instead of making a new one.

How do people feel about that? just a suggestion.

long v = ramBytesUsedTombstones.addAndGet(-(BASE_BYTES_PER_CHM_ENTRY + prev.ramBytesUsed() + uidRAMBytesUsed));
assert v >= 0 : "bytes=" + v;
}
assert keyedLock.isHeldByCurrentThread(uid) : Thread.currentThread().getName();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

while you're at it - can you add the uid?

@dnhatn
Copy link
Member Author

dnhatn commented Apr 19, 2018

@bleskes and @DaveCTurner

The current semantics of the extra map is just to keep operations that were skipped from the main map. Now it becomes a full copy and I'm not sure we need this

I have restored this.

@bleskes
Copy link
Contributor

bleskes commented Apr 19, 2018

I have restored this.

I wanted to hear what you think of the idea. If you prefer what you did I'm fine too!

@dnhatn
Copy link
Member Author

dnhatn commented Apr 19, 2018

I wanted to hear what you think of the idea. If you prefer what you did I'm fine too!

@bleskes I am putting your idea into IntelliJ and will give you my thought.

Copy link
Contributor

@bleskes bleskes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@dnhatn
Copy link
Member Author

dnhatn commented Apr 19, 2018

Thanks @bleskes and @DaveCTurner.

@dnhatn dnhatn merged commit 1b24d4e into elastic:master Apr 19, 2018
@dnhatn dnhatn deleted the assert-versionmap branch April 19, 2018 16:38
dnhatn added a commit that referenced this pull request Apr 19, 2018
Today when a version map does not require safe access, we will skip that
document. However, if the assertion is enabled, we remove the delete
tombstone of that document if existed. This side-effect may accidentally
hide bugs in which stale delete tombstone can be accessed.

This change ensures putAssertionMap not modify the tombstone maps.
jasontedor added a commit to jasontedor/elasticsearch that referenced this pull request Apr 19, 2018
* master:
  Remove extra spaces from changelog
  Add support to match_phrase query for zero_terms_query. (elastic#29598)
  Fix incorrect references to 'zero_terms_docs' in query parsing error messages. (elastic#29599)
  Build: Move java home checks to pre-execution phase (elastic#29548)
  Avoid side-effect in VersionMap when assertion enabled (elastic#29585)
  [Tests] Remove accidental logger usage
  Add tests for ranking evaluation with aliases (elastic#29452)
  Deprecate use of `htmlStrip` as name for HtmlStripCharFilter (elastic#27429)
  Update plan for the removal of mapping types. (elastic#29586)
  [Docs] Add rankEval method for Jva HL client
  Make ranking evaluation details accessible for client
jasontedor added a commit to jasontedor/elasticsearch that referenced this pull request Apr 19, 2018
* master: (21 commits)
  Remove bulk fallback for write thread pool (elastic#29609)
  Fix an incorrect reference to 'zero_terms_docs' in match_phrase queries.
  Update the version compatibility for zero_terms_query in match_phrase.
  Account translog location to ram usage in version map
  Remove extra spaces from changelog
  Add support to match_phrase query for zero_terms_query. (elastic#29598)
  Fix incorrect references to 'zero_terms_docs' in query parsing error messages. (elastic#29599)
  Build: Move java home checks to pre-execution phase (elastic#29548)
  Avoid side-effect in VersionMap when assertion enabled (elastic#29585)
  [Tests] Remove accidental logger usage
  Add tests for ranking evaluation with aliases (elastic#29452)
  Deprecate use of `htmlStrip` as name for HtmlStripCharFilter (elastic#27429)
  Update plan for the removal of mapping types. (elastic#29586)
  [Docs] Add rankEval method for Jva HL client
  Make ranking evaluation details accessible for client
  Rename the bulk thread pool to write thread pool (elastic#29593)
  [Test] Minor changes to rank_eval tests (elastic#29577)
  Fix missing node id prefix in startup logs (elastic#29534)
  Added painless execute api. (elastic#29164)
  test: also assert deprecation warning after clusters have been closed.
  ...
dnhatn added a commit that referenced this pull request Apr 20, 2018
Previously we did not put an indexing to a version map if that map does
not require safe access but removed the existing delete tombstone only
if assertion enabled. In #29585, we removed the side-effect caused by
assertion then this test started failing. This failure can be explained
as follows:

- Step 1: Index a doc then delete that doc

- Step 2: The version map can switch to unsafe mode because of
  concurrent refreshes (implicitly called by flushes)

- Step 3: Index a document - the version map won't add this version
  value and won't prune the tombstone (previously it did)

- Step 4: Delete a document - this will return NOT_FOUND instead of
  DELETED because of the stale delete tombstone

This failure is actually fixed by #29619 in which we never leave stale
delete tombstones

Closes #29626
dnhatn added a commit that referenced this pull request Apr 20, 2018
Previously we did not put an indexing to a version map if that map does
not require safe access but removed the existing delete tombstone only
if assertion enabled. In #29585, we removed the side-effect caused by
assertion then this test started failing. This failure can be explained
as follows:

- Step 1: Index a doc then delete that doc

- Step 2: The version map can switch to unsafe mode because of
  concurrent refreshes (implicitly called by flushes)

- Step 3: Index a document - the version map won't add this version
  value and won't prune the tombstone (previously it did)

- Step 4: Delete a document - this will return NOT_FOUND instead of
  DELETED because of the stale delete tombstone

This failure is actually fixed by #29619 in which we never leave stale
delete tombstones

Closes #29626
martijnvg added a commit that referenced this pull request Apr 20, 2018
* es/master: (32 commits)
  TEST: Unmute testPrimaryRelocationWhileIndexing
  Remove remaining tribe node references (#29574)
  Never leave stale delete tombstones in version map (#29619)
  Do not serialize common stats flags using ordinal (#29600)
  Remove stale comment from JVM stats (#29625)
  TEST: Mute testPrimaryRelocationWhileIndexing
  Remove bulk fallback for write thread pool (#29609)
  Fix an incorrect reference to 'zero_terms_docs' in match_phrase queries.
  Update the version compatibility for zero_terms_query in match_phrase.
  Account translog location to ram usage in version map
  Remove extra spaces from changelog
  Add support to match_phrase query for zero_terms_query. (#29598)
  Fix incorrect references to 'zero_terms_docs' in query parsing error messages. (#29599)
  Build: Move java home checks to pre-execution phase (#29548)
  Avoid side-effect in VersionMap when assertion enabled (#29585)
  [Tests] Remove accidental logger usage
  Add tests for ranking evaluation with aliases (#29452)
  Deprecate use of `htmlStrip` as name for HtmlStripCharFilter (#27429)
  Update plan for the removal of mapping types. (#29586)
  [Docs] Add rankEval method for Jva HL client
  ...
martijnvg added a commit that referenced this pull request Apr 20, 2018
* es/6.x: (28 commits)
  TEST: Unmute testPrimaryRelocationWhileIndexing
  Never leave stale delete tombstones in version map (#29619)
  Do not serialize common stats flags using ordinal (#29600)
  Remove stale comment from JVM stats (#29625)
  TEST: Mute testPrimaryRelocationWhileIndexing
  Remove 7.0.0 from 6.x changelog (#29621)
  Add support to match_phrase query for zero_terms_query. (#29598)
  Account translog location to ram usage in version map
  Avoid side-effect in VersionMap when assertion enabled (#29585)
  Build: Move java home checks to pre-execution phase (#29548)
  Add tests for ranking evaluation with aliases (#29452)
  [Test] Fix assertion in SearchDocumentationIT
  Deprecate use of `htmlStrip` as name for HtmlStripCharFilter (#27429)
  test: Assert deprecated http.enebled setting warning
  Update plan for the removal of mapping types. (#29586)
  [Docs] Add rankEval method for Jva HL client
  Make ranking evaluation details accessible for client
  Rename the bulk thread pool to write thread pool (#29593)
  [Test] Minor changes to rank_eval tests (#29577)
  test: Assert deprecated http.enebled setting warning
  ...
@s1monw
Copy link
Contributor

s1monw commented Apr 20, 2018

thanks for fixing this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
:Distributed/Engine Anything around managing Lucene and the Translog in an open shard. >enhancement v6.3.0 v7.0.0-beta1
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants