use of org.apache.asterix.replication.functions.ReplicationProtocol.ReplicationRequestType 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.functions.ReplicationProtocol.ReplicationRequestType in project asterixdb by apache.
the class ReplicationManager method requestFlushLaggingReplicaIndexes.
@Override
public void requestFlushLaggingReplicaIndexes(long nonSharpCheckpointTargetLSN) throws IOException {
long startLSN = logManager.getAppendLSN();
Set<String> replicaIds = getActiveReplicasIds();
if (replicaIds.isEmpty()) {
return;
}
ByteBuffer requestBuffer = ByteBuffer.allocate(INITIAL_BUFFER_SIZE);
for (String replicaId : replicaIds) {
//1. identify replica indexes with LSN less than nonSharpCheckpointTargetLSN.
Map<Long, String> laggingIndexes = replicaResourcesManager.getLaggingReplicaIndexesId2PathMap(replicaId, nonSharpCheckpointTargetLSN);
if (laggingIndexes.size() > 0) {
//2. send request to remote replicas that have lagging indexes.
ReplicaIndexFlushRequest laggingIndexesResponse = null;
try (SocketChannel socketChannel = getReplicaSocket(replicaId)) {
ReplicaIndexFlushRequest laggingIndexesRequest = new ReplicaIndexFlushRequest(laggingIndexes.keySet());
requestBuffer = ReplicationProtocol.writeGetReplicaIndexFlushRequest(requestBuffer, laggingIndexesRequest);
NetworkingUtil.transferBufferToChannel(socketChannel, requestBuffer);
//3. remote replicas will respond with indexes that were not flushed.
ReplicationRequestType responseFunction = waitForResponse(socketChannel, requestBuffer);
if (responseFunction == ReplicationRequestType.FLUSH_INDEX) {
requestBuffer = ReplicationProtocol.readRequest(socketChannel, requestBuffer);
//returning the indexes that were not flushed
laggingIndexesResponse = ReplicationProtocol.readReplicaIndexFlushRequest(requestBuffer);
}
//send goodbye
ReplicationProtocol.sendGoodbye(socketChannel);
}
/**
* 4. update the LSN_MAP for indexes that were not flushed
* to the current append LSN to indicate no operations happened
* since the checkpoint start.
*/
if (laggingIndexesResponse != null) {
for (Long resouceId : laggingIndexesResponse.getLaggingRescouresIds()) {
String indexPath = laggingIndexes.get(resouceId);
Map<Long, Long> indexLSNMap = replicaResourcesManager.getReplicaIndexLSNMap(indexPath);
indexLSNMap.put(ReplicaResourcesManager.REPLICA_INDEX_CREATION_LSN, startLSN);
replicaResourcesManager.updateReplicaIndexLSNMap(indexPath, indexLSNMap);
}
}
}
}
}
use of org.apache.asterix.replication.functions.ReplicationProtocol.ReplicationRequestType in project asterixdb by apache.
the class ReplicationManager method requestReplicaFiles.
//Recovery Method
@Override
public void requestReplicaFiles(String selectedReplicaId, Set<Integer> partitionsToRecover, Set<String> existingFiles) throws IOException {
ReplicaFilesRequest request = new ReplicaFilesRequest(partitionsToRecover, existingFiles);
dataBuffer = ReplicationProtocol.writeGetReplicaFilesRequest(dataBuffer, request);
try (SocketChannel socketChannel = getReplicaSocket(selectedReplicaId)) {
//transfer request
NetworkingUtil.transferBufferToChannel(socketChannel, dataBuffer);
String indexPath;
String destFilePath;
ReplicationRequestType responseFunction = ReplicationProtocol.getRequestType(socketChannel, dataBuffer);
LSMIndexFileProperties fileProperties;
while (responseFunction != ReplicationRequestType.GOODBYE) {
dataBuffer = ReplicationProtocol.readRequest(socketChannel, dataBuffer);
fileProperties = ReplicationProtocol.readFileReplicationRequest(dataBuffer);
//get index path
indexPath = replicaResourcesManager.getIndexPath(fileProperties);
destFilePath = indexPath + File.separator + fileProperties.getFileName();
//create file
File destFile = new File(destFilePath);
destFile.createNewFile();
try (RandomAccessFile fileOutputStream = new RandomAccessFile(destFile, "rw");
FileChannel fileChannel = fileOutputStream.getChannel()) {
fileOutputStream.setLength(fileProperties.getFileSize());
NetworkingUtil.downloadFile(fileChannel, socketChannel);
fileChannel.force(true);
}
//we need to create LSN map for .metadata files that belong to remote replicas
if (!fileProperties.isLSMComponentFile() && !fileProperties.getNodeId().equals(nodeId)) {
//replica index
replicaResourcesManager.initializeReplicaIndexLSNMap(indexPath, logManager.getAppendLSN());
}
responseFunction = ReplicationProtocol.getRequestType(socketChannel, dataBuffer);
}
//send goodbye
ReplicationProtocol.sendGoodbye(socketChannel);
}
}
Aggregations