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

ISPN-7803 Functional commands-based AtomicMaps #5140

Merged
merged 8 commits into from Jun 8, 2017

Conversation

rvansa
Copy link
Member

@rvansa rvansa commented May 18, 2017

https://issues.jboss.org/browse/ISPN-7803

When this gets in, I'll file PR to deprecate DeltaAware et all: https://github.com/rvansa/infinispan/tree/ISPN-7847


Infinispan now contains a new implementation of both `AtomicMap` and `FineGrainedAtomicMap`, but the semantics has been preserved. The new implementations don't use `DeltaAware` interface but link:../user_guide/user_guide.html#functional_map_api[Functional API] instead.

There are no changes in needed for `AtomicMap`, but it now supports non-transactional use case as well.
Copy link
Member

Choose a reason for hiding this comment

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

remove 'in'


=== (FineGrained)AtomicMap reimplemented

Infinispan now contains a new implementation of both `AtomicMap` and `FineGrainedAtomicMap`, but the semantics has been preserved. The new implementations don't use `DeltaAware` interface but link:../user_guide/user_guide.html#functional_map_api[Functional API] instead.
Copy link
Member

Choose a reason for hiding this comment

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

s/has/have/
s/don't/does not/
add a 'the' just before the functional api link

Copy link
Member Author

Choose a reason for hiding this comment

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

According to http://www.wordreference.com/definition/semantics 'semantics' is used with singular verb, despite it's plural noun.


There are no changes in needed for `AtomicMap`, but it now supports non-transactional use case as well.

`FineGrainedAtomicMap` now uses link:../user_guide/user_guide.html#grouping[Grouping API] and therefore you need to link:../user_guide/user_guide.html#how_do_i_use_the_grouping_api[enable groups in configuration]. Also it holds entries as regular cache entries, plus one cache entry for cached key set (the map itself). Therefore the cache size or iteration/streaming results may differ. Note that fine grained atomic maps are still supported only on transactional caches.
Copy link
Member

Choose a reason for hiding this comment

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

add 'the' before the grouping api link
'still supported on transactional caches only'

* @param other Actual value stored in the cache, or <code>null</code> if the entry does not exist.
* @return Value that will be stored in the cache, or null if it should be removed.
*/
Object merge(Object other);
Copy link
Member

Choose a reason for hiding this comment

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

No generics?

Copy link
Member Author

Choose a reason for hiding this comment

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

No. ReadCommittedEntry won't use any generics anyway. The implementation should expect any type of object stored in the cache. I don't see much value in that.


@Override
public Void apply(EntryView.ReadWriteEntryView<Object, Object> view) {
if (view.find().isPresent()) {
Copy link
Member

Choose a reason for hiding this comment

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

Optional.map(f).orElseThrow() ? :)

Copy link
Member Author

Choose a reason for hiding this comment

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

Since you call view.set(), that would create another object capturing the view.

}
}

