Line data Source code
1 : #pragma once 2 : 3 : #include <memory> 4 : #include <queue> 5 : #include <string> 6 : #include <thread> 7 : 8 : #include "envoy/extensions/common/async_files/v3/async_file_manager.pb.h" 9 : 10 : #include "source/extensions/common/async_files/async_file_handle.h" 11 : #include "source/extensions/common/async_files/async_file_manager.h" 12 : 13 : #include "absl/base/thread_annotations.h" 14 : #include "absl/status/statusor.h" 15 : 16 : namespace Envoy { 17 : namespace Extensions { 18 : namespace Common { 19 : namespace AsyncFiles { 20 : 21 : // An AsyncFileManager which performs file operations in a thread pool. 22 : // The operations are passed in through a queue, and performed in the order they are 23 : // received, except when operations are chained, in which case the thread that 24 : // performed the previous action in the chain immediately performs the newly chained 25 : // action. 26 : class AsyncFileManagerThreadPool : public AsyncFileManager, 27 : protected Logger::Loggable<Logger::Id::main> { 28 : public: 29 : explicit AsyncFileManagerThreadPool( 30 : const envoy::extensions::common::async_files::v3::AsyncFileManagerConfig& config, 31 : Api::OsSysCalls& posix); 32 : ~AsyncFileManagerThreadPool() ABSL_LOCKS_EXCLUDED(queue_mutex_) override; 33 : CancelFunction 34 : createAnonymousFile(absl::string_view path, 35 : std::function<void(absl::StatusOr<AsyncFileHandle>)> on_complete) override; 36 : CancelFunction 37 : openExistingFile(absl::string_view filename, Mode mode, 38 : std::function<void(absl::StatusOr<AsyncFileHandle>)> on_complete) override; 39 : CancelFunction stat(absl::string_view filename, 40 : std::function<void(absl::StatusOr<struct stat>)> on_complete) override; 41 : CancelFunction unlink(absl::string_view filename, 42 : std::function<void(absl::Status)> on_complete) override; 43 : std::string describe() const override; 44 0 : Api::OsSysCalls& posix() const { return posix_; } 45 : 46 : #ifdef O_TMPFILE 47 : // The first time we try to open an anonymous file, these values are used to capture whether 48 : // opening with O_TMPFILE works. If it does not, the first open is retried using 'mkstemp', 49 : // and all subsequent tries are redirected down that path. If it works, the first try is 50 : // used, and all subsequent tries use the same mechanism. 51 : // This is per-manager rather than static in part to facilitate testing, but also because 52 : // if there are multiple managers they may be operating on different file-systems with 53 : // different capabilities. 54 : std::once_flag once_flag_; 55 : bool supports_o_tmpfile_; 56 : #endif // O_TMPFILE 57 : 58 : private: 59 : std::function<void()> enqueue(std::shared_ptr<AsyncFileAction> action) 60 : ABSL_LOCKS_EXCLUDED(queue_mutex_) override; 61 : void worker() ABSL_LOCKS_EXCLUDED(queue_mutex_); 62 : void resolveActions(); 63 : 64 : absl::Mutex queue_mutex_; 65 : std::queue<std::shared_ptr<AsyncFileAction>> queue_ ABSL_GUARDED_BY(queue_mutex_); 66 : bool terminate_ ABSL_GUARDED_BY(queue_mutex_) = false; 67 : 68 : std::vector<std::thread> thread_pool_; 69 : Api::OsSysCalls& posix_; 70 : }; 71 : 72 : } // namespace AsyncFiles 73 : } // namespace Common 74 : } // namespace Extensions 75 : } // namespace Envoy