use of org.apache.ignite.lang.IgniteBiTuple 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.lang.IgniteBiTuple in project ignite by apache.
the class GridCacheStoreManagerAdapter method loadCache.
/** {@inheritDoc} */
@Override
public final boolean loadCache(final GridInClosure3 vis, Object[] args) throws IgniteCheckedException {
if (store != null) {
if (log.isDebugEnabled())
log.debug("Loading all values from store.");
sessionInit0(null);
boolean threwEx = true;
try {
store.loadCache(new IgniteBiInClosure<Object, Object>() {
@Override
public void apply(Object k, Object o) {
Object v;
GridCacheVersion ver = null;
if (locStore) {
IgniteBiTuple<Object, GridCacheVersion> t = (IgniteBiTuple<Object, GridCacheVersion>) o;
v = t.get1();
ver = t.get2();
} else
v = o;
KeyCacheObject cacheKey = cctx.toCacheKeyObject(k);
vis.apply(cacheKey, v, ver);
}
}, args);
threwEx = false;
} catch (CacheLoaderException e) {
throw new IgniteCheckedException(e);
} catch (Exception e) {
throw new IgniteCheckedException(new CacheLoaderException(e));
} finally {
sessionEnd0(null, threwEx);
}
if (log.isDebugEnabled())
log.debug("Loaded all values from store.");
return true;
}
LT.warn(log, "Calling Cache.loadCache() method will have no effect, " + "CacheConfiguration.getStore() is not defined for cache: " + cctx.name());
return false;
}
use of org.apache.ignite.lang.IgniteBiTuple in project ignite by apache.
the class GridCacheStoreManagerAdapter method loadAllFromStore.
/**
* @param tx Cache transaction.
* @param keys Keys to load.
* @param vis Key/value closure (only one of vis or verVis can be specified).
* @param verVis Key/value/version closure (only one of vis or verVis can be specified).
* @throws IgniteCheckedException If failed.
*/
private void loadAllFromStore(@Nullable IgniteInternalTx tx, Collection<? extends KeyCacheObject> keys, @Nullable final IgniteBiInClosure<KeyCacheObject, Object> vis, @Nullable final GridInClosure3<KeyCacheObject, Object, GridCacheVersion> verVis) throws IgniteCheckedException {
assert vis != null ^ verVis != null;
assert verVis == null || locStore;
final boolean convert = verVis == null;
if (!keys.isEmpty()) {
if (keys.size() == 1) {
KeyCacheObject key = F.first(keys);
if (convert)
vis.apply(key, load(tx, key));
else {
IgniteBiTuple<Object, GridCacheVersion> t = (IgniteBiTuple<Object, GridCacheVersion>) loadFromStore(tx, key, false);
if (t != null)
verVis.apply(key, t.get1(), t.get2());
}
return;
}
Collection<Object> keys0 = F.viewReadOnly(keys, new C1<KeyCacheObject, Object>() {
@Override
public Object apply(KeyCacheObject key) {
return cctx.unwrapBinaryIfNeeded(key, !convertBinary());
}
});
if (log.isDebugEnabled())
log.debug("Loading values from store for keys: " + keys0);
sessionInit0(tx);
boolean threwEx = true;
try {
IgniteBiInClosure<Object, Object> c = new CI2<Object, Object>() {
@SuppressWarnings("ConstantConditions")
@Override
public void apply(Object k, Object val) {
if (convert) {
Object v = convert(val);
vis.apply(cctx.toCacheKeyObject(k), v);
} else {
IgniteBiTuple<Object, GridCacheVersion> v = (IgniteBiTuple<Object, GridCacheVersion>) val;
if (v != null)
verVis.apply(cctx.toCacheKeyObject(k), v.get1(), v.get2());
}
}
};
if (keys.size() > singleThreadGate.loadAllThreshold()) {
Map<Object, Object> map = store.loadAll(keys0);
if (map != null) {
for (Map.Entry<Object, Object> e : map.entrySet()) c.apply(cctx.toCacheKeyObject(e.getKey()), e.getValue());
}
} else
singleThreadGate.loadAll(keys0, c);
threwEx = false;
} catch (ClassCastException e) {
handleClassCastException(e);
} catch (CacheLoaderException e) {
throw new IgniteCheckedException(e);
} catch (Exception e) {
throw new IgniteCheckedException(new CacheLoaderException(e));
} finally {
sessionEnd0(tx, threwEx);
}
if (log.isDebugEnabled())
log.debug("Loaded values from store for keys: " + keys0);
}
}
use of org.apache.ignite.lang.IgniteBiTuple in project ignite by apache.
the class GridCacheStoreManagerAdapter method putAll.
/** {@inheritDoc} */
@Override
public final boolean putAll(@Nullable IgniteInternalTx tx, Map<? extends KeyCacheObject, IgniteBiTuple<? extends CacheObject, GridCacheVersion>> map) throws IgniteCheckedException {
if (F.isEmpty(map))
return true;
if (map.size() == 1) {
Map.Entry<? extends KeyCacheObject, IgniteBiTuple<? extends CacheObject, GridCacheVersion>> e = ((Map<? extends KeyCacheObject, IgniteBiTuple<? extends CacheObject, GridCacheVersion>>) map).entrySet().iterator().next();
return put(tx, e.getKey(), e.getValue().get1(), e.getValue().get2());
} else {
if (store != null) {
EntriesView entries = new EntriesView(map);
if (log.isDebugEnabled())
log.debug("Storing values in cache store [entries=" + entries + ']');
sessionInit0(tx);
boolean threwEx = true;
try {
store.writeAll(entries);
threwEx = false;
} catch (ClassCastException e) {
handleClassCastException(e);
} catch (Exception e) {
if (!(e instanceof CacheWriterException))
e = new CacheWriterException(e);
if (!entries.isEmpty()) {
List<Object> keys = new ArrayList<>(entries.size());
for (Cache.Entry<?, ?> entry : entries) keys.add(entry.getKey());
throw new CacheStorePartialUpdateException(keys, e);
}
throw new IgniteCheckedException(e);
} finally {
sessionEnd0(tx, threwEx);
}
if (log.isDebugEnabled())
log.debug("Stored value in cache store [entries=" + entries + ']');
return true;
}
return false;
}
}
use of org.apache.ignite.lang.IgniteBiTuple in project ignite by apache.
the class GridJobWorker method finishJob.
/**
* @param res Resuilt.
* @param ex Exception
* @param sndReply If {@code true}, reply will be sent.
* @param retry If {@code true}, retry response will be sent.
*/
void finishJob(@Nullable Object res, @Nullable IgniteException ex, boolean sndReply, boolean retry) {
// Avoid finishing a job more than once from different threads.
if (!finishing.compareAndSet(false, true))
return;
// Do not send reply if job has been cancelled from system.
if (sndReply)
sndReply = !sysCancelled;
// We should save message ID here since listener callback will reset sequence.
ClusterNode sndNode = ctx.discovery().node(taskNode.id());
finishTime = U.currentTimeMillis();
Collection<IgniteBiTuple<Integer, String>> evts = null;
try {
if (ses.isFullSupport())
evtLsnr.onBeforeJobResponseSent(this);
// Send response back only if job has not timed out.
if (!isTimedOut()) {
if (sndReply) {
if (sndNode == null) {
onMasterNodeLeft();
U.warn(log, "Failed to reply to sender node because it left grid [nodeId=" + taskNode.id() + ", ses=" + ses + ", jobId=" + ses.getJobId() + ", job=" + job + ']');
// Record job reply failure.
if (!internal && ctx.event().isRecordable(EVT_JOB_FAILED))
evts = addEvent(evts, EVT_JOB_FAILED, "Job reply failed (task node left grid): " + job);
} else {
try {
byte[] resBytes = null;
byte[] exBytes = null;
byte[] attrBytes = null;
boolean loc = ctx.localNodeId().equals(sndNode.id()) && !ctx.config().isMarshalLocalJobs();
Map<Object, Object> attrs = jobCtx.getAttributes();
// Try serialize response, and if exception - return to client.
if (!loc) {
try {
resBytes = U.marshal(marsh, res);
} catch (IgniteCheckedException e) {
resBytes = U.marshal(marsh, null);
if (ex != null)
ex.addSuppressed(e);
else
ex = U.convertException(e);
U.error(log, "Failed to serialize job response [nodeId=" + taskNode.id() + ", ses=" + ses + ", jobId=" + ses.getJobId() + ", job=" + job + ", resCls=" + (res == null ? null : res.getClass()) + ']', e);
}
try {
attrBytes = U.marshal(marsh, attrs);
} catch (IgniteCheckedException e) {
attrBytes = U.marshal(marsh, Collections.emptyMap());
if (ex != null)
ex.addSuppressed(e);
else
ex = U.convertException(e);
U.error(log, "Failed to serialize job attributes [nodeId=" + taskNode.id() + ", ses=" + ses + ", jobId=" + ses.getJobId() + ", job=" + job + ", attrs=" + attrs + ']', e);
}
try {
exBytes = U.marshal(marsh, ex);
} catch (IgniteCheckedException e) {
String msg = "Failed to serialize job exception [nodeId=" + taskNode.id() + ", ses=" + ses + ", jobId=" + ses.getJobId() + ", job=" + job + ", msg=\"" + e.getMessage() + "\"]";
ex = new IgniteException(msg);
U.error(log, msg, e);
exBytes = U.marshal(marsh, ex);
}
}
if (ex != null) {
if (isStarted) {
// Job failed.
if (!internal && ctx.event().isRecordable(EVT_JOB_FAILED))
evts = addEvent(evts, EVT_JOB_FAILED, "Job failed due to exception [ex=" + ex + ", job=" + job + ']');
} else if (!internal && ctx.event().isRecordable(EVT_JOB_REJECTED))
evts = addEvent(evts, EVT_JOB_REJECTED, "Job has not been started " + "[ex=" + ex + ", job=" + job + ']');
} else if (!internal && ctx.event().isRecordable(EVT_JOB_FINISHED))
evts = addEvent(evts, EVT_JOB_FINISHED, /*no message for success. */
null);
GridJobExecuteResponse jobRes = new GridJobExecuteResponse(ctx.localNodeId(), ses.getId(), ses.getJobId(), exBytes, loc ? ex : null, resBytes, loc ? res : null, attrBytes, loc ? attrs : null, isCancelled(), retry ? ctx.cache().context().exchange().readyAffinityVersion() : null);
long timeout = ses.getEndTime() - U.currentTimeMillis();
if (timeout <= 0)
// Ignore the actual timeout and send response anyway.
timeout = 1;
if (ses.isFullSupport()) {
// Send response to designated job topic.
// Always go through communication to preserve order,
// if attributes are enabled.
ctx.io().sendOrderedMessage(sndNode, taskTopic, jobRes, internal ? MANAGEMENT_POOL : SYSTEM_POOL, timeout, false);
} else if (ctx.localNodeId().equals(sndNode.id()))
ctx.task().processJobExecuteResponse(ctx.localNodeId(), jobRes);
else
// Send response to common topic as unordered message.
ctx.io().sendToGridTopic(sndNode, TOPIC_TASK, jobRes, internal ? MANAGEMENT_POOL : SYSTEM_POOL);
} catch (IgniteCheckedException e) {
// Log and invoke the master-leave callback.
if (isDeadNode(taskNode.id())) {
onMasterNodeLeft();
// Avoid stack trace for left nodes.
U.warn(log, "Failed to reply to sender node because it left grid " + "[nodeId=" + taskNode.id() + ", jobId=" + ses.getJobId() + ", ses=" + ses + ", job=" + job + ']');
} else
U.error(log, "Error sending reply for job [nodeId=" + sndNode.id() + ", jobId=" + ses.getJobId() + ", ses=" + ses + ", job=" + job + ']', e);
if (!internal && ctx.event().isRecordable(EVT_JOB_FAILED))
evts = addEvent(evts, EVT_JOB_FAILED, "Failed to send reply for job [nodeId=" + taskNode.id() + ", job=" + job + ']');
}// it gets thrown for some reason.
catch (Exception e) {
String msg = "Failed to send reply for job [nodeId=" + taskNode.id() + ", job=" + job + ']';
U.error(log, msg, e);
if (!internal && ctx.event().isRecordable(EVT_JOB_FAILED))
evts = addEvent(evts, EVT_JOB_FAILED, msg);
}
}
} else {
if (ex != null) {
if (isStarted) {
if (!internal && ctx.event().isRecordable(EVT_JOB_FAILED))
evts = addEvent(evts, EVT_JOB_FAILED, "Job failed due to exception [ex=" + ex + ", job=" + job + ']');
} else if (!internal && ctx.event().isRecordable(EVT_JOB_REJECTED))
evts = addEvent(evts, EVT_JOB_REJECTED, "Job has not been started [ex=" + ex + ", job=" + job + ']');
} else if (!internal && ctx.event().isRecordable(EVT_JOB_FINISHED))
evts = addEvent(evts, EVT_JOB_FINISHED, /*no message for success. */
null);
}
} else // Job timed out.
if (!internal && ctx.event().isRecordable(EVT_JOB_FAILED))
evts = addEvent(evts, EVT_JOB_FAILED, "Job failed due to timeout: " + job);
} finally {
if (evts != null) {
for (IgniteBiTuple<Integer, String> t : evts) recordEvent(t.get1(), t.get2());
}
// Listener callback.
evtLsnr.onJobFinished(this);
}
}
Aggregations