2017-06-10 05:56:41 +08:00
|
|
|
/*
|
|
|
|
* IPager.h
|
|
|
|
*
|
|
|
|
* This source file is part of the FoundationDB open source project
|
|
|
|
*
|
|
|
|
* Copyright 2013-2018 Apple Inc. and the FoundationDB project authors
|
2020-04-25 05:12:40 +08:00
|
|
|
*
|
2017-06-10 05:56:41 +08:00
|
|
|
* 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
|
2020-04-25 05:12:40 +08:00
|
|
|
*
|
2017-06-10 05:56:41 +08:00
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
2020-04-25 05:12:40 +08:00
|
|
|
*
|
2017-06-10 05:56:41 +08:00
|
|
|
* 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_IPAGER_H
|
|
|
|
#define FDBSERVER_IPAGER_H
|
|
|
|
#pragma once
|
|
|
|
|
2018-10-20 01:30:13 +08:00
|
|
|
#include "fdbserver/IKeyValueStore.h"
|
2017-06-10 05:56:41 +08:00
|
|
|
|
|
|
|
#include "flow/flow.h"
|
|
|
|
#include "fdbclient/FDBTypes.h"
|
|
|
|
|
2019-02-21 18:46:30 +08:00
|
|
|
#ifndef VALGRIND
|
|
|
|
#define VALGRIND_MAKE_MEM_UNDEFINED(x, y)
|
|
|
|
#define VALGRIND_MAKE_MEM_DEFINED(x, y)
|
|
|
|
#endif
|
|
|
|
|
2019-11-11 16:46:05 +08:00
|
|
|
typedef uint32_t LogicalPageID;
|
|
|
|
typedef uint32_t PhysicalPageID;
|
|
|
|
#define invalidLogicalPageID std::numeric_limits<LogicalPageID>::max()
|
2017-06-10 05:56:41 +08:00
|
|
|
|
|
|
|
class IPage {
|
|
|
|
public:
|
2019-02-21 18:46:30 +08:00
|
|
|
IPage() : userData(nullptr) {}
|
|
|
|
|
2017-06-10 05:56:41 +08:00
|
|
|
virtual uint8_t const* begin() const = 0;
|
|
|
|
virtual uint8_t* mutate() = 0;
|
|
|
|
|
|
|
|
// Must return the same size for all pages created by the same pager instance
|
|
|
|
virtual int size() const = 0;
|
|
|
|
|
2020-04-25 05:12:40 +08:00
|
|
|
StringRef asStringRef() const { return StringRef(begin(), size()); }
|
2017-09-15 20:19:39 +08:00
|
|
|
|
2019-02-21 18:46:30 +08:00
|
|
|
virtual ~IPage() {
|
2020-04-25 05:12:40 +08:00
|
|
|
if (userData != nullptr && userDataDestructor != nullptr) {
|
2019-02-21 18:46:30 +08:00
|
|
|
userDataDestructor(userData);
|
|
|
|
}
|
|
|
|
}
|
2017-06-10 05:56:41 +08:00
|
|
|
|
2020-02-22 08:26:44 +08:00
|
|
|
virtual Reference<IPage> clone() const = 0;
|
|
|
|
|
2017-06-10 05:56:41 +08:00
|
|
|
virtual void addref() const = 0;
|
|
|
|
virtual void delref() const = 0;
|
2019-02-21 18:46:30 +08:00
|
|
|
|
2020-04-25 05:12:40 +08:00
|
|
|
mutable void* userData;
|
|
|
|
mutable void (*userDataDestructor)(void*);
|
2017-06-10 05:56:41 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
class IPagerSnapshot {
|
|
|
|
public:
|
2019-11-11 16:46:05 +08:00
|
|
|
virtual Future<Reference<const IPage>> getPhysicalPage(LogicalPageID pageID, bool cacheable, bool nohit) = 0;
|
2017-09-15 20:19:39 +08:00
|
|
|
virtual Version getVersion() const = 0;
|
2017-06-10 05:56:41 +08:00
|
|
|
|
2019-11-11 16:46:05 +08:00
|
|
|
virtual Key getMetaKey() const = 0;
|
2019-08-07 17:36:33 +08:00
|
|
|
|
2017-06-10 05:56:41 +08:00
|
|
|
virtual ~IPagerSnapshot() {}
|
|
|
|
|
|
|
|
virtual void addref() = 0;
|
|
|
|
virtual void delref() = 0;
|
|
|
|
};
|
|
|
|
|
2019-11-11 16:46:05 +08:00
|
|
|
// This API is probably customized to the behavior of DWALPager and probably needs some changes to be more generic.
|
2019-08-07 17:36:33 +08:00
|
|
|
class IPager2 : public IClosable {
|
|
|
|
public:
|
|
|
|
// Returns an IPage that can be passed to writePage. The data in the returned IPage might not be zeroed.
|
|
|
|
virtual Reference<IPage> newPageBuffer() = 0;
|
|
|
|
|
|
|
|
// Returns the usable size of pages returned by the pager (i.e. the size of the page that isn't pager overhead).
|
|
|
|
// For a given pager instance, separate calls to this function must return the same value.
|
|
|
|
// Only valid to call after recovery is complete.
|
2020-06-18 05:45:38 +08:00
|
|
|
virtual int getUsablePageSize() const = 0;
|
2019-08-07 17:36:33 +08:00
|
|
|
|
|
|
|
// Allocate a new page ID for a subsequent write. The page will be considered in-use after the next commit
|
|
|
|
// regardless of whether or not it was written to.
|
|
|
|
virtual Future<LogicalPageID> newPageID() = 0;
|
|
|
|
|
2019-09-28 06:08:05 +08:00
|
|
|
// Replace the contents of a page with new data across *all* versions.
|
|
|
|
// Existing holders of a page reference for pageID, read from any version,
|
|
|
|
// may see the effects of this write.
|
2019-08-07 17:36:33 +08:00
|
|
|
virtual void updatePage(LogicalPageID pageID, Reference<IPage> data) = 0;
|
|
|
|
|
2019-09-28 06:08:05 +08:00
|
|
|
// Try to atomically update the contents of a page as of version v in the next commit.
|
|
|
|
// If the pager is unable to do this at this time, it may choose to write the data to a new page ID
|
|
|
|
// instead and return the new page ID to the caller. Otherwise the original pageID argument will be returned.
|
|
|
|
// If a new page ID is returned, the old page ID will be freed as of version v
|
|
|
|
virtual Future<LogicalPageID> atomicUpdatePage(LogicalPageID pageID, Reference<IPage> data, Version v) = 0;
|
2019-08-07 17:36:33 +08:00
|
|
|
|
2019-09-28 06:08:05 +08:00
|
|
|
// Free pageID to be used again after the commit that moves oldestVersion past v
|
2019-09-05 15:47:57 +08:00
|
|
|
virtual void freePage(LogicalPageID pageID, Version v) = 0;
|
2019-08-07 17:36:33 +08:00
|
|
|
|
2020-08-09 15:24:52 +08:00
|
|
|
// If id is remapped, delete the original as of version v and return the page it was remapped to. The caller
|
|
|
|
// is then responsible for referencing and deleting the returned page ID.
|
|
|
|
virtual LogicalPageID detachRemappedPage(LogicalPageID id, Version v) = 0;
|
|
|
|
|
2019-09-28 06:08:05 +08:00
|
|
|
// Returns the latest data (regardless of version) for a page by LogicalPageID
|
2019-08-07 17:36:33 +08:00
|
|
|
// The data returned will be the later of
|
2019-09-28 06:08:05 +08:00
|
|
|
// - the most recent committed atomic
|
2019-08-07 17:36:33 +08:00
|
|
|
// - the most recent non-atomic write
|
2019-11-11 16:46:05 +08:00
|
|
|
// Cacheable indicates that the page should be added to the page cache (if applicable?) as a result of this read.
|
|
|
|
// NoHit indicates that the read should not be considered a cache hit, such as when preloading pages that are
|
|
|
|
// considered likely to be needed soon.
|
|
|
|
virtual Future<Reference<IPage>> readPage(LogicalPageID pageID, bool cacheable = true, bool noHit = false) = 0;
|
2019-08-07 17:36:33 +08:00
|
|
|
|
2019-09-02 14:03:31 +08:00
|
|
|
// Get a snapshot of the metakey and all pages as of the version v which must be >= getOldestVersion()
|
2019-09-28 06:08:05 +08:00
|
|
|
// Note that snapshots at any version may still see the results of updatePage() calls.
|
2019-09-02 14:03:31 +08:00
|
|
|
// The snapshot shall be usable until setOldVersion() is called with a version > v.
|
|
|
|
virtual Reference<IPagerSnapshot> getReadSnapshot(Version v) = 0;
|
2019-08-07 17:36:33 +08:00
|
|
|
|
|
|
|
// Atomically make durable all pending page writes, page frees, and update the metadata string.
|
|
|
|
virtual Future<Void> commit() = 0;
|
|
|
|
|
|
|
|
// Get the latest meta key set or committed
|
|
|
|
virtual Key getMetaKey() const = 0;
|
|
|
|
|
|
|
|
// Set the metakey which will be stored in the next commit
|
|
|
|
virtual void setMetaKey(KeyRef metaKey) = 0;
|
|
|
|
|
|
|
|
// Sets the next commit version
|
2019-10-15 18:10:50 +08:00
|
|
|
virtual void setCommitVersion(Version v) = 0;
|
2019-08-07 17:36:33 +08:00
|
|
|
|
2020-06-18 05:45:38 +08:00
|
|
|
virtual StorageBytes getStorageBytes() const = 0;
|
2019-08-07 17:36:33 +08:00
|
|
|
|
2020-08-09 15:24:52 +08:00
|
|
|
// Count of pages in use by the pager client (including retained old page versions)
|
2019-11-04 19:04:03 +08:00
|
|
|
virtual Future<int64_t> getUserPageCount() = 0;
|
2019-10-28 19:00:37 +08:00
|
|
|
|
2019-10-23 08:17:29 +08:00
|
|
|
// Future returned is ready when pager has been initialized from disk and is ready for reads and writes.
|
|
|
|
// It is invalid to call most other functions until init() is ready.
|
|
|
|
// TODO: Document further.
|
|
|
|
virtual Future<Void> init() = 0;
|
|
|
|
|
2019-08-07 17:36:33 +08:00
|
|
|
// Returns latest committed version
|
2020-06-18 05:45:38 +08:00
|
|
|
virtual Version getLatestVersion() const = 0;
|
2019-08-07 17:36:33 +08:00
|
|
|
|
2019-10-18 16:27:00 +08:00
|
|
|
// Returns the oldest readable version as of the most recent committed version
|
2020-06-18 05:45:38 +08:00
|
|
|
virtual Version getOldestVersion() const = 0;
|
2019-09-02 14:03:31 +08:00
|
|
|
|
2019-10-23 08:17:29 +08:00
|
|
|
// Sets the oldest readable version to be put into affect at the next commit.
|
2019-10-18 16:27:00 +08:00
|
|
|
// The pager can reuse pages that were freed at a version less than v.
|
2019-10-23 08:17:29 +08:00
|
|
|
// If any snapshots are in use at a version less than v, the pager can either forcefully
|
|
|
|
// invalidate them or keep their versions around until the snapshots are no longer in use.
|
2019-10-18 16:27:00 +08:00
|
|
|
virtual void setOldestVersion(Version v) = 0;
|
|
|
|
|
2019-08-07 17:36:33 +08:00
|
|
|
protected:
|
|
|
|
~IPager2() {} // Destruction should be done using close()/dispose() from the IClosable interface
|
|
|
|
};
|
|
|
|
|
2018-10-19 11:26:45 +08:00
|
|
|
#endif
|