Search in sources :

Example 6 with JournalEntry

use of alluxio.proto.journal.Journal.JournalEntry in project alluxio by Alluxio.

the class BackupManager method backup.

/**
 * Writes a backup to the specified stream.
 *
 * @param os the stream to write to
 * @param entryCount will receive total entry count that are backed up
 */
public void backup(OutputStream os, AtomicLong entryCount) throws IOException {
    // Create gZIP compressed stream as back-up stream.
    GzipCompressorOutputStream zipStream = new GzipCompressorOutputStream(os);
    // Executor for taking backup.
    CompletionService<Boolean> completionService = new ExecutorCompletionService<>(Executors.newFixedThreadPool(4, ThreadFactoryUtils.build("master-backup-%d", true)));
    // List of active tasks.
    Set<Future<?>> activeTasks = new HashSet<>();
    // Entry queue will be used as a buffer and synchronization between readers and writer.
    // Use of {@link LinkedBlockingQueue} is preferred because of {@code #drainTo()} method,
    // using which all existing entries can be drained while allowing writes.
    // Processing/draining one-by-one using {@link ConcurrentLinkedQueue} proved to be
    // inefficient compared to draining with dedicated method.
    LinkedBlockingQueue<JournalEntry> journalEntryQueue = new LinkedBlockingQueue<>(ServerConfiguration.getInt(PropertyKey.MASTER_BACKUP_ENTRY_BUFFER_COUNT));
    // Whether buffering is still active.
    AtomicBoolean bufferingActive = new AtomicBoolean(true);
    // Start the timer for backup metrics.
    long startBackupTime = System.currentTimeMillis();
    // Submit master reader task.
    activeTasks.add(completionService.submit(() -> {
        try {
            for (Master master : mRegistry.getServers()) {
                try (CloseableIterator<JournalEntry> it = master.getJournalEntryIterator()) {
                    while (it.hasNext()) {
                        journalEntryQueue.put(it.next());
                        if (Thread.interrupted()) {
                            throw new InterruptedException();
                        }
                    }
                }
            }
            // Put termination entry for signaling the writer.
            journalEntryQueue.put(JournalEntry.newBuilder().setSequenceNumber(TERMINATION_SEQ).build());
            return true;
        } catch (InterruptedException ie) {
            LOG.info("Backup reader task interrupted");
            Thread.currentThread().interrupt();
            throw new RuntimeException("Thread interrupted while reading master state.", ie);
        } finally {
            // Signal reader completion.
            bufferingActive.set(false);
        }
    }));
    // Submit writer task.
    activeTasks.add(completionService.submit(() -> {
        try {
            List<JournalEntry> pendingEntries = new LinkedList<>();
            while (bufferingActive.get() || journalEntryQueue.size() > 0) {
                // Drain pending entries.
                if (0 == journalEntryQueue.drainTo(pendingEntries)) {
                    // No elements at the moment. Fall-back to blocking mode.
                    pendingEntries.add(journalEntryQueue.take());
                }
                if (Thread.interrupted()) {
                    throw new InterruptedException();
                }
                // Write entries to back-up stream.
                for (JournalEntry journalEntry : pendingEntries) {
                    // Check for termination entry.
                    if (journalEntry.getSequenceNumber() == TERMINATION_SEQ) {
                        // Reading finished.
                        return true;
                    }
                    journalEntry.writeDelimitedTo(zipStream);
                    entryCount.incrementAndGet();
                }
                pendingEntries.clear();
            }
            return true;
        } catch (InterruptedException ie) {
            LOG.info("Backup writer task interrupted");
            // Continue interrupt chain.
            Thread.currentThread().interrupt();
            throw new RuntimeException("Thread interrupted while writing to backup stream.", ie);
        }
    }));
    // Wait until backup tasks are completed.
    safeWaitTasks(activeTasks, completionService);
    // Close timer and update entry count.
    mBackupTimeMs = System.currentTimeMillis() - startBackupTime;
    mBackupEntriesCount = entryCount.get();
    // finish() instead of close() since close would close os, which is owned by the caller.
    zipStream.finish();
    LOG.info("Created backup with {} entries", entryCount.get());
}
Also used : GzipCompressorOutputStream(org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream) CloseableIterator(alluxio.resource.CloseableIterator) ExecutorCompletionService(java.util.concurrent.ExecutorCompletionService) LinkedBlockingQueue(java.util.concurrent.LinkedBlockingQueue) JournalEntry(alluxio.proto.journal.Journal.JournalEntry) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Future(java.util.concurrent.Future) LinkedList(java.util.LinkedList) List(java.util.List) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashSet(java.util.HashSet)

Example 7 with JournalEntry

use of alluxio.proto.journal.Journal.JournalEntry in project alluxio by Alluxio.

the class DefaultBlockMaster method getJournalEntryIterator.

