Example usage for java.nio.channels SeekableByteChannel position

List of usage examples for java.nio.channels SeekableByteChannel position

Introduction

In this page you can find the example usage for java.nio.channels SeekableByteChannel position.

Prototype

long position() throws IOException;

Source Link

Document

Returns this channel's position.

Usage

From source file:Main.java

public static void printDetails(SeekableByteChannel seekableChannel, String msg) {
    try {//from  w w  w. ja  va2s. co  m
        System.out.println(
                msg + ": Size   = " + seekableChannel.size() + ", Position = " + seekableChannel.position());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

From source file:com.arpnetworking.tsdcore.tailer.StatefulTailer.java

private Optional<String> computeHash(final SeekableByteChannel reader, final int hashSize) throws IOException {
    // Don't hash empty data sets
    if (hashSize <= 0) {
        return Optional.absent();
    }/*from w  w  w  .  j a  v a2 s .  co  m*/

    // Validate sufficient data to compute the hash
    final long oldPosition = reader.position();
    reader.position(0);
    if (reader.size() < hashSize) {
        reader.position(oldPosition);
        LOGGER.trace(String.format("Reader size insufficient to compute hash; hashSize=%s, hashSize=%d",
                Integer.valueOf(hashSize), Long.valueOf(reader.size())));
        return Optional.absent();
    }

    // Read the data to hash
    final ByteBuffer buffer = ByteBuffer.allocate(hashSize);
    int totalBytesRead = 0;
    while (totalBytesRead < hashSize) {
        final int bytesRead = reader.read(buffer);
        if (bytesRead < 0) {
            LOGGER.warn(String.format("Unexpected end of file reached; totalBytesRead=%d",
                    Long.valueOf(totalBytesRead)));
            return Optional.absent();
        }
        totalBytesRead += bytesRead;
    }

    // Compute the hash
    _md5.reset();
    final byte[] digest = _md5.digest(buffer.array());
    final String hash = Hex.encodeHexString(digest);
    LOGGER.trace(String.format("Computed hash; hash=%s, bytes=%s", hash, Hex.encodeHexString(buffer.array())));

    // Return the reader to its original state
    reader.position(oldPosition);
    return Optional.of(hash);
}

From source file:com.arpnetworking.metrics.common.tailer.StatefulTailer.java

private Optional<String> computeHash(final SeekableByteChannel reader, final int hashSize) throws IOException {
    // Don't hash empty data sets
    if (hashSize <= 0) {
        return Optional.empty();
    }/*from   www. j a  v  a2 s  .  co  m*/

    // Validate sufficient data to compute the hash
    final long oldPosition = reader.position();
    reader.position(0);
    if (reader.size() < hashSize) {
        reader.position(oldPosition);
        LOGGER.trace().setMessage("Reader size insufficient to compute hash").addData("hashSize", hashSize)
                .addData("readerSize", reader.size()).log();
        return Optional.empty();
    }

    // Read the data to hash
    final ByteBuffer buffer = ByteBuffer.allocate(hashSize);
    int totalBytesRead = 0;
    while (totalBytesRead < hashSize) {
        final int bytesRead = reader.read(buffer);
        if (bytesRead < 0) {
            LOGGER.warn().setMessage("Unexpected end of file reached").addData("totalBytesRead", totalBytesRead)
                    .log();
            return Optional.empty();
        }
        totalBytesRead += bytesRead;
    }

    // Compute the hash
    _md5.reset();
    final byte[] digest = _md5.digest(buffer.array());
    final String hash = Hex.encodeHexString(digest);
    LOGGER.trace().setMessage("Computed hash").addData("hash", hash).log();

    // Return the reader to its original state
    reader.position(oldPosition);
    return Optional.of(hash);
}

From source file:com.arpnetworking.metrics.common.tailer.StatefulTailer.java

private boolean readLines(final SeekableByteChannel reader) throws IOException {
    // Compute the hash if not already set
    if (!_hash.isPresent() && reader.size() >= REQUIRED_BYTES_FOR_HASH) {
        _hash = computeHash(reader, REQUIRED_BYTES_FOR_HASH);
    }/*from ww w  . j  a va  2 s. c o  m*/

    // Track current position in file and next read position
    // NOTE: The next read position is always the beginning of a line
    long position = reader.position();
    long nextReadPosition = position;

    // Reset buffers
    _buffer.clear();
    _lineBuffer.reset();

    // Process available data
    int bufferSize = reader.read(_buffer);
    boolean hasData = false;
    boolean hasCR = false;
    while (isRunning() && bufferSize != -1) {
        hasData = true;
        for (int i = 0; i < bufferSize; i++) {
            final byte ch = _buffer.get(i);
            switch (ch) {
            case '\n':
                hasCR = false;
                handleLine();
                nextReadPosition = position + i + 1;
                updateCheckpoint(nextReadPosition);
                break;
            case '\r':
                if (hasCR) {
                    _lineBuffer.write('\r');
                }
                hasCR = true;
                break;
            default:
                if (hasCR) {
                    hasCR = false;
                    handleLine();
                    nextReadPosition = position + i + 1;
                    updateCheckpoint(nextReadPosition);
                }
                _lineBuffer.write(ch);
            }
        }
        position = reader.position();
        _buffer.clear();
        bufferSize = reader.read(_buffer);
    }

    reader.position(nextReadPosition);
    return hasData;
}

From source file:com.arpnetworking.tsdcore.tailer.StatefulTailer.java

private void readLoop(final SeekableByteChannel reader) throws IOException, InterruptedException {
    Optional<Long> lastChecked = Optional.absent();
    Optional<String> currentReaderPrefixHash = Optional.absent();
    int currentReaderPrefixHashLength = 0;
    while (isRunning()) {
        // Obtain properties of file we expect we are reading
        final Attributes attributes;
        try {// w ww.java 2 s.c  o  m
            attributes = getAttributes(_file, lastChecked);
        } catch (final NoSuchFileException t) {
            rotate(Optional.of(reader),
                    String.format("File rotation detected based attributes access failure; file=%s", _file));

            // Return to the file loop
            return;
        }

        if (attributes.getLength() < reader.position()) {
            // File was rotated; either:
            // 1) Position is past the length of the file
            // 2) The expected file is smaller than the current file
            rotate(Optional.of(reader), String.format(
                    "File rotation detected based on length, position and size; file=%s, length=%d, position=%d, size=%d",
                    _file, Long.valueOf(attributes.getLength()), Long.valueOf(reader.position()),
                    Long.valueOf(reader.size())));

            // Return to the file loop
            return;

        } else {
            // File was _likely_ not rotated
            if (reader.size() > reader.position()) {
                // There is more data in the file
                if (!readLines(reader)) {
                    // There actually isn't any more data in the file; this
                    // means the file was rotated and the new file has more
                    // data than the old file (e.g. rotation from empty).

                    // TODO(vkoskela): Account for missing final newline. [MAI-322]
                    // There is a degenerate case where the last line in a
                    // file does not have a newline. Then readLines will
                    // always find new data, but the file has been rotated
                    // away. We should buffer the contents of partial lines
                    // thereby detecting when the length grows whether we
                    // actually got more data in the current file.

                    rotate(Optional.<SeekableByteChannel>absent(), String.format(
                            "File rotation detected based on length and no new data; file=%s, length=%d, position=%d",
                            _file, Long.valueOf(attributes.getLength()), Long.valueOf(reader.position())));

                    // Return to the file loop
                    return;
                }
                lastChecked = Optional.of(Long.valueOf(_file.lastModified()));

            } else if (attributes.isNewer()) {
                // The file does not contain any additional data, but its
                // last modified date is after the last read date. The file
                // must have rotated and contains the same length of
                // content. This can happen on periodic systems which log
                // the same data at the beginning of each period.

                rotate(Optional.<SeekableByteChannel>absent(),
                        String.format(
                                "File rotation detected based equal length and position but newer"
                                        + "; file=%s, length=%d, position=%d, lastChecked=%s, attributes=%s",
                                _file, Long.valueOf(attributes.getLength()), Long.valueOf(reader.position()),
                                lastChecked.get(), attributes));

                // Return to the file loop
                return;

            } else {
                // The files are the same size and the timestamps are the
                // same. This is more common than it sounds since file
                // modification timestamps are not very precise on many
                // file systems.
                //
                // Since we're not doing anything at this point let's hash
                // the first N bytes of the current file and the expected
                // file to see if we're still working on the same file.

                final Optional<Boolean> hashesSame = compareByHash(currentReaderPrefixHash,
                        currentReaderPrefixHashLength);
                if (hashesSame.isPresent() && !hashesSame.get().booleanValue()) {
                    // The file rotated with the same length!
                    rotate(Optional.<SeekableByteChannel>absent(),
                            String.format("File rotation detected based on hash; file=%s", _file));

                    // Return to the file loop
                    return;
                }
                // else: the files are empty or the hashes are the same. In
                // either case we don't have enough data to determine if
                // the files are different; we'll need to wait and see when
                // more data is written if the size and length diverge.

                // TODO(vkoskela): Configurable maximum rotation hash size. [MAI-323]
                // TODO(vkoskela): Configurable minimum rotation hash size. [MAI-324]
                // TODO(vkoskela): Configurable identity hash size. [MAI-325]
                // TODO(vkoskela): We should add a rehash interval. [MAI-326]
                // This interval would be separate from the read interval,
                // and generally longer, preventing us from rehashing the
                // file every interval; but short enough that we don't wait
                // too long before realizing a slowly growing file was
                // rotated.
            }
        }

        // Compute the prefix hash unless we have an identity
        if (!_hash.isPresent()) {
            currentReaderPrefixHashLength = (int) Math.min(reader.size(), REQUIRED_BYTES_FOR_HASH);
            currentReaderPrefixHash = computeHash(reader, currentReaderPrefixHashLength);
        }

        // Read interval
        _trigger.waitOnTrigger();

        // Update the reader position
        updateCheckpoint(reader.position());
    }
}

From source file:com.arpnetworking.metrics.common.tailer.StatefulTailer.java

private void readLoop(final SeekableByteChannel reader) throws IOException, InterruptedException {
    Optional<Long> lastChecked = Optional.empty();
    Optional<String> currentReaderPrefixHash = Optional.empty();
    int currentReaderPrefixHashLength = 0;
    while (isRunning()) {
        // Obtain properties of file we expect we are reading
        final Attributes attributes;
        try {//  ww  w  .j  a va  2s  .  com
            attributes = getAttributes(_file, lastChecked);
        } catch (final NoSuchFileException t) {
            rotate(Optional.of(reader),
                    String.format("File rotation detected based attributes access failure; file=%s", _file));

            // Return to the file loop
            return;
        }

        if (attributes.getLength() < reader.position()) {
            // File was rotated; either:
            // 1) Position is past the length of the file
            // 2) The expected file is smaller than the current file
            rotate(Optional.of(reader), String.format(
                    "File rotation detected based on length, position and size; file=%s, length=%d, position=%d, size=%d",
                    _file, attributes.getLength(), reader.position(), reader.size()));

            // Return to the file loop
            return;

        } else {
            // File was _likely_ not rotated
            if (reader.size() > reader.position()) {
                // There is more data in the file
                if (!readLines(reader)) {
                    // There actually isn't any more data in the file; this
                    // means the file was rotated and the new file has more
                    // data than the old file (e.g. rotation from empty).

                    // TODO(vkoskela): Account for missing final newline. [MAI-322]
                    // There is a degenerate case where the last line in a
                    // file does not have a newline. Then readLines will
                    // always find new data, but the file has been rotated
                    // away. We should buffer the contents of partial lines
                    // thereby detecting when the length grows whether we
                    // actually got more data in the current file.

                    rotate(Optional.<SeekableByteChannel>empty(), String.format(
                            "File rotation detected based on length and no new data; file=%s, length=%d, position=%d",
                            _file, attributes.getLength(), reader.position()));

                    // Return to the file loop
                    return;
                }
                lastChecked = Optional.of(attributes.getLastModifiedTime());

                // This control path, specifically, successfully reading
                // data from the file does not trigger a wait. This permits
                // continuous reading without pausing.

            } else if (attributes.isNewer()) {
                // The file does not contain any additional data, but its
                // last modified date is after the last read date. The file
                // must have rotated and contains the same length of
                // content. This can happen on periodic systems which log
                // the same data at the beginning of each period.

                rotate(Optional.<SeekableByteChannel>empty(), String.format(
                        "File rotation detected based equal length and position but newer"
                                + "; file=%s, length=%d, position=%d, lastChecked=%s, attributes=%s",
                        _file, attributes.getLength(), reader.position(), lastChecked.get(), attributes));

                // Return to the file loop
                return;

            } else {
                // The files are the same size and the timestamps are the
                // same. This is more common than it sounds since file
                // modification timestamps are not very precise on many
                // file systems.
                //
                // Since we're not doing anything at this point let's hash
                // the first N bytes of the current file and the expected
                // file to see if we're still working on the same file.

                final Optional<Boolean> hashesSame = compareByHash(currentReaderPrefixHash,
                        currentReaderPrefixHashLength);
                if (hashesSame.isPresent() && !hashesSame.get()) {
                    // The file rotated with the same length!
                    rotate(Optional.<SeekableByteChannel>empty(),
                            String.format("File rotation detected based on hash; file=%s", _file));

                    // Return to the file loop
                    return;
                }
                // else: the files are empty or the hashes are the same. In
                // either case we don't have enough data to determine if
                // the files are different; we'll need to wait and see when
                // more data is written if the size and age diverge.

                // TODO(vkoskela): Configurable maximum rotation hash size. [MAI-323]
                // TODO(vkoskela): Configurable minimum rotation hash size. [MAI-324]
                // TODO(vkoskela): Configurable identity hash size. [MAI-325]
                // TODO(vkoskela): We should add a rehash interval. [MAI-326]
                // This interval would be separate from the read interval,
                // and generally longer, preventing us from rehashing the
                // file every interval; but short enough that we don't wait
                // too long before realizing a slowly growing file was
                // rotated.

                // Read interval
                _trigger.waitOnTrigger();
            }
        }

        // Compute the prefix hash unless we have an identity
        final int newPrefixHashLength = (int) Math.min(reader.size(), REQUIRED_BYTES_FOR_HASH);
        if (!_hash.isPresent() && (currentReaderPrefixHashLength != newPrefixHashLength
                || !currentReaderPrefixHash.isPresent())) {
            currentReaderPrefixHashLength = newPrefixHashLength;
            currentReaderPrefixHash = computeHash(reader, currentReaderPrefixHashLength);
        }

        // Update the reader position
        updateCheckpoint(reader.position());
    }
}