blob: 2b76772b7708a23cd6395a9a0c661708a236b081 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ignite.internal.processors.cache.transactions;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.cache.CacheWriteSynchronizationMode;
import org.apache.ignite.internal.cluster.ClusterTopologyServerNotFoundException;
import org.apache.ignite.internal.processors.cache.CacheStoppedException;
import org.apache.ignite.internal.processors.cache.GridCacheContext;
import org.apache.ignite.internal.processors.cache.GridCacheSharedContext;
import org.apache.ignite.internal.processors.cache.distributed.dht.GridDhtTopologyFuture;
import org.apache.ignite.internal.processors.cache.store.CacheStoreManager;
import org.apache.ignite.internal.util.GridIntList;
import org.apache.ignite.internal.util.future.GridFutureAdapter;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.CU;
import org.apache.ignite.internal.util.typedef.internal.S;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.jetbrains.annotations.Nullable;
import static org.apache.ignite.cache.CacheWriteSynchronizationMode.FULL_ASYNC;
/**
*
*/
public class IgniteTxImplicitSingleStateImpl extends IgniteTxLocalStateAdapter {
/** */
private GridCacheContext cacheCtx;
/** Entry is stored as singleton list for performance optimization. */
private List<IgniteTxEntry> entry;
/** */
private boolean init;
/** */
private boolean recovery;
/** {@inheritDoc} */
@Override public void addActiveCache(GridCacheContext ctx, boolean recovery, IgniteTxAdapter tx)
throws IgniteCheckedException {
assert cacheCtx == null : "Cache already set [cur=" + cacheCtx.name() + ", new=" + ctx.name() + ']';
assert tx.local();
cacheCtx = ctx;
this.recovery = recovery;
tx.activeCachesDeploymentEnabled(cacheCtx.deploymentEnabled());
}
/** {@inheritDoc} */
@Nullable @Override public GridIntList cacheIds() {
return GridIntList.asList(cacheCtx.cacheId());
}
/** {@inheritDoc} */
@Nullable @Override public GridCacheContext singleCacheContext(GridCacheSharedContext cctx) {
return cacheCtx;
}
/** {@inheritDoc} */
@Nullable @Override public Integer firstCacheId() {
return cacheCtx != null ? cacheCtx.cacheId() : null;
}
/** {@inheritDoc} */
@Override public void unwindEvicts(GridCacheSharedContext cctx) {
if (entry == null || entry.isEmpty())
return;
assert entry.size() == 1;
GridCacheContext ctx = cctx.cacheContext(entry.get(0).cacheId());
if (ctx != null)
CU.unwindEvicts(ctx);
}
/** {@inheritDoc} */
@Override public void awaitLastFuture(GridCacheSharedContext ctx) {
if (cacheCtx == null)
return;
cacheCtx.cache().awaitLastFut();
}
/** {@inheritDoc} */
@Override public boolean implicitSingle() {
return true;
}
/** {@inheritDoc} */
@Override public IgniteCheckedException validateTopology(
GridCacheSharedContext cctx,
boolean read,
GridDhtTopologyFuture topFut
) {
if (cacheCtx == null)
return null;
Throwable err = topFut.validateCache(cacheCtx, recovery, read, null, entry);
if (err != null) {
return new IgniteCheckedException(
"Failed to perform cache operation (cache topology is not valid): "
+ U.maskName(cacheCtx.name()), err);
}
if (CU.affinityNodes(cacheCtx, topFut.topologyVersion()).isEmpty()) {
return new ClusterTopologyServerNotFoundException("Failed to map keys for cache (all " +
"partition nodes left the grid): " + cacheCtx.name());
}
return null;
}
/** {@inheritDoc} */
@Override public CacheWriteSynchronizationMode syncMode(GridCacheSharedContext cctx) {
return cacheCtx != null ? cacheCtx.config().getWriteSynchronizationMode() : FULL_ASYNC;
}
/** {@inheritDoc} */
@Override public GridDhtTopologyFuture topologyReadLock(GridCacheSharedContext cctx, GridFutureAdapter<?> fut) {
if (cacheCtx == null || cacheCtx.isLocal())
return cctx.exchange().lastTopologyFuture();
cacheCtx.topology().readLock();
if (cacheCtx.topology().stopping()) {
fut.onDone(new CacheStoppedException(cacheCtx.name()));
return null;
}
return cacheCtx.topology().topologyVersionFuture();
}
/** {@inheritDoc} */
@Override public void topologyReadUnlock(GridCacheSharedContext cctx) {
if (cacheCtx == null || cacheCtx.isLocal())
return;
cacheCtx.topology().readUnlock();
}
/** {@inheritDoc} */
@Override public boolean storeWriteThrough(GridCacheSharedContext cctx) {
if (cacheCtx == null)
return false;
CacheStoreManager store = cacheCtx.store();
return store.configured() && store.isWriteThrough();
}
/** {@inheritDoc} */
@Override public boolean hasInterceptor(GridCacheSharedContext cctx) {
GridCacheContext ctx0 = cacheCtx;
return ctx0 != null && ctx0.config().getInterceptor() != null;
}
/** {@inheritDoc} */
@Override public Collection<CacheStoreManager> stores(GridCacheSharedContext cctx) {
if (cacheCtx == null)
return null;
CacheStoreManager store = cacheCtx.store();
if (store.configured())
return Collections.singleton(store);
return null;
}
/** {@inheritDoc} */
@Override public void onTxEnd(GridCacheSharedContext cctx, IgniteInternalTx tx, boolean commit) {
if (cacheCtx != null)
onTxEnd(cacheCtx, tx, commit);
}
/** {@inheritDoc} */
@Override public IgniteTxEntry entry(IgniteTxKey key) {
if (entry != null && entry.get(0).txKey().equals(key))
return entry.get(0);
return null;
}
/** {@inheritDoc} */
@Override public boolean hasWriteKey(IgniteTxKey key) {
return entry != null && entry.get(0).txKey().equals(key);
}
/** {@inheritDoc} */
@Override public Set<IgniteTxKey> readSet() {
return Collections.emptySet();
}
/** {@inheritDoc} */
@Override public Set<IgniteTxKey> writeSet() {
if (entry != null) {
Set<IgniteTxKey> set = new HashSet<>(3, 0.75f);
set.add(entry.get(0).txKey());
return set;
}
else
return Collections.<IgniteTxKey>emptySet();
}
/** {@inheritDoc} */
@Override public Collection<IgniteTxEntry> writeEntries() {
return entry != null ? entry : Collections.<IgniteTxEntry>emptyList();
}
/** {@inheritDoc} */
@Override public Collection<IgniteTxEntry> readEntries() {
return Collections.emptyList();
}
/** {@inheritDoc} */
@Override public Map<IgniteTxKey, IgniteTxEntry> writeMap() {
return entry != null ? F.asMap(entry.get(0).txKey(), entry.get(0)) :
Collections.<IgniteTxKey, IgniteTxEntry>emptyMap();
}
/** {@inheritDoc} */
@Override public Map<IgniteTxKey, IgniteTxEntry> readMap() {
return Collections.emptyMap();
}
/** {@inheritDoc} */
@Override public boolean empty() {
return entry == null;
}
/** {@inheritDoc} */
@Override public Collection<IgniteTxEntry> allEntries() {
return entry != null ? entry : Collections.<IgniteTxEntry>emptyList();
}
/** {@inheritDoc} */
@Override public boolean init(int txSize) {
if (!init) {
init = true;
return true;
}
return false;
}
/** {@inheritDoc} */
@Override public boolean initialized() {
return init;
}
/** {@inheritDoc} */
@Override public void addEntry(IgniteTxEntry entry) {
assert this.entry == null : "Entry already set [cur=" + this.entry + ", new=" + entry + ']';
this.entry = Collections.singletonList(entry);
}
/** {@inheritDoc} */
@Override public void seal() {
// No-op.
}
/** {@inheritDoc} */
@Override public IgniteTxEntry singleWrite() {
return entry != null ? entry.get(0) : null;
}
/** {@inheritDoc} */
@Override public boolean mvccEnabled() {
GridCacheContext ctx0 = cacheCtx;
return ctx0 != null && ctx0.mvccEnabled();
}
/** {@inheritDoc} */
@Override public String toString() {
return S.toString(IgniteTxImplicitSingleStateImpl.class, this);
}
}