/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF 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. */ package org.apache.activemq.artemis.core.journal; import java.util.List; import java.util.Map; import org.apache.activemq.artemis.core.io.SequentialFileFactory; import org.apache.activemq.artemis.core.journal.impl.JournalFile; import org.apache.activemq.artemis.core.persistence.Persister; import org.apache.activemq.artemis.core.server.ActiveMQComponent; /** * Most methods on the journal provide a blocking version where you select the sync mode and a non * blocking mode where you pass a completion callback as a parameter. * <p> * Notice also that even on the callback methods it's possible to pass the sync mode. That will only * make sense on the NIO operations. */ public interface Journal extends ActiveMQComponent { enum JournalState { STOPPED, /** * The journal has some fields initialized and services running. But it is not fully * operational. See {@link JournalState#LOADED}. */ STARTED, /** * When a replicating server is still not synchronized with its live. So if the live stops, * the backup may not fail-over and will stop as well. */ SYNCING, /** * Journal is being used by a replicating server which is up-to-date with its live. That means * that if the live stops, the backup can fail-over. */ SYNCING_UP_TO_DATE, /** * The journal is fully operational. This is the state the journal should be when its server * is live. */ LOADED; } // Non transactional operations void appendAddRecord(long id, byte recordType, byte[] record, boolean sync) throws Exception; default void appendAddRecord(long id, byte recordType, EncodingSupport record, boolean sync) throws Exception { appendAddRecord(id, recordType, EncoderPersister.getInstance(), record, sync); } void appendAddRecord(long id, byte recordType, Persister persister, Object record, boolean sync) throws Exception; void appendAddRecord(long id, byte recordType, Persister persister, Object record, boolean sync, IOCompletion completionCallback) throws Exception; default void appendAddRecord(long id, byte recordType, EncodingSupport record, boolean sync, IOCompletion completionCallback) throws Exception { appendAddRecord(id, recordType, EncoderPersister.getInstance(), record, sync, completionCallback); } void appendUpdateRecord(long id, byte recordType, byte[] record, boolean sync) throws Exception; default void appendUpdateRecord(long id, byte recordType, EncodingSupport record, boolean sync) throws Exception { appendUpdateRecord(id, recordType, EncoderPersister.getInstance(), record, sync); } void appendUpdateRecord(long id, byte recordType, Persister persister, Object record, boolean sync) throws Exception; default void appendUpdateRecord(long id, byte recordType, EncodingSupport record, boolean sync, IOCompletion completionCallback) throws Exception { appendUpdateRecord(id, recordType, EncoderPersister.getInstance(), record, sync, completionCallback); } void appendUpdateRecord(final long id, final byte recordType, final Persister persister, final Object record, final boolean sync, final IOCompletion callback) throws Exception; void appendDeleteRecord(long id, boolean sync) throws Exception; void appendDeleteRecord(long id, boolean sync, IOCompletion completionCallback) throws Exception; // Transactional operations void appendAddRecordTransactional(long txID, long id, byte recordType, byte[] record) throws Exception; default void appendAddRecordTransactional(long txID, long id, byte recordType, EncodingSupport record) throws Exception { appendAddRecordTransactional(txID, id, recordType, EncoderPersister.getInstance(), record); } void appendAddRecordTransactional(final long txID, final long id, final byte recordType, final Persister persister, final Object record) throws Exception; void appendUpdateRecordTransactional(long txID, long id, byte recordType, byte[] record) throws Exception; default void appendUpdateRecordTransactional(long txID, long id, byte recordType, EncodingSupport record) throws Exception { appendUpdateRecordTransactional(txID, id, recordType, EncoderPersister.getInstance(), record); } void appendUpdateRecordTransactional(long txID, long id, byte recordType, Persister persister, Object record) throws Exception; void appendDeleteRecordTransactional(long txID, long id, byte[] record) throws Exception; void appendDeleteRecordTransactional(long txID, long id, EncodingSupport record) throws Exception; void appendDeleteRecordTransactional(long txID, long id) throws Exception; void appendCommitRecord(long txID, boolean sync) throws Exception; void appendCommitRecord(long txID, boolean sync, IOCompletion callback) throws Exception; /** * @param txID * @param sync * @param callback * @param lineUpContext if appendCommitRecord should call a storeLineUp. This is because the * caller may have already taken into account * @throws Exception */ void appendCommitRecord(long txID, boolean sync, IOCompletion callback, boolean lineUpContext) throws Exception; /** * <p>If the system crashed after a prepare was called, it should store information that is required to bring the transaction * back to a state it could be committed. </p> * * <p> transactionData allows you to store any other supporting user-data related to the transaction</p> * * @param txID * @param transactionData - extra user data for the prepare * @throws Exception */ void appendPrepareRecord(long txID, EncodingSupport transactionData, boolean sync) throws Exception; void appendPrepareRecord(long txID, EncodingSupport transactionData, boolean sync, IOCompletion callback) throws Exception; void appendPrepareRecord(long txID, byte[] transactionData, boolean sync) throws Exception; void appendRollbackRecord(long txID, boolean sync) throws Exception; void appendRollbackRecord(long txID, boolean sync, IOCompletion callback) throws Exception; // Load JournalLoadInformation load(LoaderCallback reloadManager) throws Exception; /** * Load internal data structures and not expose any data. This is only useful if you're using the * journal but not interested on the current data. Useful in situations where the journal is * being replicated, copied... etc. */ JournalLoadInformation loadInternalOnly() throws Exception; /** * Load internal data structures, and remain waiting for synchronization to complete. * * @param state the current state of the journal, this parameter ensures consistency. */ JournalLoadInformation loadSyncOnly(JournalState state) throws Exception; void lineUpContext(IOCompletion callback); JournalLoadInformation load(List<RecordInfo> committedRecords, List<PreparedTransactionInfo> preparedTransactions, TransactionFailureCallback transactionFailure) throws Exception; int getAlignment() throws Exception; int getNumberOfRecords(); int getUserVersion(); void runDirectJournalBlast() throws Exception; /** * Reserves journal file IDs, creates the necessary files for synchronization, and places * references to these (reserved for sync) files in the map. * <p> * During the synchronization between a live server and backup, we reserve in the backup the * journal file IDs used in the live server. This call also makes sure the files are created * empty without any kind of headers added. * * @param fileIds IDs to reserve for synchronization * @return map to be filled with id and journal file pairs for <b>synchronization</b>. * @throws Exception */ Map<Long, JournalFile> createFilesForBackupSync(long[] fileIds) throws Exception; /** * Write lock the Journal and write lock the compacting process. Necessary only during * replication for backup synchronization. */ void synchronizationLock(); /** * Unlock the Journal and the compacting process. * * @see Journal#synchronizationLock() */ void synchronizationUnlock(); /** * Force the usage of a new {@link JournalFile}. * * @throws Exception */ void forceMoveNextFile() throws Exception; /** * Returns the {@link JournalFile}s in use. * * @return array with all {@link JournalFile}s in use */ JournalFile[] getDataFiles(); SequentialFileFactory getFileFactory(); int getFileSize(); /** * This method will start compact using the compactorExecutor and block up to timeout seconds * * @param timeout the timeout in seconds or block forever if {@code <= 0} * @throws Exception */ void scheduleCompactAndBlock(int timeout) throws Exception; /** * Stops any operation that may delete or modify old (stale) data. * <p> * Meant to be used during synchronization of data between a live server and its replicating * (remote) backup. Old files must not be compacted or deleted during synchronization. */ void replicationSyncPreserveOldFiles(); /** * Restarts file reclaim and compacting on the journal. * <p> * Meant to be used to revert the effect of {@link #replicationSyncPreserveOldFiles()}. it should * only be called once the synchronization of the backup and live servers is completed. */ void replicationSyncFinished(); /** * It will make sure there are no more pending operations on the Executors. * */ void flush() throws Exception; }