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

Use an explicit per-View modification counter [ECR-2804] #658

Merged
merged 11 commits into from
Jan 18, 2019

Conversation

dmitry-timofeev
Copy link
Contributor

@dmitry-timofeev dmitry-timofeev commented Jan 15, 2019

Overview

Use an explicit modification counter in each View to get rid of
static state in ViewModificationCounter singleton and simplify
testing. As previously, a ModificationCounter is associated with each
View (either a Fork or Snapshot), but this relationship is now more
transparent.


See: https://jira.bf.local/browse/ECR-2804

Definition of Done

  • There are no TODOs left in the code
  • Change is covered by automated tests
  • The coding guidelines are followed
  • Public API has Javadoc
  • Method preconditions are checked and documented in the Javadoc of the method
  • Changelog is updated if needed (in case of notable or breaking changes)
  • The continuous integration build passes

Use an explicit modification counter in each View to get rid of
static state in ViewModificationCounter singleton and simplify
testing. As previously, a ModificationCounter is associated with each
View (either a Fork or Snapshot), but this relationship is now more
transparent.
@dmitry-timofeev dmitry-timofeev added the work-in-progress 👷‍♂️ Do not expect reviewers to provide any feedback on WIP PRs — please ask for it explicitly! label Jan 15, 2019
/**
* Notifies this counter that the source object is modified, updating its current value.
*
* @throws IllegalStateException if this counter corresponds to a read-only (immutable) object,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure if a counter shall concern itself with immutable things (on top of that, the AbstractIndexProxy does this check itself)

Copy link
Contributor

@MakarovS MakarovS Jan 16, 2019

Choose a reason for hiding this comment

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

I think it's better to be safe and throw an exception in case of an immutable counter (as it is now)

})
@Disabled
// TODO Won't run on Java 10 till Powermock is updated [ECR-1614].
// TODO Won't run on Junit 5 till Powermock is updated [ECR-1614].
Copy link
Contributor Author

Choose a reason for hiding this comment

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

to be more precise, till Powermock gains support of JUnit 5 (we use the most recent version)

assertThat(thrown.getMessage(), matchesPattern(pattern));

assertFalse(counter.isModifiedSince(initialValue));
}

@Test
void notifyModifiedAcceptsFork() {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This test verifies that the index does use a counter from the Fork. Not sure if we shall add an integration test of Collection + Iterator + ModificationCounter, verifying that modification of another collection created with the same Fork invalidates the iterator of the first collection.

Copy link
Contributor

@MakarovS MakarovS left a comment

Choose a reason for hiding this comment

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

👍

package com.exonum.binding.storage.database;

/**
* A counter of events-modifications of some objects (e.g., a collection, or a database view).
Copy link
Contributor

Choose a reason for hiding this comment

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

A counter of modification events?

/**
* Notifies this counter that the source object is modified, updating its current value.
*
* @throws IllegalStateException if this counter corresponds to a read-only (immutable) object,
Copy link
Contributor

@MakarovS MakarovS Jan 16, 2019

Choose a reason for hiding this comment

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

I think it's better to be safe and throw an exception in case of an immutable counter (as it is now)

@@ -32,8 +32,10 @@
final class ConfigurableRustIter<E> extends AbstractNativeProxy implements RustIter<E> {

private final LongFunction<E> nextFunction;
// todo: This view is kept only for diagnostic purposes (to put in error message) —
Copy link
Contributor

Choose a reason for hiding this comment

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

Views don't have toString overridden, so would it be helpful to log things like com.exonum.binding.storage.database.Fork@131ef10? Or maybe it would make sense to return View#getViewNativeHandle for diagnostic purposes? If no to both questions, then I'd remove this field.

*/
boolean isModifiedSince(int lastValue);

// todo: We _might_ consider adding a special type for this timestamp, but at the moment it feels like an overkill
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe create a task instead of todo? Do you think it's realistic that a counter might overflow int range? If yes, we could add throwing an exception in notifyModified for such a case

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The reasoning was to hide the knowledge of how that timestamp is represented to be able to change later, but in an internal interface it seems to be unnecessary.

I've documented, however, that counters must detect up to 4B modifications, that shall be enough :-)


final class IncrementalModificationCounter implements ModificationCounter {

private static final int INITIAL_VALUE = 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

Seems excessive to me, as we only use it once in the next line. Or maybe make it public? That way it'd be clear for users what the initial value is (because right now in tests to get initialValue we call getCurrentValue which is error-prone. We could use a public field in tests as well). But I do not insist, it's good as it is as well :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I do not think that the clients shall care about the initial value, what they shall is current value (= the value at the moment when an (spl)iterator is bound to source). initial value is an implementation detail of this counter.

The constnant can probably be inlined, and the field renamed to counter

@dmitry-timofeev dmitry-timofeev removed the work-in-progress 👷‍♂️ Do not expect reviewers to provide any feedback on WIP PRs — please ask for it explicitly! label Jan 17, 2019
@coveralls
Copy link

Coverage Status

Coverage decreased (-0.02%) to 84.144% when pulling 9c96b2e on dmitry-timofeev:refactor-mod-counter into 6b02435 on exonum:master.

@dmitry-timofeev dmitry-timofeev merged commit a20608c into exonum:master Jan 18, 2019
@dmitry-timofeev dmitry-timofeev deleted the refactor-mod-counter branch January 18, 2019 07:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

4 participants