use of org.apache.ignite.internal.processors.cache.version.GridCacheVersion in project ignite by apache.
the class GridCacheMapEntry method innerGet0.
/**
*/
@SuppressWarnings({ "TooBroadScope" })
private Object innerGet0(GridCacheVersion nextVer, IgniteInternalTx tx, boolean readThrough, boolean evt, boolean updateMetrics, Object transformClo, String taskName, @Nullable IgniteCacheExpiryPolicy expiryPlc, boolean retVer, boolean keepBinary, boolean reserveForLoad, @Nullable ReaderArguments readerArgs) throws IgniteCheckedException, GridCacheEntryRemovedException {
assert !(retVer && readThrough);
assert !(reserveForLoad && readThrough);
// Disable read-through if there is no store.
if (readThrough && !cctx.readThrough())
readThrough = false;
GridCacheVersion startVer;
GridCacheVersion resVer = null;
boolean obsolete = false;
boolean deferred = false;
GridCacheVersion ver0 = null;
Object res = null;
lockEntry();
try {
checkObsolete();
CacheObject val;
AffinityTopologyVersion topVer = tx != null ? tx.topologyVersion() : cctx.affinity().affinityTopologyVersion();
boolean valid = valid(topVer);
if (valid) {
val = this.val;
if (val == null) {
if (isStartVersion()) {
unswap(null, false);
val = this.val;
if (val != null && tx == null)
updatePlatformCache(val, topVer);
}
}
if (val != null) {
long expireTime = expireTimeExtras();
if (expireTime > 0 && (expireTime < U.currentTimeMillis())) {
if (onExpired((CacheObject) cctx.unwrapTemporary(val), null)) {
val = null;
evt = false;
if (cctx.deferredDelete()) {
deferred = true;
ver0 = ver;
} else
obsolete = true;
}
}
}
} else
val = null;
CacheObject ret = val;
if (ret == null) {
if (updateMetrics && cctx.statisticsEnabled())
cctx.cache().metrics0().onRead(false);
} else {
if (updateMetrics && cctx.statisticsEnabled())
cctx.cache().metrics0().onRead(true);
}
if (evt && cctx.events().isRecordable(EVT_CACHE_OBJECT_READ)) {
transformClo = EntryProcessorResourceInjectorProxy.unwrap(transformClo);
GridCacheMvcc mvcc = mvccExtras();
cctx.events().addEvent(partition(), key, tx, mvcc != null ? mvcc.anyOwner() : null, EVT_CACHE_OBJECT_READ, ret, ret != null, ret, ret != null, transformClo != null ? transformClo.getClass().getName() : null, taskName, keepBinary);
// No more notifications.
evt = false;
}
if (ret != null && expiryPlc != null)
updateTtl(expiryPlc);
if (retVer && resVer == null) {
resVer = (isNear() && cctx.transactional()) ? ((GridNearCacheEntry) this).dhtVersion() : this.ver;
if (resVer == null)
ret = null;
}
// Cache version for optimistic check.
startVer = ver;
addReaderIfNeed(readerArgs);
if (ret != null) {
assert !obsolete;
assert !deferred;
// If return value is consistent, then done.
res = retVer ? entryGetResult(ret, resVer, false) : ret;
} else if (reserveForLoad && !obsolete) {
assert !readThrough;
assert retVer;
boolean reserve = !evictionDisabled();
if (reserve)
flags |= IS_EVICT_DISABLED;
res = entryGetResult(null, resVer, reserve);
}
} finally {
unlockEntry();
}
if (obsolete) {
onMarkedObsolete();
throw new GridCacheEntryRemovedException();
}
if (deferred)
cctx.onDeferredDelete(this, ver0);
if (res != null)
return res;
CacheObject ret = null;
if (readThrough) {
IgniteInternalTx tx0 = null;
if (tx != null && tx.local()) {
if (cctx.isReplicated() || cctx.isColocated() || tx.near())
tx0 = tx;
else if (tx.dht()) {
GridCacheVersion ver = tx.nearXidVersion();
tx0 = cctx.dht().near().context().tm().tx(ver);
}
}
Object storeVal = readThrough(tx0, key, false, taskName);
ret = cctx.toCacheObject(storeVal);
}
if (ret == null && !evt)
return null;
lockEntry();
try {
long ttl = ttlExtras();
// If version matched, set value.
if (startVer.equals(ver)) {
if (ret != null) {
// Detach value before index update.
ret = cctx.kernalContext().cacheObjects().prepareForCache(ret, cctx);
nextVer = nextVer != null ? nextVer : nextVersion();
long expTime = CU.toExpireTime(ttl);
// Update indexes before actual write to entry.
storeValue(ret, expTime, nextVer);
update(ret, expTime, ttl, nextVer, true);
if (cctx.deferredDelete() && deletedUnlocked() && !isInternal() && !detached())
deletedUnlocked(false);
assert readerArgs == null;
}
if (evt && cctx.events().isRecordable(EVT_CACHE_OBJECT_READ)) {
transformClo = EntryProcessorResourceInjectorProxy.unwrap(transformClo);
GridCacheMvcc mvcc = mvccExtras();
cctx.events().addEvent(partition(), key, tx, mvcc != null ? mvcc.anyOwner() : null, EVT_CACHE_OBJECT_READ, ret, ret != null, null, false, transformClo != null ? transformClo.getClass().getName() : null, taskName, keepBinary);
}
}
} finally {
unlockEntry();
}
assert ret == null || !retVer;
return ret;
}
use of org.apache.ignite.internal.processors.cache.version.GridCacheVersion in project ignite by apache.
the class GridCacheMapEntry method innerRemove.
/**
* {@inheritDoc}
*/
@Override
public final GridCacheUpdateTxResult innerRemove(@Nullable IgniteInternalTx tx, UUID evtNodeId, UUID affNodeId, boolean retval, boolean evt, boolean metrics, boolean keepBinary, boolean oldValPresent, @Nullable CacheObject oldVal, AffinityTopologyVersion topVer, CacheEntryPredicate[] filter, GridDrType drType, @Nullable GridCacheVersion explicitVer, String taskName, @Nullable GridCacheVersion dhtVer, @Nullable Long updateCntr) throws IgniteCheckedException, GridCacheEntryRemovedException {
assert cctx.transactional();
CacheObject old;
GridCacheVersion newVer;
final boolean valid = valid(tx != null ? tx.topologyVersion() : topVer);
// Lock should be held by now.
if (!cctx.isAll(this, filter))
return new GridCacheUpdateTxResult(false);
GridCacheVersion obsoleteVer = null;
boolean intercept = cctx.config().getInterceptor() != null;
IgniteBiTuple<Boolean, Object> interceptRes = null;
CacheLazyEntry entry0 = null;
long updateCntr0;
WALPointer logPtr = null;
boolean deferred;
boolean marked = false;
lockListenerReadLock();
lockEntry();
try {
checkObsolete();
if (isNear()) {
assert dhtVer != null;
// It is possible that 'get' could load more recent value.
if (!((GridNearCacheEntry) this).recordDhtVersion(dhtVer))
return new GridCacheUpdateTxResult(false, logPtr);
}
assert tx == null || (!tx.local() && tx.onePhaseCommit()) || tx.ownsLock(this) : "Transaction does not own lock for remove[entry=" + this + ", tx=" + tx + ']';
boolean startVer = isStartVersion();
newVer = explicitVer != null ? explicitVer : tx == null ? nextVersion() : tx.writeVersion();
boolean internal = isInternal() || !context().userCache();
Map<UUID, CacheContinuousQueryListener> lsnrCol = notifyContinuousQueries() ? cctx.continuousQueries().updateListeners(internal, false) : null;
if (startVer && (retval || intercept || lsnrCol != null))
unswap();
old = oldValPresent ? oldVal : val;
if (intercept)
intercept = !skipInterceptor(explicitVer);
if (intercept) {
entry0 = new CacheLazyEntry(cctx, key, old, keepBinary);
interceptRes = cctx.config().getInterceptor().onBeforeRemove(entry0);
if (cctx.cancelRemove(interceptRes)) {
CacheObject ret = cctx.toCacheObject(cctx.unwrapTemporary(interceptRes.get2()));
return new GridCacheUpdateTxResult(false, logPtr);
}
}
removeValue();
update(null, 0, 0, newVer, true);
if (cctx.deferredDelete() && !detached() && !isInternal()) {
if (!deletedUnlocked()) {
deletedUnlocked(true);
if (tx != null) {
GridCacheMvcc mvcc = mvccExtras();
if (mvcc == null || mvcc.isEmpty(tx.xidVersion()))
clearReaders();
else {
// Optimize memory usage - do not allocate additional array.
List<GridCacheMvccCandidate> locs = mvcc.localCandidatesNoCopy(false);
GridCacheVersion txVer = tx.xidVersion();
UUID originatingNodeId = tx.originatingNodeId();
boolean hasOriginatingNodeId = false;
for (GridCacheMvccCandidate c : locs) {
if (c.reentry() || Objects.equals(c.version(), txVer))
continue;
if (Objects.equals(c.otherNodeId(), originatingNodeId)) {
hasOriginatingNodeId = true;
break;
}
}
// Remove reader only if there are no other active transactions from it.
if (!hasOriginatingNodeId)
clearReader(originatingNodeId);
}
}
}
}
updateCntr0 = nextPartitionCounter(tx, updateCntr);
if (tx != null && cctx.group().persistenceEnabled() && cctx.group().walEnabled())
logPtr = logTxUpdate(tx, null, addConflictVersion(tx.writeVersion(), newVer), 0, updateCntr0);
drReplicate(drType, null, newVer, topVer);
if (metrics && cctx.statisticsEnabled()) {
cctx.cache().metrics0().onRemove();
T2<GridCacheOperation, CacheObject> entryProcRes = tx.entry(txKey()).entryProcessorCalculatedValue();
if (entryProcRes != null && DELETE.equals(entryProcRes.get1()))
cctx.cache().metrics0().onInvokeRemove(old != null);
}
if (tx == null)
obsoleteVer = newVer;
else {
// Only delete entry if the lock is not explicit.
if (lockedBy(tx.xidVersion()))
obsoleteVer = tx.xidVersion();
else if (log.isDebugEnabled())
log.debug("Obsolete version was not set because lock was explicit: " + this);
}
if (evt && newVer != null && cctx.events().isRecordable(EVT_CACHE_OBJECT_REMOVED)) {
CacheObject evtOld = cctx.unwrapTemporary(old);
cctx.events().addEvent(partition(), key, evtNodeId, tx, null, newVer, EVT_CACHE_OBJECT_REMOVED, null, false, evtOld, evtOld != null || hasValueUnlocked(), null, taskName, keepBinary);
}
if (lsnrCol != null) {
cctx.continuousQueries().onEntryUpdated(lsnrCol, key, null, old, internal, partition(), tx.local(), false, updateCntr0, null, topVer);
}
deferred = cctx.deferredDelete() && !detached();
if (intercept)
entry0.updateCounter(updateCntr0);
if (!deferred) {
// If entry is still removed.
assert newVer == ver;
if (obsoleteVer == null || !(marked = markObsolete0(obsoleteVer, true, null))) {
if (log.isDebugEnabled())
log.debug("Entry could not be marked obsolete (it is still used): " + this);
} else {
recordNodeId(affNodeId, topVer);
if (log.isDebugEnabled())
log.debug("Entry was marked obsolete: " + this);
}
}
} finally {
unlockEntry();
unlockListenerReadLock();
}
if (marked) {
assert !deferred;
onMarkedObsolete();
}
onUpdateFinished(updateCntr0);
if (intercept)
cctx.config().getInterceptor().onAfterRemove(entry0);
if (valid)
return new GridCacheUpdateTxResult(true, updateCntr0, logPtr);
else
return new GridCacheUpdateTxResult(false, logPtr);
}
use of org.apache.ignite.internal.processors.cache.version.GridCacheVersion in project ignite by apache.
the class GridCacheMapEntry method mvccLock.
/**
* {@inheritDoc}
*/
@Override
public GridCacheUpdateTxResult mvccLock(GridDhtTxLocalAdapter tx, MvccSnapshot mvccVer) throws GridCacheEntryRemovedException, IgniteCheckedException {
assert tx != null;
assert mvccVer != null;
final boolean valid = valid(tx.topologyVersion());
final GridCacheVersion newVer;
WALPointer logPtr = null;
lockEntry();
try {
checkObsolete();
newVer = tx.writeVersion();
assert newVer != null : "Failed to get write version for tx: " + tx;
assert tx.local();
MvccUpdateResult res = cctx.offheap().mvccLock(this, mvccVer);
assert res != null;
if (res.resultType() == ResultType.VERSION_MISMATCH)
throw serializationError();
else if (res.resultType() == ResultType.LOCKED) {
unlockEntry();
MvccVersion lockVer = res.resultVersion();
GridFutureAdapter<GridCacheUpdateTxResult> resFut = new GridFutureAdapter<>();
IgniteInternalFuture<?> lockFut = cctx.kernalContext().coordinators().waitForLock(cctx, mvccVer, lockVer);
lockFut.listen(new MvccAcquireLockListener(tx, this, mvccVer, resFut));
return new GridCacheUpdateTxResult(false, resFut);
}
} finally {
if (lockedByCurrentThread()) {
unlockEntry();
cctx.evicts().touch(this);
}
}
onUpdateFinished(0L);
return new GridCacheUpdateTxResult(valid, logPtr);
}
use of org.apache.ignite.internal.processors.cache.version.GridCacheVersion in project ignite by apache.
the class GridCacheMapEntry method initialValue.
/**
* {@inheritDoc}
*/
@Override
public boolean initialValue(CacheObject val, GridCacheVersion ver, MvccVersion mvccVer, MvccVersion newMvccVer, byte mvccTxState, byte newMvccTxState, long ttl, long expireTime, boolean preload, AffinityTopologyVersion topVer, GridDrType drType, boolean fromStore, boolean primary, CacheDataRow row) throws IgniteCheckedException, GridCacheEntryRemovedException {
assert !primary || !(preload || fromStore);
ensureFreeSpace();
boolean deferred = false;
boolean obsolete = false;
GridCacheVersion oldVer = null;
lockListenerReadLock();
lockEntry();
try {
checkObsolete();
boolean walEnabled = !cctx.isNear() && cctx.group().persistenceEnabled() && cctx.group().walEnabled();
long expTime = expireTime < 0 ? CU.toExpireTime(ttl) : expireTime;
val = cctx.kernalContext().cacheObjects().prepareForCache(val, cctx);
final boolean unswapped = ((flags & IS_UNSWAPPED_MASK) != 0);
boolean update;
IgnitePredicate<CacheDataRow> p = new IgnitePredicate<CacheDataRow>() {
@Override
public boolean apply(@Nullable CacheDataRow row) {
boolean update0;
GridCacheVersion currentVer = row != null ? row.version() : GridCacheMapEntry.this.ver;
boolean isStartVer = cctx.shared().versions().isStartVersion(currentVer);
if (cctx.group().persistenceEnabled()) {
if (!isStartVer) {
if (cctx.atomic())
update0 = ATOMIC_VER_COMPARATOR.compare(currentVer, ver) < 0;
else
update0 = currentVer.compareTo(ver) < 0;
} else
update0 = true;
} else
update0 = isStartVer;
update0 |= (!preload && deletedUnlocked());
return update0;
}
};
if (unswapped) {
update = p.apply(null);
if (update) {
// If entry is already unswapped and we are modifying it, we must run deletion callbacks for old value.
long oldExpTime = expireTimeUnlocked();
if (oldExpTime > 0 && oldExpTime < U.currentTimeMillis()) {
if (onExpired(this.val, null)) {
if (cctx.deferredDelete()) {
deferred = true;
oldVer = this.ver;
} else if (val == null)
obsolete = true;
}
}
if (cctx.mvccEnabled()) {
assert !preload;
cctx.offheap().mvccInitialValue(this, val, ver, expTime, mvccVer, newMvccVer);
} else
storeValue(val, expTime, ver, null, row);
}
} else {
if (cctx.mvccEnabled()) {
// cannot identify whether the entry is exist on the fly
unswap(false);
if (update = p.apply(null)) {
// If entry is already unswapped and we are modifying it, we must run deletion callbacks for old value.
long oldExpTime = expireTimeUnlocked();
long delta = (oldExpTime == 0 ? 0 : oldExpTime - U.currentTimeMillis());
if (delta < 0) {
if (onExpired(this.val, null)) {
if (cctx.deferredDelete()) {
deferred = true;
oldVer = this.ver;
} else if (val == null)
obsolete = true;
}
}
assert !preload;
cctx.offheap().mvccInitialValue(this, val, ver, expTime, mvccVer, newMvccVer);
}
} else
// Optimization to access storage only once.
update = storeValue(val, expTime, ver, p, row);
}
if (update) {
update(val, expTime, ttl, ver, true);
boolean skipQryNtf = false;
if (val == null) {
skipQryNtf = true;
if (cctx.deferredDelete() && !deletedUnlocked() && !isInternal())
deletedUnlocked(true);
} else if (deletedUnlocked())
deletedUnlocked(false);
long updateCntr = 0;
if (!preload)
updateCntr = nextPartitionCounter(topVer, true, true, null);
if (walEnabled) {
if (cctx.mvccEnabled()) {
cctx.shared().wal().log(new MvccDataRecord(new MvccDataEntry(cctx.cacheId(), key, val, val == null ? DELETE : GridCacheOperation.CREATE, null, ver, expireTime, partition(), updateCntr, mvccVer == null ? MvccUtils.INITIAL_VERSION : mvccVer)));
} else {
cctx.shared().wal().log(new DataRecord(new DataEntry(cctx.cacheId(), key, val, val == null ? DELETE : GridCacheOperation.CREATE, null, ver, expireTime, partition(), updateCntr, DataEntry.flags(primary, preload, fromStore))));
}
}
drReplicate(drType, val, ver, topVer);
if (!skipQryNtf) {
cctx.continuousQueries().onEntryUpdated(key, val, null, this.isInternal() || !this.context().userCache(), this.partition(), true, preload, updateCntr, null, topVer);
}
updatePlatformCache(val, topVer);
onUpdateFinished(updateCntr);
if (!fromStore && cctx.store().isLocal()) {
if (val != null)
cctx.store().put(null, key, val, ver);
}
return true;
}
return false;
} finally {
unlockEntry();
unlockListenerReadLock();
if (obsolete) {
onMarkedObsolete();
cctx.cache().removeEntry(this);
}
if (deferred) {
assert oldVer != null;
cctx.onDeferredDelete(this, oldVer);
}
}
}
use of org.apache.ignite.internal.processors.cache.version.GridCacheVersion in project ignite by apache.
the class GridCacheMapEntry method innerSet.
/**
* {@inheritDoc}
*/
@Override
public final GridCacheUpdateTxResult innerSet(@Nullable IgniteInternalTx tx, UUID evtNodeId, UUID affNodeId, CacheObject val, boolean writeThrough, boolean retval, long ttl, boolean evt, boolean metrics, boolean keepBinary, boolean oldValPresent, @Nullable CacheObject oldVal, AffinityTopologyVersion topVer, CacheEntryPredicate[] filter, GridDrType drType, long drExpireTime, @Nullable GridCacheVersion explicitVer, String taskName, @Nullable GridCacheVersion dhtVer, @Nullable Long updateCntr) throws IgniteCheckedException, GridCacheEntryRemovedException {
CacheObject old;
final boolean valid = valid(tx != null ? tx.topologyVersion() : topVer);
// Lock should be held by now.
if (!cctx.isAll(this, filter))
return new GridCacheUpdateTxResult(false);
final GridCacheVersion newVer;
boolean intercept = cctx.config().getInterceptor() != null;
Object key0 = null;
Object val0 = null;
WALPointer logPtr = null;
long updateCntr0;
ensureFreeSpace();
lockListenerReadLock();
lockEntry();
try {
checkObsolete();
if (isNear()) {
assert dhtVer != null;
// It is possible that 'get' could load more recent value.
if (!((GridNearCacheEntry) this).recordDhtVersion(dhtVer))
return new GridCacheUpdateTxResult(false, logPtr);
}
assert tx == null || (!tx.local() && tx.onePhaseCommit()) || tx.ownsLock(this) : "Transaction does not own lock for update [entry=" + this + ", tx=" + tx + ']';
// Load and remove from swap if it is new.
boolean startVer = isStartVersion();
boolean internal = isInternal() || !context().userCache();
Map<UUID, CacheContinuousQueryListener> lsnrCol = notifyContinuousQueries() ? cctx.continuousQueries().updateListeners(internal, false) : null;
if (startVer && (retval || intercept || lsnrCol != null))
unswap(retval);
newVer = explicitVer != null ? explicitVer : tx == null ? nextVersion() : tx.writeVersion();
assert newVer != null : "Failed to get write version for tx: " + tx;
old = oldValPresent ? oldVal : this.val;
if (intercept)
intercept = !skipInterceptor(explicitVer);
if (intercept) {
val0 = cctx.unwrapBinaryIfNeeded(val, keepBinary, false, null);
CacheLazyEntry e = new CacheLazyEntry(cctx, key, old, keepBinary);
key0 = e.key();
Object interceptorVal = cctx.config().getInterceptor().onBeforePut(e, val0);
if (interceptorVal == null)
return new GridCacheUpdateTxResult(false, logPtr);
else if (interceptorVal != val0)
val0 = cctx.unwrapTemporary(interceptorVal);
val = cctx.toCacheObject(val0);
}
// Determine new ttl and expire time.
long expireTime;
if (drExpireTime >= 0) {
assert ttl >= 0 : ttl;
expireTime = drExpireTime;
} else {
if (ttl == -1L) {
ttl = ttlExtras();
expireTime = expireTimeExtras();
} else
expireTime = CU.toExpireTime(ttl);
}
assert ttl >= 0 : ttl;
assert expireTime >= 0 : expireTime;
// Detach value before index update.
val = cctx.kernalContext().cacheObjects().prepareForCache(val, cctx);
assert val != null;
storeValue(val, expireTime, newVer);
if (cctx.deferredDelete() && deletedUnlocked() && !isInternal() && !detached())
deletedUnlocked(false);
updateCntr0 = nextPartitionCounter(tx, updateCntr);
if (tx != null && cctx.group().persistenceEnabled() && cctx.group().walEnabled())
logPtr = logTxUpdate(tx, val, addConflictVersion(tx.writeVersion(), newVer), expireTime, updateCntr0);
update(val, expireTime, ttl, newVer, true);
drReplicate(drType, val, newVer, topVer);
recordNodeId(affNodeId, topVer);
if (metrics && cctx.statisticsEnabled() && tx != null) {
cctx.cache().metrics0().onWrite();
IgniteTxEntry txEntry = tx.entry(txKey());
if (txEntry != null) {
T2<GridCacheOperation, CacheObject> entryProcRes = txEntry.entryProcessorCalculatedValue();
if (entryProcRes != null && UPDATE.equals(entryProcRes.get1()))
cctx.cache().metrics0().onInvokeUpdate(old != null);
}
}
if (evt && newVer != null && cctx.events().isRecordable(EVT_CACHE_OBJECT_PUT)) {
CacheObject evtOld = cctx.unwrapTemporary(old);
cctx.events().addEvent(partition(), key, evtNodeId, tx, null, newVer, EVT_CACHE_OBJECT_PUT, val, val != null, evtOld, evtOld != null || hasValueUnlocked(), null, taskName, keepBinary);
}
if (lsnrCol != null) {
cctx.continuousQueries().onEntryUpdated(lsnrCol, key, val, old, internal, partition(), tx.local(), false, updateCntr0, null, topVer);
}
} finally {
unlockEntry();
unlockListenerReadLock();
}
onUpdateFinished(updateCntr0);
if (log.isDebugEnabled())
log.debug("Updated cache entry [val=" + val + ", old=" + old + ", entry=" + this + ']');
// value will be handled by current transaction.
if (writeThrough)
cctx.store().put(tx, key, val, newVer);
if (intercept)
cctx.config().getInterceptor().onAfterPut(new CacheLazyEntry(cctx, key, key0, val, val0, keepBinary, updateCntr0));
updatePlatformCache(val, topVer);
return valid ? new GridCacheUpdateTxResult(true, updateCntr0, logPtr) : new GridCacheUpdateTxResult(false, logPtr);
}
Aggregations