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
Conversation
|
||
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. |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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'
18fee71
to
d1a8b73
Compare
* @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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No generics?
There was a problem hiding this comment.
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()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Optional.map(f).orElseThrow() ? :)
There was a problem hiding this comment.
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) { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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 ^.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed TransactionHelper
Have you benchmarked this and compared with old method? |
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 |
Rebased. |
Thx for replies, all looks good. Anyone else wants to look at this? |
@galderz Seems there are no further objections. |
There was a problem hiding this 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> |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
Rebased (this had conflicts with removal of Metadata parameter from CommitManager). |
CI running... let's wait for it |
@galderz CI finished... |
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. |
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 👎 |
@rvansa is there anything you wanted to squash/rebase before I merged this, there are quite a few commits :) |
@wburns No, please keep the commits as-is. Those are logically structured changes. |
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(); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this 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. |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
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