/* * LogSystemDiskQueueAdapter.h * * This source file is part of the FoundationDB open source project * * Copyright 2013-2018 Apple Inc. and the FoundationDB project authors * * Licensed 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. */ #ifndef FDBSERVER_LOGSYSTEMDISKQUEUEADAPTER_H #define FDBSERVER_LOGSYSTEMDISKQUEUEADAPTER_H #pragma once #include "fdbclient/FDBTypes.h" #include "fdbserver/IDiskQueue.h" struct PeekSpecialInfo { int8_t primaryLocality; int8_t secondaryLocality; Version knownCommittedVersion; bool operator == (const PeekSpecialInfo& r) const { return primaryLocality == r.primaryLocality && secondaryLocality == r.secondaryLocality && knownCommittedVersion == r.knownCommittedVersion; } PeekSpecialInfo(int8_t primaryLocality, int8_t secondaryLocality, Version knownCommittedVersion) : primaryLocality(primaryLocality), secondaryLocality(secondaryLocality), knownCommittedVersion(knownCommittedVersion) {} }; class LogSystemDiskQueueAdapter : public IDiskQueue { public: // This adapter is designed to let KeyValueStoreMemory use ILogSystem // as a backing store, so that the transaction subsystem can in // turn use KeyValueStoreMemory to track configuration information as of // the database version and recover it from the logging subsystem as necessary. // Because the transaction subsystem will need to control the actual pushing of // committed information to the ILogSystem, commit() in this interface doesn't directly // call ILogSystem::push(). Instead it makes a commit message available through // getCommitMessage(), and doesn't return until its acknowledge promise is set. // The caller is responsible for calling ILogSystem::push() and ILogSystem::pop() with the results. // It does, however, peek the specified tag directly at recovery time. LogSystemDiskQueueAdapter( Reference logSystem, Tag tag, Reference> peekLocality, bool recover=true ) : logSystem(logSystem), tag(tag), peekLocality(peekLocality), enableRecovery(recover), recoveryLoc(1), recoveryQueueLoc(1), poppedUpTo(0), nextCommit(1), recoveryQueueDataSize(0), peekTypeSwitches(0) { if (enableRecovery) { localityChanged = peekLocality ? peekLocality->onChange() : Never(); cursor = logSystem->peekSpecial( UID(), 1, tag, peekLocality ? peekLocality->get().primaryLocality : tagLocalityInvalid, peekLocality ? peekLocality->get().knownCommittedVersion : invalidVersion ); } } struct CommitMessage { Standalone>> messages; // push this into the logSystem with `tag` Version popTo; // pop this from the logSystem with `tag` Promise acknowledge; // then send Void to this, so commit() can return }; // Set the version of the next push or commit (or a lower version) // If lower, locations returned by the IDiskQueue interface will be conservative, so things that could be popped might not be void setNextVersion( Version next ) { nextCommit = next; } // Return the next commit message resulting from a call to commit(). Future getCommitMessage(); // IClosable interface virtual Future getError(); virtual Future onClosed(); virtual void dispose(); virtual void close(); // IDiskQueue interface virtual Future initializeRecovery(location recoverAt) { return false; } virtual Future> readNext( int bytes ); virtual IDiskQueue::location getNextReadLocation(); virtual IDiskQueue::location getNextCommitLocation() { ASSERT(false); throw internal_error(); } virtual IDiskQueue::location getNextPushLocation() { ASSERT(false); throw internal_error(); } virtual Future> read( location start, location end, CheckHashes ch ) { ASSERT(false); throw internal_error(); } virtual IDiskQueue::location push( StringRef contents ); virtual void pop( IDiskQueue::location upTo ); virtual Future commit(); virtual StorageBytes getStorageBytes() { ASSERT(false); throw internal_error(); } virtual int getCommitOverhead() { return 0; } //SOMEDAY: could this be more accurate? private: Reference> peekLocality; Future localityChanged; Reference cursor; int peekTypeSwitches; Tag tag; // Recovery state (used while readNext() is being called repeatedly) bool enableRecovery; Reference logSystem; Version recoveryLoc, recoveryQueueLoc; std::vector> recoveryQueue; int recoveryQueueDataSize; // State for next commit() call Standalone>> pushedData; // SOMEDAY: better representation? Version poppedUpTo; std::deque< Promise > commitMessages; Version nextCommit; friend class LogSystemDiskQueueAdapterImpl; }; LogSystemDiskQueueAdapter* openDiskQueueAdapter( Reference logSystem, Tag tag, Reference> peekLocality ); #endif