@Override
public CloseableIterator<JournalEntry> getJournalEntryIterator() {
    Iterator<Block> blockStoreIterator = mBlockStore.iterator();
    Iterator<JournalEntry> blockIterator = new Iterator<JournalEntry>() {

        @Override
        public boolean hasNext() {
            return blockStoreIterator.hasNext();
        }

        @Override
        public JournalEntry next() {
            if (!hasNext()) {
                throw new NoSuchElementException();
            }
            Block block = blockStoreIterator.next();
            BlockInfoEntry blockInfoEntry = BlockInfoEntry.newBuilder().setBlockId(block.getId()).setLength(block.getMeta().getLength()).build();
            return JournalEntry.newBuilder().setBlockInfo(blockInfoEntry).build();
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException("BlockMaster#Iterator#remove is not supported.");
        }
    };
    CloseableIterator<JournalEntry> closeableIterator = CloseableIterator.create(blockIterator, (whatever) -> {
        if (blockStoreIterator instanceof CloseableIterator) {
            final CloseableIterator<Block> c = (CloseableIterator<Block>) blockStoreIterator;
            c.close();
        } else {
        // no op
        }
    });
    return CloseableIterator.concat(CloseableIterator.noopCloseable(CommonUtils.singleElementIterator(getContainerIdJournalEntry())), closeableIterator);
}
Also used : CloseableIterator(alluxio.resource.CloseableIterator) CloseableIterator(alluxio.resource.CloseableIterator) Iterator(java.util.Iterator) Block(alluxio.master.metastore.BlockStore.Block) JournalEntry(alluxio.proto.journal.Journal.JournalEntry) NoSuchElementException(java.util.NoSuchElementException) BlockInfoEntry(alluxio.proto.journal.Block.BlockInfoEntry)

Example 8 with JournalEntry

use of alluxio.proto.journal.Journal.JournalEntry in project alluxio by Alluxio.

the class RaftJournalWriter method flush.

