use of org.apache.ignite.internal.processors.cache.version.GridCacheVersion in project ignite by apache.
the class IgniteTxAdapter method batchStoreCommit.
/**
* Performs batch database operations. This commit must be called
* before cache update. This way if there is a DB failure,
* cache transaction can still be rolled back.
*
* @param writeEntries Transaction write set.
* @throws IgniteCheckedException If batch update failed.
*/
@SuppressWarnings({ "CatchGenericClass" })
protected final void batchStoreCommit(Iterable<IgniteTxEntry> writeEntries) throws IgniteCheckedException {
if (!storeEnabled() || internal() || // No need to work with local store at GridNearTxRemote.
(!local() && near()))
return;
Collection<CacheStoreManager> stores = txState().stores(cctx);
if (stores == null || stores.isEmpty())
return;
assert isWriteToStoreFromDhtValid(stores) : "isWriteToStoreFromDht can't be different within one transaction";
CacheStoreManager first = F.first(stores);
boolean isWriteToStoreFromDht = first.isWriteToStoreFromDht();
if ((local() || first.isLocal()) && (near() || isWriteToStoreFromDht)) {
try {
if (writeEntries != null) {
Map<KeyCacheObject, IgniteBiTuple<? extends CacheObject, GridCacheVersion>> putMap = null;
List<KeyCacheObject> rmvCol = null;
CacheStoreManager writeStore = null;
boolean skipNonPrimary = near() && isWriteToStoreFromDht;
for (IgniteTxEntry e : writeEntries) {
boolean skip = e.skipStore();
if (!skip && skipNonPrimary) {
skip = e.cached().isNear() || e.cached().detached() || !e.context().affinity().primaryByPartition(e.cached().partition(), topologyVersion()).isLocal();
}
if (// Update local store at backups only if needed.
!skip && !local() && cctx.localStorePrimaryOnly())
skip = true;
if (skip)
continue;
boolean intercept = e.context().config().getInterceptor() != null;
if (intercept || !F.isEmpty(e.entryProcessors()))
e.cached().unswap(false);
IgniteBiTuple<GridCacheOperation, CacheObject> res = applyTransformClosures(e, false, null);
GridCacheContext cacheCtx = e.context();
GridCacheOperation op = res.get1();
KeyCacheObject key = e.key();
CacheObject val = res.get2();
GridCacheVersion ver = writeVersion();
if (op == CREATE || op == UPDATE) {
// Batch-process all removes if needed.
if (rmvCol != null && !rmvCol.isEmpty()) {
assert writeStore != null;
writeStore.removeAll(this, rmvCol);
// Reset.
rmvCol.clear();
writeStore = null;
}
// Batch-process puts if cache ID has changed.
if (writeStore != null && writeStore != cacheCtx.store()) {
if (putMap != null && !putMap.isEmpty()) {
writeStore.putAll(this, putMap);
// Reset.
putMap.clear();
}
writeStore = null;
}
if (intercept) {
Object interceptorVal = cacheCtx.config().getInterceptor().onBeforePut(new CacheLazyEntry(cacheCtx, key, e.cached().rawGet(), e.keepBinary()), cacheCtx.cacheObjectContext().unwrapBinaryIfNeeded(val, e.keepBinary(), false));
if (interceptorVal == null)
continue;
val = cacheCtx.toCacheObject(cacheCtx.unwrapTemporary(interceptorVal));
}
if (writeStore == null)
writeStore = cacheCtx.store();
if (writeStore.isWriteThrough()) {
if (putMap == null)
putMap = new LinkedHashMap<>(writeMap().size(), 1.0f);
putMap.put(key, F.t(val, ver));
}
} else if (op == DELETE) {
// Batch-process all puts if needed.
if (putMap != null && !putMap.isEmpty()) {
assert writeStore != null;
writeStore.putAll(this, putMap);
// Reset.
putMap.clear();
writeStore = null;
}
if (writeStore != null && writeStore != cacheCtx.store()) {
if (rmvCol != null && !rmvCol.isEmpty()) {
writeStore.removeAll(this, rmvCol);
// Reset.
rmvCol.clear();
}
writeStore = null;
}
if (intercept) {
IgniteBiTuple<Boolean, Object> t = cacheCtx.config().getInterceptor().onBeforeRemove(new CacheLazyEntry(cacheCtx, key, e.cached().rawGet(), e.keepBinary()));
if (cacheCtx.cancelRemove(t))
continue;
}
if (writeStore == null)
writeStore = cacheCtx.store();
if (writeStore.isWriteThrough()) {
if (rmvCol == null)
rmvCol = new ArrayList<>();
rmvCol.add(key);
}
} else if (log.isDebugEnabled())
log.debug("Ignoring NOOP entry for batch store commit: " + e);
}
if (putMap != null && !putMap.isEmpty()) {
assert rmvCol == null || rmvCol.isEmpty();
assert writeStore != null;
// Batch put at the end of transaction.
writeStore.putAll(this, putMap);
}
if (rmvCol != null && !rmvCol.isEmpty()) {
assert putMap == null || putMap.isEmpty();
assert writeStore != null;
// Batch remove at the end of transaction.
writeStore.removeAll(this, rmvCol);
}
}
// Commit while locks are held.
sessionEnd(stores, true);
} catch (IgniteCheckedException ex) {
commitError(ex);
errorWhenCommitting();
// Safe to remove transaction from committed tx list because nothing was committed yet.
cctx.tm().removeCommittedTx(this);
throw ex;
} catch (Throwable ex) {
commitError(ex);
errorWhenCommitting();
// Safe to remove transaction from committed tx list because nothing was committed yet.
cctx.tm().removeCommittedTx(this);
if (ex instanceof Error)
throw (Error) ex;
throw new IgniteCheckedException("Failed to commit transaction to database: " + this, ex);
} finally {
if (isRollbackOnly())
sessionEnd(stores, false);
}
} else
sessionEnd(stores, true);
}
use of org.apache.ignite.internal.processors.cache.version.GridCacheVersion in project ignite by apache.
the class IgniteTxAdapter method commitVersion.
/**
* @param commitVer Commit version.
*/
@Override
public void commitVersion(GridCacheVersion commitVer) {
if (commitVer == null)
return;
GridCacheVersion commitVer0 = this.commitVer;
if (commitVer0 != null)
return;
synchronized (this) {
commitVer0 = this.commitVer;
if (commitVer0 != null)
return;
this.commitVer = commitVer;
}
}
use of org.apache.ignite.internal.processors.cache.version.GridCacheVersion in project ignite by apache.
the class IgniteTxAdapter method ownsLockUnsafe.
/**
* {@inheritDoc}
*/
@SuppressWarnings("SimplifiableIfStatement")
@Override
public boolean ownsLockUnsafe(GridCacheEntryEx entry) {
GridCacheContext cacheCtx = entry.context();
IgniteTxEntry txEntry = entry(entry.txKey());
GridCacheVersion explicit = txEntry == null ? null : txEntry.explicitVersion();
return local() && !cacheCtx.isDht() ? entry.lockedByThreadUnsafe(threadId()) || (explicit != null && entry.lockedByUnsafe(explicit)) : // Otherwise, check if entry is owned by version.
!entry.hasLockCandidateUnsafe(xidVersion()) || entry.lockedByUnsafe(xidVersion());
}
use of org.apache.ignite.internal.processors.cache.version.GridCacheVersion in project ignite by apache.
the class IgniteTxEntry method applyEntryProcessors.
/**
* @param cacheVal Value.
* @return New value.
*/
@SuppressWarnings("unchecked")
public CacheObject applyEntryProcessors(CacheObject cacheVal) {
GridCacheVersion ver;
try {
ver = entry.version();
} catch (GridCacheEntryRemovedException ignore) {
assert tx == null || tx.optimistic() : tx;
ver = null;
}
Object val = null;
Object keyVal = null;
for (T2<EntryProcessor<Object, Object, Object>, Object[]> t : entryProcessors()) {
try {
CacheInvokeEntry<Object, Object> invokeEntry = new CacheInvokeEntry(key, keyVal, cacheVal, val, ver, keepBinary(), cached());
EntryProcessor processor = t.get1();
processor.process(invokeEntry, t.get2());
val = invokeEntry.getValue();
keyVal = invokeEntry.key();
} catch (Exception ignore) {
// No-op.
}
}
return ctx.toCacheObject(val);
}
use of org.apache.ignite.internal.processors.cache.version.GridCacheVersion in project ignite by apache.
the class GridCacheAtomicInvalidPartitionHandlingSelfTest method checkRestarts.
/**
* @param writeSync Write synchronization mode to check.
* @throws Exception If failed.
*/
private void checkRestarts(CacheWriteSynchronizationMode writeSync) throws Exception {
this.writeSync = writeSync;
final int gridCnt = 6;
startGrids(gridCnt);
awaitPartitionMapExchange();
try {
assertEquals(testClientNode(), (boolean) grid(0).configuration().isClientMode());
final IgniteCache<Object, Object> cache = grid(0).cache(DEFAULT_CACHE_NAME);
final int range = 100_000;
final Set<Integer> keys = new LinkedHashSet<>();
try (IgniteDataStreamer<Integer, Integer> streamer = grid(0).dataStreamer(DEFAULT_CACHE_NAME)) {
streamer.allowOverwrite(true);
for (int i = 0; i < range; i++) {
streamer.addData(i, 0);
keys.add(i);
if (i > 0 && i % 10_000 == 0)
System.err.println("Put: " + i);
}
}
final Affinity<Integer> aff = grid(0).affinity(DEFAULT_CACHE_NAME);
boolean putDone = GridTestUtils.waitForCondition(new GridAbsPredicate() {
@Override
public boolean apply() {
Iterator<Integer> it = keys.iterator();
while (it.hasNext()) {
Integer key = it.next();
Collection<ClusterNode> affNodes = aff.mapKeyToPrimaryAndBackups(key);
for (int i = 0; i < gridCnt; i++) {
ClusterNode locNode = grid(i).localNode();
IgniteCache<Object, Object> cache = grid(i).cache(DEFAULT_CACHE_NAME);
Object val = cache.localPeek(key);
if (affNodes.contains(locNode)) {
if (val == null)
return false;
} else
assertNull(val);
}
it.remove();
}
return true;
}
}, 30_000);
assertTrue(putDone);
assertTrue(keys.isEmpty());
final AtomicBoolean done = new AtomicBoolean();
delay = true;
System.err.println("FINISHED PUTS");
// Start put threads.
IgniteInternalFuture<?> fut = multithreadedAsync(new Callable<Object>() {
@Override
public Object call() throws Exception {
Random rnd = new Random();
while (!done.get()) {
try {
int cnt = rnd.nextInt(5);
if (cnt < 2) {
int key = rnd.nextInt(range);
int val = rnd.nextInt();
cache.put(key, val);
} else {
Map<Integer, Integer> upd = new TreeMap<>();
for (int i = 0; i < cnt; i++) upd.put(rnd.nextInt(range), rnd.nextInt());
cache.putAll(upd);
}
} catch (CachePartialUpdateException ignored) {
// No-op.
}
}
return null;
}
}, 4, "putAll-thread");
Random rnd = new Random();
// Restart random nodes.
for (int r = 0; r < 20; r++) {
int idx0 = rnd.nextInt(gridCnt - 1) + 1;
stopGrid(idx0);
U.sleep(200);
startGrid(idx0);
}
done.set(true);
awaitPartitionMapExchange();
fut.get();
for (int k = 0; k < range; k++) {
Collection<ClusterNode> affNodes = affinity(cache).mapKeyToPrimaryAndBackups(k);
// Test is valid with at least one backup.
assert affNodes.size() >= 2;
Object val = null;
GridCacheVersion ver = null;
UUID nodeId = null;
for (int i = 0; i < gridCnt; i++) {
ClusterNode locNode = grid(i).localNode();
GridCacheAdapter<Object, Object> c = ((IgniteKernal) grid(i)).internalCache(DEFAULT_CACHE_NAME);
GridCacheEntryEx entry = null;
try {
entry = c.entryEx(k);
entry.unswap();
} catch (GridDhtInvalidPartitionException ignored) {
// Skip key.
}
for (int r = 0; r < 10; r++) {
try {
if (affNodes.contains(locNode)) {
assert c.affinity().isPrimaryOrBackup(locNode, k);
boolean primary = c.affinity().isPrimary(locNode, k);
assertNotNull("Failed to find entry on node for key [locNode=" + locNode.id() + ", key=" + k + ']', entry);
if (val == null) {
assertNull(ver);
val = CU.value(entry.rawGet(), entry.context(), false);
ver = entry.version();
nodeId = locNode.id();
} else {
assertNotNull(ver);
assertEquals("Failed to check value for key [key=" + k + ", node=" + locNode.id() + ", primary=" + primary + ", recNodeId=" + nodeId + ']', val, CU.value(entry.rawGet(), entry.context(), false));
assertEquals("Failed to check version for key [key=" + k + ", node=" + locNode.id() + ", primary=" + primary + ", recNodeId=" + nodeId + ']', ver, entry.version());
}
} else
assertTrue("Invalid entry: " + entry, entry == null || !entry.partitionValid());
} catch (AssertionError e) {
if (r == 9) {
info("Failed to verify cache contents: " + e.getMessage());
throw e;
}
info("Failed to verify cache contents, will retry: " + e.getMessage());
// Give some time to finish async updates.
U.sleep(1000);
}
}
}
}
} finally {
stopAllGrids();
}
}
Aggregations