/** * Logs a fatal error and then exits the system. * * @param logger the logger to log to * @param format the error message format string * @param args args for the format string */ public static void fatalError(Logger logger, String format, Object... args) { fatalError(logger, null, format, args); }
private synchronized void applyToMaster(JournalEntry entry) { String masterName; try { masterName = JournalEntryAssociation.getMasterForEntry(entry); } catch (Throwable t) { ProcessUtils.fatalError(LOG, t, "Unrecognized journal entry: {}", entry); throw new IllegalStateException(); } try { JournalEntryStateMachine master = mJournals.get(masterName).getStateMachine(); LOG.trace("Applying entry to master {}: {} ", masterName, entry); master.processJournalEntry(entry); } catch (Throwable t) { ProcessUtils.fatalError(LOG, t, "Failed to apply journal entry to master {}. Entry: {}", masterName, entry); } }
@SuppressFBWarnings(value = "VO_VOLATILE_INCREMENT", justification = "All writes to mNextSequenceNumberToRead are synchronized") private synchronized void applySingleEntry(JournalEntry entry) { if (mClosed) { return; } long newSN = entry.getSequenceNumber(); if (newSN < mNextSequenceNumberToRead) { LOG.info("Ignoring duplicate journal entry with SN {} when next SN is {}", newSN, mNextSequenceNumberToRead); return; } if (newSN > mNextSequenceNumberToRead) { ProcessUtils.fatalError(LOG, "Unexpected journal entry. The next expected SN is {}, but" + " encountered an entry with SN {}. Full journal entry: {}", mNextSequenceNumberToRead, newSN, entry); } mNextSequenceNumberToRead++; if (!mIgnoreApplys) { applyToMaster(entry); } }
/** * Starts the Alluxio master. * * @param args command line arguments, should be empty */ public static void main(String[] args) { if (args.length != 0) { LOG.info("java -cp {} {}", RuntimeConstants.ALLUXIO_JAR, AlluxioMaster.class.getCanonicalName()); System.exit(-1); } CommonUtils.PROCESS_TYPE.set(CommonUtils.ProcessType.MASTER); MasterProcess process; try { process = AlluxioMasterProcess.Factory.create(); } catch (Throwable t) { ProcessUtils.fatalError(LOG, t, "Failed to create master process"); // fatalError will exit, so we shouldn't reach here. throw t; } // Register a shutdown hook for master, so that master closes the journal files when it // receives SIGTERM. ProcessUtils.stopProcessOnShutdown(process); ProcessUtils.run(process); }
/** * Adds an inode to the inode tree. * * @param context journal context supplier * @param inode an inode to add and create a journal entry for */ public void applyAndJournal(Supplier<JournalContext> context, MutableInode<?> inode) { try { applyInode(inode); context.get().append(inode.toJournalEntry()); } catch (Throwable t) { ProcessUtils.fatalError(LOG, t, "Failed to apply %s", inode); throw t; // fatalError will usually system.exit } }
private void losePrimacy() throws Exception { if (mServingThread != null) { stopServing(); } // Put the journal in secondary mode ASAP to avoid interfering with the new primary. This must // happen after stopServing because downgrading the journal system will reset master state, // which could cause NPEs for outstanding RPC threads. We need to first close all client // sockets in stopServing so that clients don't see NPEs. mJournalSystem.losePrimacy(); if (mServingThread != null) { mServingThread.join(mServingThreadTimeoutMs); if (mServingThread.isAlive()) { ProcessUtils.fatalError(LOG, "Failed to stop serving thread after %dms. Serving thread stack trace:%n%s", mServingThreadTimeoutMs, ThreadUtils.formatStackTrace(mServingThread)); } mServingThread = null; stopMasters(); LOG.info("Primary stopped"); } startMasters(false); LOG.info("Secondary started"); }
/** * Waits for the flush counter to be flushed to the journal. If the counter is * {@link #INVALID_FLUSH_COUNTER}, this is a noop. */ private void waitForJournalFlush() throws UnavailableException { if (mFlushCounter == INVALID_FLUSH_COUNTER) { // Check this before the precondition. return; } RetryPolicy retry = new TimeoutRetry(FLUSH_RETRY_TIMEOUT_MS, FLUSH_RETRY_INTERVAL_MS); while (retry.attempt()) { try { mAsyncJournalWriter.flush(mFlushCounter); return; } catch (IOException e) { LOG.warn("Journal flush failed. retrying...", e); } catch (JournalClosedException e) { throw new UnavailableException(String.format("Failed to complete request: %s", e.getMessage()), e); } catch (Throwable e) { ProcessUtils.fatalError(LOG, e, "Journal flush failed"); } } ProcessUtils.fatalError(LOG, "Journal flush failed after %d attempts", retry.getAttemptCount()); }
/** * Applies a journal entry commit to the state machine. * * This method is automatically discovered by the Copycat framework. * * @param commit the commit */ public void applyJournalEntryCommand(Commit<JournalEntryCommand> commit) { JournalEntry entry; try { entry = JournalEntry.parseFrom(commit.command().getSerializedJournalEntry()); } catch (Throwable t) { ProcessUtils.fatalError(LOG, t, "Encountered invalid journal entry in commit: {}.", commit); throw new IllegalStateException(); } applyEntry(entry); }
/** * Updates an inode directory's state. * * @param context journal context supplier * @param entry update inode directory entry */ public void applyAndJournal(Supplier<JournalContext> context, UpdateInodeDirectoryEntry entry) { try { apply(entry); context.get().append(JournalEntry.newBuilder().setUpdateInodeDirectory(entry).build()); } catch (Throwable t) { ProcessUtils.fatalError(LOG, t, "Failed to apply %s", entry); throw t; // fatalError will usually system.exit } }
/** * Apply AddSyncPoint entry and journal the entry. * @param context journal context * @param entry addSyncPoint entry */ public void applyAndJournal(Supplier<JournalContext> context, AddSyncPointEntry entry) { try { apply(entry); context.get().append(Journal.JournalEntry.newBuilder().setAddSyncPoint(entry).build()); } catch (Throwable t) { ProcessUtils.fatalError(LOG, t, "Failed to apply %s", entry); throw t; // fatalError will usually system.exit } }
/** * Updates an inode's state. This is used for state common to both files and directories. * * @param context journal context supplier * @param entry update inode entry */ public void applyAndJournal(Supplier<JournalContext> context, UpdateInodeEntry entry) { try { apply(entry); context.get().append(JournalEntry.newBuilder().setUpdateInode(entry).build()); } catch (Throwable t) { ProcessUtils.fatalError(LOG, t, "Failed to apply %s", entry); throw t; // fatalError will usually system.exit } }
/** * Apply removeSyncPoint entry and journal the entry. * @param context journal context * @param entry removeSyncPoint entry */ public void applyAndJournal(Supplier<JournalContext> context, RemoveSyncPointEntry entry) { try { apply(entry); context.get().append(Journal.JournalEntry.newBuilder().setRemoveSyncPoint(entry).build()); } catch (Throwable t) { ProcessUtils.fatalError(LOG, t, "Failed to apply %s", entry); throw t; // fatalError will usually system.exit } }
/** * Starts the Alluxio proxy. * * @param args command line arguments, should be empty */ public static void main(String[] args) { if (args.length != 0) { LOG.info("java -cp {} {}", RuntimeConstants.ALLUXIO_JAR, AlluxioProxy.class.getCanonicalName()); System.exit(-1); } if (!ConfigurationUtils.masterHostConfigured(ServerConfiguration.global())) { ProcessUtils.fatalError(LOG, "Cannot run alluxio proxy; master hostname is not " + "configured. Please modify %s to either set %s or configure zookeeper with " + "%s=true and %s=[comma-separated zookeeper master addresses]", Constants.SITE_PROPERTIES, PropertyKey.MASTER_HOSTNAME.toString(), PropertyKey.ZOOKEEPER_ENABLED.toString(), PropertyKey.ZOOKEEPER_ADDRESS.toString()); } CommonUtils.PROCESS_TYPE.set(CommonUtils.ProcessType.PROXY); ProxyProcess process = ProxyProcess.Factory.create(); ProcessUtils.run(process); }
/** * Renames an inode. * * @param context journal context supplier * @param entry rename entry */ public void applyAndJournal(Supplier<JournalContext> context, RenameEntry entry) { try { applyRename(entry); context.get().append(JournalEntry.newBuilder().setRename(entry).build()); } catch (Throwable t) { ProcessUtils.fatalError(LOG, t, "Failed to apply %s", entry); throw t; // fatalError will usually system.exit } }
/** * Updates an inode file's state. * * @param context journal context supplier * @param entry update inode file entry */ public void applyAndJournal(Supplier<JournalContext> context, UpdateInodeFileEntry entry) { try { apply(entry); context.get().append(JournalEntry.newBuilder().setUpdateInodeFile(entry).build()); } catch (Throwable t) { ProcessUtils.fatalError(LOG, t, "Failed to apply %s", entry); throw t; // fatalError will usually system.exit } }
/** * Sets an ACL for an inode. * * @param context journal context supplier * @param entry set acl entry */ public void applyAndJournal(Supplier<JournalContext> context, SetAclEntry entry) { try { apply(entry); context.get().append(JournalEntry.newBuilder().setSetAcl(entry).build()); } catch (Throwable t) { ProcessUtils.fatalError(LOG, t, "Failed to apply %s", entry); throw t; // fatalError will usually system.exit } }
/** * Allocates and returns the next block ID for the indicated inode. * * @param context journal context supplier * @param entry new block entry * @return the new block id */ public long applyAndJournal(Supplier<JournalContext> context, NewBlockEntry entry) { try { long id = apply(entry); context.get().append(JournalEntry.newBuilder().setNewBlock(entry).build()); return id; } catch (Throwable t) { ProcessUtils.fatalError(LOG, t, "Failed to apply %s", entry); throw t; // fatalError will usually system.exit } }
/** * Applies a journal entry commit to the state machine. * * This method is automatically discovered by the Copycat framework. * * @param commit the commit */ public synchronized void applyJournalEntryCommand(Commit<JournalEntryCommand> commit) { JournalEntry entry; try { entry = JournalEntry.parseFrom(commit.command().getSerializedJournalEntry()); } catch (Exception e) { ProcessUtils.fatalError(LOG, e, "Encountered invalid journal entry in commit: {}.", commit); System.exit(-1); throw new IllegalStateException(e); // We should never reach here. } try { applyEntry(entry); } finally { Preconditions.checkState(commit.index() > mLastAppliedCommitIndex); mLastAppliedCommitIndex = commit.index(); commit.close(); } }
@Override public synchronized void install(SnapshotReader snapshotReader) { if (mClosed) { return; } if (mIgnoreApplys) { LOG.warn("Unexpected request to install a snapshot on a read-only journal state machine"); return; } resetState(); JournalEntryStreamReader reader = new JournalEntryStreamReader(new SnapshotReaderStream(snapshotReader)); JournalEntry entry = null; while (snapshotReader.hasRemaining()) { try { entry = reader.readEntry(); } catch (IOException e) { ProcessUtils.fatalError(LOG, e, "Failed to install snapshot"); } applyToMaster(entry); } long snapshotSN = entry != null ? entry.getSequenceNumber() : -1; if (snapshotSN < mNextSequenceNumberToRead - 1) { LOG.warn("Installed snapshot for SN {} but next SN to read is {}", snapshotSN, mNextSequenceNumberToRead); } mNextSequenceNumberToRead = snapshotSN + 1; LOG.info("Successfully installed snapshot up to SN {}", snapshotSN); }
/** * Reads the next journal entry. * * @return the journal entry, null if no journal entry is found */ private Journal.JournalEntry readInternal() throws IOException { updateInputStream(); if (mInputStream == null) { return null; } JournalEntry entry = mInputStream.mReader.readEntry(); if (entry != null) { return entry; } // If this is the checkpoint file, we need to reset the sequence number to update the stream // because the sequence number in the checkpoint entries is not in the same space as the // sequence number in the edit logs. if (mInputStream.mFile.isCheckpoint()) { mNextSequenceNumber = mInputStream.mFile.getEnd(); return readInternal(); } else if (mInputStream.mFile.isIncompleteLog()) { // Incomplete logs may end early. return null; } else { Preconditions.checkState(mInputStream.mFile.isCompletedLog(), "Expected log to be either checkpoint, incomplete, or complete"); ProcessUtils.fatalError(LOG, "Journal entry %s was truncated", mNextSequenceNumber); return null; } }