<T> T run(Supplier<T> op) {
Copy link
Member

Choose a reason for hiding this comment

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

This is not implementing the correct pattern of dealing with transaction commit/rollback. This code shows the correct pattern.

Copy link
Member Author

Choose a reason for hiding this comment

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

Then we should fix CacheImpl.executeCommandAndCommitIfNeeded and some code in functional maps as well... this is basically inlined ^.

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed TransactionHelper

@galderz
Copy link
Member

galderz commented May 24, 2017

Have you benchmarked this and compared with old method?

@rvansa
Copy link
Member Author

rvansa commented May 26, 2017

No, regreattably I haven't had a chance to write a benchmark. It will mostly depend on performance of functional commands in general. However I can't argue that it will change dramatically after ISPN-7590 since I don't use ReadWriteKeyValueCommand which propagates the previous value to backup.

@rvansa
Copy link
Member Author

rvansa commented May 26, 2017

Rebased.

@galderz
Copy link
Member

galderz commented May 29, 2017

Thx for replies, all looks good. Anyone else wants to look at this?

@rvansa
Copy link
Member Author

rvansa commented Jun 1, 2017

@galderz Seems there are no further objections.

Copy link
Member

@wburns wburns left a comment

Choose a reason for hiding this comment

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

Sorry just had a couple minor things. Looks good to me though @rvansa Especially with the interceptor fixes. I assume your other PR hasn't found issues with them? :)

import org.infinispan.util.concurrent.IsolationLevel;

/**
* This is a special type of Map geared for use in Infinispan. AtomicMaps have two major characteristics:
*
* <ol>
* <li>Atomic locking and isolation over the entire collection</li>
* <li>Fine-grained serialization of deltas</li>
* <li>Replication of updates through deltas</li>
Copy link
Member

Choose a reason for hiding this comment

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

Do we still want to use the term delta?

Copy link
Member Author

Choose a reason for hiding this comment

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

I think that 'delta' is a general term, synonym for a 'change'.

@@ -142,6 +129,7 @@
* @param <MK> key param of the cache
*/
public static <MK> void removeAtomicMap(Cache<MK, ?> cache, MK key) {
cache.getAdvancedCache().withFlags(Flag.IGNORE_RETURN_VALUES).remove(key);
// This removes any entry from the cache but includes special handling for fine-grained maps
FineGrainedAtomicMapProxyImpl.removeMap((Cache<Object, Object>) cache, key);
Copy link
Member

Choose a reason for hiding this comment

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

I assume this is fine even if it is not fine grained? I just ask because the create specifically had 2 branches.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, for anything but fine grained it works just like a regular cache.remove(). Non-fine grained maps are just single entries, so no problem with that.

* LockingMode.SKIP is equivalent to Flag.SKIP_LOCKING
* ExecutionMode.LOCAL is equivalent to Flag.CACHE_MODE_LOCAL
* encoding of Params is still just single byte
* Params are internally converted to flags bit set to simplify checks
* FunctionalMapImpl attempts to retrieve flags from the provided Cache
* ReadOnly*Commands should honour Params
…lying implementation

* no fine-grained maps so far
…internals

* Not changing AdvancedCache.getGroup as this is API & SPI
* Changed Grouper SPI but since existing implementations are expected
  to be used only with string-based keys the bridge implementation
  should work.
* require transactional cache with grouping enabled
* store map entries as cache-entries => expected number of entries changed in some tests
* introduce MergeOnStore and minor changes in CommitManager
@rvansa
Copy link
Member Author

rvansa commented Jun 1, 2017

Rebased (this had conflicts with removal of Metadata parameter from CommitManager).

@rvansa
Copy link
Member Author

rvansa commented Jun 6, 2017

@galderz @wburns anything left?

@galderz
Copy link
Member

galderz commented Jun 6, 2017

CI running... let's wait for it

@rvansa
Copy link
Member Author

rvansa commented Jun 8, 2017

@galderz CI finished...

@wburns
Copy link
Member

wburns commented Jun 8, 2017

I see there are a bunch of failures with DirectoryProviderModuleMemberRegistrationIT. Is this just a random failure that occurs sometimes? Unfortunately I can't tell as easily with Jenkins. I wish I could see the history of a given test.

http://ci.infinispan.org/job/Infinispan/job/PR-5140/33/display/redirect

I will poke around, maybe those are using atomic map? I wasn't aware of indexing doing such a thing though.

@wburns
Copy link
Member

wburns commented Jun 8, 2017

It seems they failed here as well http://ci.infinispan.org/job/Infinispan/job/PR-5183/4/#showFailuresLink So it does seem unrelated, guess we have more failures in the test suite now 👎

@wburns
Copy link
Member

wburns commented Jun 8, 2017

@rvansa is there anything you wanted to squash/rebase before I merged this, there are quite a few commits :)

@rvansa
Copy link
Member Author

rvansa commented Jun 8, 2017

@wburns No, please keep the commits as-is. Those are logically structured changes.

@wburns wburns merged commit 738cd9e into infinispan:master Jun 8, 2017
@wburns
Copy link
Member

wburns commented Jun 8, 2017

Integrated into master, thanks @rvansa !

@@ -57,6 +57,7 @@ public void setUp() {
// The default cache is NOT write skew enabled.
cacheManager = TestCacheManagerFactory.createCacheManager(configurationBuilder);
configurationBuilder.locking().isolationLevel(IsolationLevel.REPEATABLE_READ);
configurationBuilder.clustering().hash().groups().enabled();
Copy link
Member

Choose a reason for hiding this comment

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

@rvansa This fails with trace logging enabled, because it forces the component registry to create a DistributionManagerImpl, and its start() methods throws a NPE if the cache manager is not clustered. Do you really need grouping in this class?

Copy link
Member Author

Choose a reason for hiding this comment

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

testDontFailOnImmediateRemovalOfAtomicMaps uses fine grained maps, so grouping is necessary. Please use localAddress in the trace log instead, and drop the getAddress() method.

Copy link
Member

@danberindei danberindei left a comment

Choose a reason for hiding this comment

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

Some late comments

* its correctness. If the application is sure that no concurrent operation occurs,
* it is possible to increase performance by setting this param to {@link #SKIP}.
* The result of any operation without locking is undefined under presence of concurrent
* writes.
Copy link
Member

Choose a reason for hiding this comment

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

Missing @since tag.

}

/**
* Defines where is the command executed.
Copy link
Member

Choose a reason for hiding this comment

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

Missing @since tag.

* only with {@link org.infinispan.context.Flag#SKIP_CACHE_LOAD} and
* {@link org.infinispan.context.Flag#SKIP_CACHE_STORE} or implementing a custom externalizer that will deal with this.
*/
public interface MergeOnStore {
Copy link
Member

Choose a reason for hiding this comment

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

This looks a lot like Delta to me... do we really want to expose another public API that does the same thing, instead of using a lambda?

I'm not sure what you mean about the atomicity of load and store into persistence layer, don't we allow using atomic maps with persistence?

Also, missing @since tag.

Copy link
Member Author

Choose a reason for hiding this comment

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

Delta was supposed to work in general, this contract is more narrow - speaking only about atomic application into DC. It is a way to allow the FGAM use case - modifying an entry without having it locked.

FGAMs with persistence would get broken in the old implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
6 participants