Search in sources :

Example 1 with ReplicationRequestType

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);
    }
}
Also used : Path(java.nio.file.Path) SocketChannel(java.nio.channels.SocketChannel) LSMComponentProperties(org.apache.asterix.replication.storage.LSMComponentProperties) FileChannel(java.nio.channels.FileChannel) IOException(java.io.IOException) ILSMIndexReplicationJob(org.apache.hyracks.storage.am.lsm.common.api.ILSMIndexReplicationJob) ByteBuffer(java.nio.ByteBuffer) ILSMDiskComponent(org.apache.hyracks.storage.am.lsm.common.api.ILSMDiskComponent) Entry(java.util.Map.Entry) RandomAccessFile(java.io.RandomAccessFile) LSMIndexFileProperties(org.apache.asterix.replication.storage.LSMIndexFileProperties) IndexFileProperties(org.apache.asterix.common.storage.IndexFileProperties) ReplicationRequestType(org.apache.asterix.replication.functions.ReplicationProtocol.ReplicationRequestType) LSMIndexFileProperties(org.apache.asterix.replication.storage.LSMIndexFileProperties) Iterator(java.util.Iterator) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap)

Example 2 with ReplicationRequestType

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);
                }
            }
        }
    }
}
Also used : SocketChannel(java.nio.channels.SocketChannel) ReplicationRequestType(org.apache.asterix.replication.functions.ReplicationProtocol.ReplicationRequestType) ReplicaIndexFlushRequest(org.apache.asterix.replication.functions.ReplicaIndexFlushRequest) ByteBuffer(java.nio.ByteBuffer)

Example 3 with ReplicationRequestType

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);
    }
}
Also used : ReplicaFilesRequest(org.apache.asterix.replication.functions.ReplicaFilesRequest) SocketChannel(java.nio.channels.SocketChannel) RandomAccessFile(java.io.RandomAccessFile) ReplicationRequestType(org.apache.asterix.replication.functions.ReplicationProtocol.ReplicationRequestType) LSMIndexFileProperties(org.apache.asterix.replication.storage.LSMIndexFileProperties) FileChannel(java.nio.channels.FileChannel) RandomAccessFile(java.io.RandomAccessFile) File(java.io.File)

Aggregations

SocketChannel (java.nio.channels.SocketChannel)3 ReplicationRequestType (org.apache.asterix.replication.functions.ReplicationProtocol.ReplicationRequestType)3 RandomAccessFile (java.io.RandomAccessFile)2 ByteBuffer (java.nio.ByteBuffer)2 FileChannel (java.nio.channels.FileChannel)2 LSMIndexFileProperties (org.apache.asterix.replication.storage.LSMIndexFileProperties)2 File (java.io.File)1 IOException (java.io.IOException)1 Path (java.nio.file.Path)1 HashMap (java.util.HashMap)1 Iterator (java.util.Iterator)1 Map (java.util.Map)1 Entry (java.util.Map.Entry)1 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)1 IndexFileProperties (org.apache.asterix.common.storage.IndexFileProperties)1 ReplicaFilesRequest (org.apache.asterix.replication.functions.ReplicaFilesRequest)1 ReplicaIndexFlushRequest (org.apache.asterix.replication.functions.ReplicaIndexFlushRequest)1 LSMComponentProperties (org.apache.asterix.replication.storage.LSMComponentProperties)1 ILSMDiskComponent (org.apache.hyracks.storage.am.lsm.common.api.ILSMDiskComponent)1 ILSMIndexReplicationJob (org.apache.hyracks.storage.am.lsm.common.api.ILSMIndexReplicationJob)1