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