Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.hazelcast.multimap.impl.txn.TransactionalMultiMapProxySupport Maven / Gradle / Ivy
/*
* Copyright (c) 2008-2015, Hazelcast, Inc. All Rights Reserved.
*
* Licensed 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 com.hazelcast.multimap.impl.txn;
import com.hazelcast.config.MultiMapConfig;
import com.hazelcast.multimap.impl.MultiMapRecord;
import com.hazelcast.multimap.impl.MultiMapService;
import com.hazelcast.multimap.impl.operations.CountOperation;
import com.hazelcast.multimap.impl.operations.GetAllOperation;
import com.hazelcast.multimap.impl.operations.MultiMapOperationFactory;
import com.hazelcast.multimap.impl.operations.MultiMapResponse;
import com.hazelcast.nio.serialization.Data;
import com.hazelcast.spi.AbstractDistributedObject;
import com.hazelcast.spi.NodeEngine;
import com.hazelcast.spi.OperationService;
import com.hazelcast.transaction.TransactionNotActiveException;
import com.hazelcast.transaction.TransactionalObject;
import com.hazelcast.transaction.impl.Transaction;
import com.hazelcast.transaction.impl.TransactionSupport;
import com.hazelcast.util.ExceptionUtil;
import com.hazelcast.util.ThreadUtil;
import java.util.ArrayList;
import java.util.Collection;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.Future;
import static com.hazelcast.util.Preconditions.checkNotNull;
public abstract class TransactionalMultiMapProxySupport extends AbstractDistributedObject
implements TransactionalObject {
private static final double TIMEOUT_EXTEND_MULTIPLIER = 1.5;
protected final String name;
protected final TransactionSupport tx;
protected final MultiMapConfig config;
private final Map> txMap = new HashMap>();
protected TransactionalMultiMapProxySupport(NodeEngine nodeEngine,
MultiMapService service,
String name,
TransactionSupport tx) {
super(nodeEngine, service);
this.name = name;
this.tx = tx;
this.config = nodeEngine.getConfig().findMultiMapConfig(name);
}
protected void checkTransactionActive() {
if (!tx.getState().equals(Transaction.State.ACTIVE)) {
throw new TransactionNotActiveException("Transaction is not active!");
}
}
protected boolean putInternal(Data key, Data value) {
checkObjectNotNull(key);
checkObjectNotNull(value);
Collection coll = txMap.get(key);
long recordId = -1;
long timeout = tx.getTimeoutMillis();
long ttl = extendTimeout(timeout);
final MultiMapTransactionLog log;
if (coll == null) {
MultiMapResponse response = lockAndGet(key, timeout, ttl);
if (response == null) {
throw new ConcurrentModificationException("Transaction couldn't obtain lock " + getThreadId());
}
recordId = response.getNextRecordId();
coll = createCollection(response.getRecordCollection(getNodeEngine()));
txMap.put(key, coll);
log = new MultiMapTransactionLog(key, name, ttl, getThreadId());
tx.addTransactionLog(log);
} else {
log = (MultiMapTransactionLog) tx.getTransactionLog(getTxLogKey(key));
}
MultiMapRecord record = new MultiMapRecord(config.isBinary() ? value : getNodeEngine().toObject(value));
if (coll.add(record)) {
if (recordId == -1) {
recordId = nextId(key);
}
record.setRecordId(recordId);
TxnPutOperation operation = new TxnPutOperation(name, key, value, recordId);
log.addOperation(operation);
return true;
}
return false;
}
protected boolean removeInternal(Data key, Data value) {
checkObjectNotNull(key);
checkObjectNotNull(value);
Collection coll = txMap.get(key);
long timeout = tx.getTimeoutMillis();
long ttl = extendTimeout(timeout);
final MultiMapTransactionLog log;
if (coll == null) {
MultiMapResponse response = lockAndGet(key, timeout, ttl);
if (response == null) {
throw new ConcurrentModificationException("Transaction couldn't obtain lock " + getThreadId());
}
coll = createCollection(response.getRecordCollection(getNodeEngine()));
txMap.put(key, coll);
log = new MultiMapTransactionLog(key, name, ttl, getThreadId());
tx.addTransactionLog(log);
} else {
log = (MultiMapTransactionLog) tx.getTransactionLog(getTxLogKey(key));
}
MultiMapRecord record = new MultiMapRecord(config.isBinary() ? value : getNodeEngine().toObject(value));
Iterator iterator = coll.iterator();
long recordId = -1;
while (iterator.hasNext()) {
MultiMapRecord r = iterator.next();
if (r.equals(record)) {
iterator.remove();
recordId = r.getRecordId();
break;
}
}
if (recordId != -1) {
TxnRemoveOperation operation = new TxnRemoveOperation(name, key, recordId, value);
log.addOperation(operation);
return recordId != -1;
}
return false;
}
protected Collection removeAllInternal(Data key) {
checkObjectNotNull(key);
long timeout = tx.getTimeoutMillis();
long ttl = extendTimeout(timeout);
Collection coll = txMap.get(key);
final MultiMapTransactionLog log;
if (coll == null) {
MultiMapResponse response = lockAndGet(key, timeout, ttl);
if (response == null) {
throw new ConcurrentModificationException("Transaction couldn't obtain lock " + getThreadId());
}
coll = createCollection(response.getRecordCollection(getNodeEngine()));
log = new MultiMapTransactionLog(key, name, ttl, getThreadId());
tx.addTransactionLog(log);
} else {
log = (MultiMapTransactionLog) tx.getTransactionLog(getTxLogKey(key));
}
txMap.put(key, createCollection());
TxnRemoveAllOperation operation = new TxnRemoveAllOperation(name, key, coll);
log.addOperation(operation);
return coll;
}
protected Collection getInternal(Data key) {
checkObjectNotNull(key);
Collection coll = txMap.get(key);
if (coll == null) {
GetAllOperation operation = new GetAllOperation(name, key);
operation.setThreadId(ThreadUtil.getThreadId());
try {
int partitionId = getNodeEngine().getPartitionService().getPartitionId(key);
final OperationService operationService = getNodeEngine().getOperationService();
Future f = operationService.invokeOnPartition(
MultiMapService.SERVICE_NAME,
operation,
partitionId
);
MultiMapResponse response = f.get();
coll = response.getRecordCollection(getNodeEngine());
} catch (Throwable t) {
throw ExceptionUtil.rethrow(t);
}
}
return coll;
}
protected int valueCountInternal(Data key) {
checkObjectNotNull(key);
Collection coll = txMap.get(key);
if (coll == null) {
CountOperation operation = new CountOperation(name, key);
operation.setThreadId(ThreadUtil.getThreadId());
try {
int partitionId = getNodeEngine().getPartitionService().getPartitionId(key);
final OperationService operationService = getNodeEngine().getOperationService();
Future f = operationService
.invokeOnPartition(MultiMapService.SERVICE_NAME, operation, partitionId);
return f.get();
} catch (Throwable t) {
throw ExceptionUtil.rethrow(t);
}
}
return coll.size();
}
public int size() {
checkTransactionActive();
try {
final OperationService operationService = getNodeEngine().getOperationService();
final Map results = operationService.invokeOnAllPartitions(MultiMapService.SERVICE_NAME,
new MultiMapOperationFactory(name, MultiMapOperationFactory.OperationFactoryType.SIZE));
int size = 0;
for (Object obj : results.values()) {
if (obj == null) {
continue;
}
Integer result = getNodeEngine().toObject(obj);
size += result;
}
for (Data key : txMap.keySet()) {
MultiMapTransactionLog log = (MultiMapTransactionLog) tx.getTransactionLog(getTxLogKey(key));
if (log != null) {
size += log.size();
}
}
return size;
} catch (Throwable t) {
throw ExceptionUtil.rethrow(t);
}
}
private TransactionLogKey getTxLogKey(Data key) {
return new TransactionLogKey(name, key);
}
public final String getServiceName() {
return MultiMapService.SERVICE_NAME;
}
private void checkObjectNotNull(Object o) {
checkNotNull(o, "Object is null");
}
private long getThreadId() {
return ThreadUtil.getThreadId();
}
private MultiMapResponse lockAndGet(Data key, long timeout, long ttl) {
final NodeEngine nodeEngine = getNodeEngine();
TxnLockAndGetOperation operation = new TxnLockAndGetOperation(name, key, timeout, ttl, getThreadId());
try {
int partitionId = nodeEngine.getPartitionService().getPartitionId(key);
final OperationService operationService = nodeEngine.getOperationService();
Future f = operationService.
invokeOnPartition(MultiMapService.SERVICE_NAME, operation, partitionId);
return f.get();
} catch (Throwable t) {
throw ExceptionUtil.rethrow(t);
}
}
private long nextId(Data key) {
final NodeEngine nodeEngine = getNodeEngine();
TxnGenerateRecordIdOperation operation = new TxnGenerateRecordIdOperation(name, key);
try {
int partitionId = nodeEngine.getPartitionService().getPartitionId(key);
final OperationService operationService = nodeEngine.getOperationService();
Future f = operationService.invokeOnPartition(MultiMapService.SERVICE_NAME, operation, partitionId);
return f.get();
} catch (Throwable t) {
throw ExceptionUtil.rethrow(t);
}
}
private Collection createCollection() {
if (config.getValueCollectionType().equals(MultiMapConfig.ValueCollectionType.SET)) {
return new HashSet();
} else if (config.getValueCollectionType().equals(MultiMapConfig.ValueCollectionType.LIST)) {
return new ArrayList();
}
return null;
}
private Collection createCollection(Collection coll) {
if (config.getValueCollectionType().equals(MultiMapConfig.ValueCollectionType.SET)) {
return new HashSet(coll);
} else if (config.getValueCollectionType().equals(MultiMapConfig.ValueCollectionType.LIST)) {
return new ArrayList(coll);
}
return null;
}
private long extendTimeout(long timeout) {
return (long) (timeout * TIMEOUT_EXTEND_MULTIPLIER);
}
}