use of org.apache.asterix.common.exceptions.ACIDException in project asterixdb by apache.
the class UpsertOperationCallbackFactory method createModificationOperationCallback.
@Override
public IModificationOperationCallback createModificationOperationCallback(LocalResource resource, IHyracksTaskContext ctx, IOperatorNodePushable operatorNodePushable) throws HyracksDataException {
DatasetLocalResource aResource = (DatasetLocalResource) resource.getResource();
ITransactionSubsystem txnSubsystem = txnSubsystemProvider.getTransactionSubsystem(ctx);
IResourceLifecycleManager indexLifeCycleManager = txnSubsystem.getAsterixAppRuntimeContextProvider().getDatasetLifecycleManager();
ILSMIndex index = (ILSMIndex) indexLifeCycleManager.get(resource.getPath());
if (index == null) {
throw new HyracksDataException("Index(id:" + resource.getId() + ") is not registered.");
}
try {
ITransactionContext txnCtx = txnSubsystem.getTransactionManager().getTransactionContext(jobId, false);
IModificationOperationCallback modCallback = new UpsertOperationCallback(new DatasetId(datasetId), primaryKeyFields, txnCtx, txnSubsystem.getLockManager(), txnSubsystem, resource.getId(), aResource.getPartition(), resourceType, indexOp);
txnCtx.registerIndexAndCallback(resource.getId(), index, (AbstractOperationCallback) modCallback, true);
return modCallback;
} catch (ACIDException e) {
throw new HyracksDataException(e);
}
}
use of org.apache.asterix.common.exceptions.ACIDException in project asterixdb by apache.
the class PrimaryIndexModificationOperationCallback method before.
@Override
public void before(ITupleReference tuple) throws HyracksDataException {
int pkHash = computePrimaryKeyHashValue(tuple, primaryKeyFields);
try {
if (operatorNodePushable != null) {
/**********************************************************************************
* In order to achieve deadlock-free locking protocol during any write (insert/delete/upsert) operations,
* the following logic is implemented.
* See https://cwiki.apache.org/confluence/display/ASTERIXDB/Deadlock-Free+Locking+Protocol for more details.
* 1. for each entry in a frame
* 2. returnValue = tryLock() for an entry
* 3. if returnValue == false
* 3-1. flush all entries (which already acquired locks) to the next operator
* : this will make all those entries reach commit operator so that corresponding commit logs will be created.
* 3-2. create a WAIT log and wait until logFlusher thread will flush the WAIT log and gives notification
* : this notification guarantees that all locks acquired by this transactor (or all locks acquired for the entries)
* were released.
* 3-3. acquire lock using lock() instead of tryLock() for the failed entry
* : we know for sure this lock call will not cause deadlock since the transactor doesn't hold any other locks.
* 4. create an update log and insert the entry
* From the above logic, step 2 and 3 are implemented in this before() method.
**********************/
//release all locks held by this actor (which is a thread) by flushing partial frame.
boolean tryLockSucceed = lockManager.tryLock(datasetId, pkHash, LockMode.X, txnCtx);
if (!tryLockSucceed) {
//flush entries which have been inserted already to release locks hold by them
operatorNodePushable.flushPartialFrame();
//create WAIT log and wait until the WAIT log is flushed and notified by LogFlusher thread
logWait();
//acquire lock
lockManager.lock(datasetId, pkHash, LockMode.X, txnCtx);
}
} else {
//operatorNodePushable can be null when metadata node operation is executed
lockManager.lock(datasetId, pkHash, LockMode.X, txnCtx);
}
} catch (ACIDException e) {
throw new HyracksDataException(e);
}
}
use of org.apache.asterix.common.exceptions.ACIDException in project asterixdb by apache.
the class PrimaryIndexModificationOperationCallback method found.
@Override
public void found(ITupleReference before, ITupleReference after) throws HyracksDataException {
try {
int pkHash = computePrimaryKeyHashValue(after, primaryKeyFields);
log(pkHash, after, before);
} catch (ACIDException e) {
throw new HyracksDataException(e);
}
}
use of org.apache.asterix.common.exceptions.ACIDException in project asterixdb by apache.
the class SecondaryIndexModificationOperationCallback method found.
@Override
public void found(ITupleReference before, ITupleReference after) throws HyracksDataException {
try {
int pkHash = computePrimaryKeyHashValue(after, primaryKeyFields);
this.log(pkHash, after, before);
} catch (ACIDException e) {
throw new HyracksDataException(e);
}
}
use of org.apache.asterix.common.exceptions.ACIDException in project asterixdb by apache.
the class LogReader method read.
//for random reading
@Override
public ILogRecord read(long LSN) throws ACIDException {
readLSN = LSN;
//wait for the log to be flushed if needed before trying to read it.
synchronized (flushLSN) {
while (readLSN >= flushLSN.get()) {
try {
flushLSN.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
try {
if (logFile == null) {
//get the log file which contains readLSN
getLogFile();
fillLogReadBuffer();
} else if (readLSN < fileBeginLSN || readLSN >= fileBeginLSN + logFile.size()) {
//log is not in the current log file
logFile.close();
getLogFile();
fillLogReadBuffer();
} else if (readLSN < bufferBeginLSN || readLSN >= bufferBeginLSN + readBuffer.limit()) {
//log is not in the current read buffer
fillLogReadBuffer();
} else {
//log is either completely in the current read buffer or truncated
readBuffer.position((int) (readLSN - bufferBeginLSN));
}
} catch (IOException e) {
throw new ACIDException(e);
}
ByteBuffer readBuffer = this.readBuffer;
while (true) {
RecordReadStatus status = logRecord.readLogRecord(readBuffer);
switch(status) {
case LARGE_RECORD:
{
readBuffer = ByteBuffer.allocate(logRecord.getLogSize());
fillLogReadBuffer(logRecord.getLogSize(), readBuffer);
//now see what we have in the refilled buffer
continue;
}
case TRUNCATED:
{
if (!fillLogReadBuffer()) {
throw new IllegalStateException("Could not read LSN(" + LSN + ") from log file id " + logFile.getLogFileId());
}
//now read the complete log record
continue;
}
case BAD_CHKSUM:
{
throw new ACIDException("Log record has incorrect checksum");
}
case OK:
break;
default:
throw new IllegalStateException("Unexpected log read status: " + status);
}
break;
}
logRecord.setLSN(readLSN);
readLSN += logRecord.getLogSize();
return logRecord;
}
Aggregations