use of org.apache.asterix.replication.storage.LSMComponentProperties in project asterixdb by apache.
the class ReplicationManager method processJob.
/**
* Processes the replication job based on its specifications
*
* @param job
* The replication job
* @param replicasSockets
* The remote replicas sockets to send the request to.
* @param requestBuffer
* The buffer to use to send the request.
* @throws IOException
*/
private void processJob(IReplicationJob job, Map<String, SocketChannel> replicasSockets, ByteBuffer requestBuffer) throws IOException {
try {
//all of the job's files belong to a single storage partition.
//get any of them to determine the partition from the file path.
String jobFile = job.getJobFiles().iterator().next();
IndexFileProperties indexFileRef = localResourceRepo.getIndexFileRef(jobFile);
if (!replicationStrategy.isMatch(indexFileRef.getDatasetId())) {
return;
}
int jobPartitionId = indexFileRef.getPartitionId();
ByteBuffer responseBuffer = null;
LSMIndexFileProperties asterixFileProperties = new LSMIndexFileProperties();
if (requestBuffer == null) {
requestBuffer = ByteBuffer.allocate(INITIAL_BUFFER_SIZE);
}
boolean isLSMComponentFile = job.getJobType() == ReplicationJobType.LSM_COMPONENT;
try {
//if there isn't already a connection, establish a new one
if (replicasSockets == null) {
replicasSockets = getActiveRemoteReplicasSockets();
}
int remainingFiles = job.getJobFiles().size();
if (job.getOperation() == ReplicationOperation.REPLICATE) {
//if the replication job is an LSM_COMPONENT, its properties are sent first, then its files.
ILSMIndexReplicationJob LSMComponentJob = null;
if (job.getJobType() == ReplicationJobType.LSM_COMPONENT) {
//send LSMComponent properties
LSMComponentJob = (ILSMIndexReplicationJob) job;
LSMComponentProperties lsmCompProp = new LSMComponentProperties(LSMComponentJob, nodeId);
requestBuffer = ReplicationProtocol.writeLSMComponentPropertiesRequest(lsmCompProp, requestBuffer);
sendRequest(replicasSockets, requestBuffer);
}
for (String filePath : job.getJobFiles()) {
remainingFiles--;
Path path = Paths.get(filePath);
if (Files.notExists(path)) {
LOGGER.log(Level.SEVERE, "File deleted before replication: " + filePath);
continue;
}
LOGGER.log(Level.INFO, "Replicating file: " + filePath);
//open file for reading
try (RandomAccessFile fromFile = new RandomAccessFile(filePath, "r");
FileChannel fileChannel = fromFile.getChannel()) {
long fileSize = fileChannel.size();
if (LSMComponentJob != null) {
/**
* since this is LSM_COMPONENT REPLICATE job, the job will contain
* only the component being replicated.
*/
ILSMDiskComponent diskComponent = LSMComponentJob.getLSMIndexOperationContext().getComponentsToBeReplicated().get(0);
long lsnOffset = LSMIndexUtil.getComponentFileLSNOffset(LSMComponentJob.getLSMIndex(), diskComponent, filePath);
asterixFileProperties.initialize(filePath, fileSize, nodeId, isLSMComponentFile, lsnOffset, remainingFiles == 0);
} else {
asterixFileProperties.initialize(filePath, fileSize, nodeId, isLSMComponentFile, -1L, remainingFiles == 0);
}
requestBuffer = ReplicationProtocol.writeFileReplicationRequest(requestBuffer, asterixFileProperties, ReplicationRequestType.REPLICATE_FILE);
Iterator<Map.Entry<String, SocketChannel>> iterator = replicasSockets.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, SocketChannel> entry = iterator.next();
//if the remote replica is not interested in this partition, skip it.
if (!replica2PartitionsMap.get(entry.getKey()).contains(jobPartitionId)) {
continue;
}
SocketChannel socketChannel = entry.getValue();
//transfer request header & file
try {
NetworkingUtil.transferBufferToChannel(socketChannel, requestBuffer);
NetworkingUtil.sendFile(fileChannel, socketChannel);
if (asterixFileProperties.requiresAck()) {
ReplicationRequestType responseType = waitForResponse(socketChannel, responseBuffer);
if (responseType != ReplicationRequestType.ACK) {
throw new IOException("Could not receive ACK from replica " + entry.getKey());
}
}
} catch (IOException e) {
handleReplicationFailure(socketChannel, e);
iterator.remove();
} finally {
requestBuffer.position(0);
}
}
}
}
} else if (job.getOperation() == ReplicationOperation.DELETE) {
for (String filePath : job.getJobFiles()) {
remainingFiles--;
asterixFileProperties.initialize(filePath, -1, nodeId, isLSMComponentFile, -1L, remainingFiles == 0);
ReplicationProtocol.writeFileReplicationRequest(requestBuffer, asterixFileProperties, ReplicationRequestType.DELETE_FILE);
Iterator<Map.Entry<String, SocketChannel>> iterator = replicasSockets.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry<String, SocketChannel> entry = iterator.next();
//if the remote replica is not interested in this partition, skip it.
if (!replica2PartitionsMap.get(entry.getKey()).contains(jobPartitionId)) {
continue;
}
SocketChannel socketChannel = entry.getValue();
try {
sendRequest(replicasSockets, requestBuffer);
if (asterixFileProperties.requiresAck()) {
waitForResponse(socketChannel, responseBuffer);
}
} catch (IOException e) {
handleReplicationFailure(socketChannel, e);
iterator.remove();
} finally {
requestBuffer.position(0);
}
}
}
}
} finally {
//if sync, close sockets with replicas since they wont be reused
if (job.getExecutionType() == ReplicationExecutionType.SYNC) {
closeReplicaSockets(replicasSockets);
}
}
} finally {
exitReplicatedLSMComponent(job);
}
}
use of org.apache.asterix.replication.storage.LSMComponentProperties in project asterixdb by apache.
the class ReplicationChannel method updateLSMComponentRemainingFiles.
private void updateLSMComponentRemainingFiles(String lsmComponentId) throws IOException {
LSMComponentProperties lsmCompProp = lsmComponentId2PropertiesMap.get(lsmComponentId);
int remainingFile = lsmCompProp.markFileComplete();
//clean up when all the LSM component files have been received.
if (remainingFile == 0) {
if (lsmCompProp.getOpType() == LSMOperationType.FLUSH && lsmCompProp.getReplicaLSN() != null && replicaUniqueLSN2RemoteMapping.containsKey(lsmCompProp.getNodeUniqueLSN())) {
int remainingIndexes = replicaUniqueLSN2RemoteMapping.get(lsmCompProp.getNodeUniqueLSN()).numOfFlushedIndexes.decrementAndGet();
if (remainingIndexes == 0) {
/**
* Note: there is a chance that this will never be removed because some
* index in the dataset was not flushed because it is empty. This could
* be solved by passing only the number of successfully flushed indexes.
*/
replicaUniqueLSN2RemoteMapping.remove(lsmCompProp.getNodeUniqueLSN());
}
}
//delete mask to indicate that this component is now valid.
replicaResourcesManager.markLSMComponentReplicaAsValid(lsmCompProp);
lsmComponentId2PropertiesMap.remove(lsmComponentId);
LOGGER.log(Level.INFO, "Completed LSMComponent " + lsmComponentId + " Replication.");
}
}
Aggregations