1 /* 2 * IAsyncFile.h 3 * 4 * This source file is part of the FoundationDB open source project 5 * 6 * Copyright 2013-2018 Apple Inc. and the FoundationDB project authors 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21 #ifndef FLOW_IASYNCFILE_H 22 #define FLOW_IASYNCFILE_H 23 #pragma once 24 25 #include <ctime> 26 #include "flow/flow.h" 27 28 // All outstanding operations must be cancelled before the destructor of IAsyncFile is called. 29 // The desirability of the above semantic is disputed. Some classes (AsyncFileBlobStore, 30 // AsyncFileCached) maintain references, while others (AsyncFileNonDurable) don't, and the comment 31 // is unapplicable to some others as well (AsyncFileKAIO). It's safest to assume that all operations 32 // must complete or cancel, but you should probably look at the file implementations you'll be using. 33 class IAsyncFile { 34 public: 35 virtual ~IAsyncFile(); 36 // Pass these to g_network->open to get an IAsyncFile 37 enum { 38 // Implementation relies on the low bits being the same as the SQLite flags (this is validated by a static_assert there) 39 OPEN_READONLY = 0x1, 40 OPEN_READWRITE = 0x2, 41 OPEN_CREATE = 0x4, 42 OPEN_EXCLUSIVE = 0x10, 43 44 // Further flag values are arbitrary bits 45 OPEN_UNBUFFERED = 0x10000, 46 OPEN_UNCACHED = 0x20000, 47 OPEN_LOCK = 0x40000, 48 OPEN_ATOMIC_WRITE_AND_CREATE = 0x80000, // A temporary file is opened, and on the first call to sync() it is atomically renamed to the given filename 49 OPEN_LARGE_PAGES = 0x100000, 50 OPEN_NO_AIO = 0x200000, // Don't use AsyncFileKAIO or similar implementations that rely on filesystem support for AIO 51 OPEN_CACHED_READ_ONLY = 0x400000 // AsyncFileCached opens files read/write even if you specify read only 52 }; 53 54 virtual void addref() = 0; 55 virtual void delref() = 0; 56 57 // For read() and write(), the data buffer must remain valid until the future is ready 58 virtual Future<int> read( void* data, int length, int64_t offset ) = 0; // Returns number of bytes actually read (from [0,length]) 59 virtual Future<Void> write( void const* data, int length, int64_t offset ) = 0; 60 // The zeroed data is not guaranteed to be durable after `zeroRange` returns. A call to sync() would be required. 61 // This operation holds a reference to the AsyncFile, and does not need to be cancelled before a reference is dropped. 62 virtual Future<Void> zeroRange( int64_t offset, int64_t length ); 63 virtual Future<Void> truncate( int64_t size ) = 0; 64 virtual Future<Void> sync() = 0; flush()65 virtual Future<Void> flush() { return Void(); } // Sends previous writes to the OS if they have been buffered in memory, but does not make them power safe 66 virtual Future<int64_t> size() = 0; 67 virtual std::string getFilename() = 0; 68 69 // Attempt to read the *length bytes at offset without copying. If successful, a pointer to the 70 // requested bytes is written to *data, and the number of bytes successfully read is 71 // written to *length. If unsuccessful, *data and *length are undefined. 72 // readZeroCopy may fail (returning io_error) at any time, even if the requested bytes are readable. 73 // For example, an implementation of IAsyncFile may not implement readZeroCopy or may implement it 74 // only in certain cases (e.g. when the requested range does not cross a page boundary). So callers 75 // should always retry a failed readZeroCopy as a read(). 76 // Once readZeroCopy succeeds, the returned bytes will be pinned in memory until releaseZeroCopy is 77 // called, so the caller must always ensure that a matching call to releaseZeroCopy takes place. 78 // Between readZeroCopy and releaseZeroCopy, it is illegal (undefined behavior) to concurrently write 79 // to an overlapping range of bytes, whether or not using the same IAsyncFile handle. readZeroCopy(void ** data,int * length,int64_t offset)80 virtual Future<Void> readZeroCopy( void** data, int* length, int64_t offset ) { return io_error(); } releaseZeroCopy(void * data,int length,int64_t offset)81 virtual void releaseZeroCopy( void* data, int length, int64_t offset ) {} 82 83 virtual int64_t debugFD() = 0; 84 }; 85 86 typedef void (*runCycleFuncPtr)(); 87 88 class IAsyncFileSystem { 89 public: 90 // Opens a file for asynchronous I/O 91 virtual Future< Reference<class IAsyncFile> > open( std::string filename, int64_t flags, int64_t mode ) = 0; 92 93 // Deletes the given file. If mustBeDurable, returns only when the file is guaranteed to be deleted even after a power failure. 94 virtual Future< Void > deleteFile( std::string filename, bool mustBeDurable ) = 0; 95 96 // Unlinks a file and then deletes it slowly by truncating the file repeatedly. 97 // If mustBeDurable, returns only when the file is guaranteed to be deleted even after a power failure. 98 virtual Future<Void> incrementalDeleteFile( std::string filename, bool mustBeDurable ); 99 100 // Returns the time of the last modification of the file. 101 virtual Future<std::time_t> lastWriteTime( std::string filename ) = 0; 102 filesystem()103 static IAsyncFileSystem* filesystem() { return filesystem(g_network); } runCycleFunc()104 static runCycleFuncPtr runCycleFunc() { return reinterpret_cast<runCycleFuncPtr>(reinterpret_cast<flowGlobalType>(g_network->global(INetwork::enRunCycleFunc))); } 105 filesystem(INetwork * networkPtr)106 static IAsyncFileSystem* filesystem(INetwork* networkPtr) { return static_cast<IAsyncFileSystem*>(networkPtr->global(INetwork::enFileSystem)); } 107 108 109 protected: IAsyncFileSystem()110 IAsyncFileSystem() {} ~IAsyncFileSystem()111 virtual ~IAsyncFileSystem() {} // Please don't try to delete through this interface! 112 }; 113 114 #endif 115