@Override
public void flush() throws IOException, JournalClosedException {
    if (mClosed) {
        throw new JournalClosedException("Cannot flush. Journal writer has been closed");
    }
    if (mJournalEntryBuilder != null) {
        long flushSN = mNextSequenceNumberToWrite.get() - 1;
        try {
            // It is ok to submit the same entries multiple times because we de-duplicate by sequence
            // number when applying them. This could happen if submit fails and we re-submit the same
            // entry on retry.
            JournalEntry entry = mJournalEntryBuilder.build();
            Message message = RaftJournalSystem.toRaftMessage(entry);
            mLastSubmittedSequenceNumber.set(flushSN);
            LOG.trace("Flushing entry {} ({})", entry, message);
            RaftClientReply reply = mClient.sendAsync(message, TimeDuration.valueOf(mWriteTimeoutMs, TimeUnit.MILLISECONDS)).get(mWriteTimeoutMs, TimeUnit.MILLISECONDS);
            mLastCommittedSequenceNumber.set(flushSN);
            if (reply.getException() != null) {
                throw reply.getException();
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new IOException(e);
        } catch (ExecutionException e) {
            throw new IOException(e.getCause());
        } catch (TimeoutException e) {
            throw new IOException(String.format("Timed out after waiting %s milliseconds for journal entries to be processed", mWriteTimeoutMs), e);
        }
        mJournalEntryBuilder = null;
    }
}
Also used : JournalClosedException(alluxio.exception.JournalClosedException) Message(org.apache.ratis.protocol.Message) RaftClientReply(org.apache.ratis.protocol.RaftClientReply) IOException(java.io.IOException) ExecutionException(java.util.concurrent.ExecutionException) JournalEntry(alluxio.proto.journal.Journal.JournalEntry) TimeoutException(java.util.concurrent.TimeoutException)

Example 9 with JournalEntry

use of alluxio.proto.journal.Journal.JournalEntry in project alluxio by Alluxio.

the class UfsJournalCheckpointThread method runInternal.

private void runInternal() {
    // Keeps reading journal entries. If none is found, sleep for sometime. Periodically write
    // checkpoints if some conditions are met. When a shutdown signal is received, wait until
    // no new journal entries.
    LOG.info("{}: Journal checkpoint thread started.", mMaster.getName());
    // Set to true if it has waited for a quiet period. Reset if a valid journal entry is read.
    boolean quietPeriodWaited = false;
    mCatchupState = CatchupState.IN_PROGRESS;
    while (true) {
        JournalEntry entry = null;
        try {
            switch(mJournalReader.advance()) {
                case CHECKPOINT:
                    LOG.debug("{}: Restoring from checkpoint", mMaster.getName());
                    mMaster.restoreFromCheckpoint(mJournalReader.getCheckpoint());
                    LOG.debug("{}: Finished restoring from checkpoint", mMaster.getName());
                    break;
                case LOG:
                    entry = mJournalReader.getEntry();
                    try {
                        if (!mMaster.processJournalEntry(entry)) {
                            JournalUtils.handleJournalReplayFailure(LOG, null, "%s: Unrecognized journal entry: %s", mMaster.getName(), entry);
                        } else {
                            JournalUtils.sinkAppend(mJournalSinks, entry);
                        }
                    } catch (Throwable t) {
                        JournalUtils.handleJournalReplayFailure(LOG, t, "%s: Failed to read or process journal entry %s.", mMaster.getName(), entry);
                    }
                    if (quietPeriodWaited) {
                        LOG.info("Quiet period interrupted by new journal entry");
                        quietPeriodWaited = false;
                    }
                    mLastAppliedSN = entry.getSequenceNumber();
                    break;
                default:
                    mCatchupState = CatchupState.DONE;
                    break;
            }
        } catch (IOException e) {
            LOG.error("{}: Failed to read or process a journal entry.", mMaster.getName(), e);
            try {
                mJournalReader.close();
            } catch (IOException ee) {
                LOG.warn("{}: Failed to close the journal reader with error {}.", mMaster.getName(), ee.toString());
            }
            long nextSequenceNumber = mJournalReader.getNextSequenceNumber();
            mJournalReader = new UfsJournalReader(mJournal, nextSequenceNumber, false);
            quietPeriodWaited = false;
            continue;
        }
        // Sleep for a while if no entry is found.
        if (entry == null) {
            // Only try to checkpoint when it can keep up.
            maybeCheckpoint();
            if (mShutdownInitiated) {
                if (quietPeriodWaited || !mWaitQuietPeriod) {
                    mCatchupState = CatchupState.DONE;
                    LOG.info("{}: Journal checkpoint thread has been shutdown. No new logs have been found " + "during the quiet period.", mMaster.getName());
                    if (mJournalReader != null) {
                        try {
                            mJournalReader.close();
                        } catch (IOException e) {
                            LOG.warn("{}: Failed to close the journal reader with error {}.", mMaster.getName(), e.toString());
                        }
                    }
                    return;
                }
                CommonUtils.sleepMs(LOG, mShutdownQuietWaitTimeMs);
                quietPeriodWaited = true;
            } else {
                CommonUtils.sleepMs(LOG, mJournalCheckpointSleepTimeMs);
            }
        }
        if (Thread.interrupted() && !mShutdownInitiated) {
            LOG.info("{}: Checkpoint thread interrupted, shutting down", mMaster.getName());
            return;
        }
    }
}
Also used : IOException(java.io.IOException) JournalEntry(alluxio.proto.journal.Journal.JournalEntry)

Example 10 with JournalEntry

use of alluxio.proto.journal.Journal.JournalEntry in project alluxio by Alluxio.

the class AsyncJournalWriter method flush.

/**
 * Flushes and waits until the specified counter is flushed to the journal. If the specified
 * counter is already flushed, this is essentially a no-op.
 *
 * @param targetCounter the counter to flush
 */
public void flush(final long targetCounter) throws IOException {
    if (targetCounter <= mFlushCounter.get()) {
        return;
    }
    // Using reentrant lock, since it seems to result in higher throughput than using 'synchronized'
    mFlushLock.lock();
    try {
        long startTime = System.nanoTime();
        long flushCounter = mFlushCounter.get();
        if (targetCounter <= flushCounter) {
            // The specified counter is already flushed, so just return.
            return;
        }
        long writeCounter = mWriteCounter.get();
        while (targetCounter > writeCounter) {
            for (; ; ) {
                // Get, but do not remove, the head entry.
                JournalEntry entry = mQueue.peek();
                if (entry == null) {
                    // No more entries in the queue. Break out of the infinite for-loop.
                    break;
                }
                mJournalWriter.write(entry);
                // Remove the head entry, after the entry was successfully written.
                mQueue.poll();
                writeCounter = mWriteCounter.incrementAndGet();
                if (writeCounter >= targetCounter) {
                    if ((System.nanoTime() - startTime) >= mFlushBatchTimeNs) {
                        // infinite for-loop.
                        break;
                    }
                }
            }
        }
        mJournalWriter.flush();
        mFlushCounter.set(writeCounter);
    } finally {
        mFlushLock.unlock();
    }
}
Also used : JournalEntry(alluxio.proto.journal.Journal.JournalEntry)

Aggregations

JournalEntry (alluxio.proto.journal.Journal.JournalEntry)34 IOException (java.io.IOException)11 AlluxioURI (alluxio.AlluxioURI)8 Test (org.junit.Test)8 FileSystem (alluxio.client.file.FileSystem)6 URIStatus (alluxio.client.file.URIStatus)6 AlluxioEntryApplier (org.smartdata.alluxio.metric.fetcher.AlluxioEntryApplier)6 FileInfo (org.smartdata.model.FileInfo)6 BackUpInfo (org.smartdata.model.BackUpInfo)5 FileDiff (org.smartdata.model.FileDiff)5 JournalClosedException (alluxio.exception.JournalClosedException)2 IOJournalClosedException (alluxio.exception.JournalClosedException.IOJournalClosedException)2 JournalContext (alluxio.master.journal.JournalContext)2 JournalEntryStreamReader (alluxio.master.journal.JournalEntryStreamReader)2 CloseableIterator (alluxio.resource.CloseableIterator)2 Timer (com.codahale.metrics.Timer)2 ByteArrayInputStream (java.io.ByteArrayInputStream)2 HashSet (java.util.HashSet)2 Iterator (java.util.Iterator)2 LinkedList (java.util.LinkedList)2