Package io.crate.blob.pending_transfer

Source Code of io.crate.blob.pending_transfer.PutHeadChunkRunnable

/*
* Licensed to CRATE Technology GmbH ("Crate") under one or more contributor
* license agreements.  See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.  Crate licenses
* this file to you 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.
*
* However, if you have executed another commercial license agreement
* with Crate these terms will supersede the license and you may use the
* software solely pursuant to the terms of the relevant commercial agreement.
*/

package io.crate.blob.pending_transfer;

import io.crate.blob.BlobTransferTarget;
import org.elasticsearch.cluster.node.DiscoveryNode;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.Loggers;
import org.elasticsearch.transport.EmptyTransportResponseHandler;
import org.elasticsearch.transport.TransportRequestOptions;
import org.elasticsearch.transport.TransportService;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.file.*;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

public class PutHeadChunkRunnable implements Runnable {

    private final File pendingFile;
    private final long bytesToSend;
    private final DiscoveryNode recipientNode;
    private final TransportService transportService;
    private final BlobTransferTarget blobTransferTarget;
    private final UUID transferId;
    private WatchKey watchKey;
    private WatchService watcher;
    private final ESLogger logger = Loggers.getLogger(getClass());

    public PutHeadChunkRunnable(File pendingFile, long bytesToSend,
                                TransportService transportService,
                                BlobTransferTarget blobTransferTarget,
                                DiscoveryNode recipientNode, UUID transferId) {
        this.pendingFile = pendingFile;
        this.bytesToSend = bytesToSend;
        this.recipientNode = recipientNode;
        this.blobTransferTarget = blobTransferTarget;
        this.transferId = transferId;
        this.transportService = transportService;
    }

    @Override
    public void run() {
        try {
            try (FileInputStream inputStream = new FileInputStream(pendingFile)) {
                int bufSize = 4096;
                int bytesRead;
                int size;
                int maxFileGrowthWait = 5;
                int fileGrowthWaited = 0;
                byte[] buffer = new byte[bufSize];
                long remainingBytes = bytesToSend;

                while (remainingBytes > 0) {
                    size = (int) Math.min(bufSize, remainingBytes);
                    bytesRead = inputStream.read(buffer, 0, size);
                    if (bytesRead < size) {
                        waitUntilFileHasGrown(pendingFile);
                        fileGrowthWaited++;
                        if (fileGrowthWaited == maxFileGrowthWait) {
                            throw new HeadChunkFileTooSmallException(pendingFile.getAbsolutePath());
                        }
                        if (bytesRead < 1) {
                            continue;
                        }
                    }
                    remainingBytes -= bytesRead;

                    transportService.submitRequest(
                        recipientNode,
                        BlobHeadRequestHandler.Actions.PUT_BLOB_HEAD_CHUNK,
                        new PutBlobHeadChunkRequest(transferId, new BytesArray(buffer, 0, bytesRead)),
                        TransportRequestOptions.options(),
                        EmptyTransportResponseHandler.INSTANCE_SAME
                    ).txGet();
                }
            }
        } catch (FileNotFoundException ex) {
            logger.error("Can't send HeadChunk - file not found", ex);
        } catch (IOException ex) {
            logger.error("IOException in PutHeadChunkRunnable", ex);
        } finally {
            blobTransferTarget.putHeadChunkTransferFinished(transferId);
        }
    }

    private void waitUntilFileHasGrown(File pendingFile)
    {
        try {
            if (watcher == null) {
                initWatcher(pendingFile.getParent());
            }

            watchKey = watcher.poll(5, TimeUnit.SECONDS);
            if (watchKey == null) {
                return;
            }
            for (WatchEvent<?> event : watchKey.pollEvents()) {
                WatchEvent.Kind<?> kind = event.kind();

                if (kind == StandardWatchEventKinds.OVERFLOW) {
                    continue;
                }

                @SuppressWarnings("unchecked")
                WatchEvent<Path> ev = (WatchEvent<Path>)event;
                Path filename = ev.context();
                if (filename.toString().equals(pendingFile.getName())) {
                    break;
                }
            }
        } catch (IOException | InterruptedException ex) {
            logger.warn(ex.getMessage(), ex);
        }
    }

    private void initWatcher(String directoryToWatch) throws IOException {
        FileSystem fs = FileSystems.getDefault();
        watcher = fs.newWatchService();
        Path path = fs.getPath(directoryToWatch);
        watchKey = path.register(watcher, StandardWatchEventKinds.ENTRY_MODIFY);
    }
}
TOP

Related Classes of io.crate.blob.pending_transfer.PutHeadChunkRunnable

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.