1
#pragma once
2

            
3
#include <memory>
4

            
5
#include "envoy/event/dispatcher.h"
6

            
7
#include "source/extensions/common/async_files/async_file_action.h"
8
#include "source/extensions/common/async_files/async_file_handle.h"
9

            
10
#include "absl/status/statusor.h"
11
#include "absl/strings/string_view.h"
12
#include "absl/types/optional.h"
13

            
14
namespace Envoy {
15
namespace Extensions {
16
namespace Common {
17
namespace AsyncFiles {
18

            
19
// An AsyncFileManager should be a singleton or singleton-like.
20
// Possible subclasses currently are:
21
//   * AsyncFileManagerThreadPool
22
class AsyncFileManager {
23
public:
24
279
  virtual ~AsyncFileManager() = default;
25

            
26
  // Action to create and open a temporary file.
27
  //
28
  // The path parameter is a path to a directory in which the anonymous file will be
29
  // created (commonly "/tmp", for example). Even though an anonymous file is not linked and
30
  // has no filename, the path can be important as it determines which physical hardware the file
31
  // is written to (i.e. if you were to link() the file later, linking it to a path on a different
32
  // device is an expensive operation; or you might prefer to write temporary files to a virtual
33
  // filesystem or to a mounted disposable SSD.)
34
  // on_complete receives an AsyncFileHandle on success, or an error on failure.
35
  //
36
  // Returns a cancellation function, which aborts the operation (and closes
37
  // the file if opened) unless the callback has already been called.
38
  virtual CancelFunction
39
  createAnonymousFile(Event::Dispatcher* dispatcher, absl::string_view path,
40
                      absl::AnyInvocable<void(absl::StatusOr<AsyncFileHandle>)> on_complete) PURE;
41

            
42
  // A mode for opening existing files.
43
  enum class Mode { ReadOnly, WriteOnly, ReadWrite };
44

            
45
  // Action to asynchronously open a named file that already exists.
46
  // on_complete receives an AsyncFileHandle on success, or an error on failure.
47
  //
48
  // Returns a cancellation function, which aborts the operation (and closes
49
  // the file if opened) unless the callback has already been called.
50
  virtual CancelFunction
51
  openExistingFile(Event::Dispatcher* dispatcher, absl::string_view filename, Mode mode,
52
                   absl::AnyInvocable<void(absl::StatusOr<AsyncFileHandle>)> on_complete) PURE;
53

            
54
  // Action to stat a file.
55
  // on_complete receives a stat structure on success, or an error on failure.
56
  //
57
  // Returns a cancellation function, which aborts the operation
58
  // unless the callback has already been called.
59
  virtual CancelFunction
60
  stat(Event::Dispatcher* dispatcher, absl::string_view filename,
61
       absl::AnyInvocable<void(absl::StatusOr<struct stat>)> on_complete) PURE;
62

            
63
  // Action to delete a named file.
64
  // on_complete receives OK on success, or an error on failure.
65
  //
66
  // Returns a cancellation function, which aborts the operation
67
  // unless it has already been performed.
68
  virtual CancelFunction unlink(Event::Dispatcher* dispatcher, absl::string_view filename,
69
                                absl::AnyInvocable<void(absl::Status)> on_complete) PURE;
70

            
71
  // Return a string description of the configuration of the manager.
72
  // (This is mostly to facilitate testing.)
73
  virtual std::string describe() const PURE;
74

            
75
  // To facilitate testing, blocks until all queued actions have been performed and
76
  // callbacks posted.
77
  // This does not guarantee that the callbacks have been executed, only that they
78
  // have been sent to the dispatcher.
79
  virtual void waitForIdle() PURE;
80

            
81
protected:
82
  class QueuedAction {
83
  public:
84
    QueuedAction(std::unique_ptr<AsyncFileAction> action, Event::Dispatcher* dispatcher)
85
4407
        : action_(std::move(action)), dispatcher_(dispatcher),
86
4407
          state_(std::make_shared<std::atomic<State>>(State::Queued)) {}
87
4264
    QueuedAction() = default;
88
    std::unique_ptr<AsyncFileAction> action_;
89
    Event::Dispatcher* dispatcher_ = nullptr;
90
    enum class State { Queued, Executing, InCallback, Done, Cancelled };
91
    std::shared_ptr<std::atomic<State>> state_;
92
  };
93

            
94
private:
95
  // Puts an action in the queue for execution.
96
  virtual CancelFunction enqueue(Event::Dispatcher* dispatcher,
97
                                 std::unique_ptr<AsyncFileAction> action) PURE;
98
  // Puts an action in the queue for its `onCancelledBeforeCallback` function to be
99
  // called.
100
  virtual void postCancelledActionForCleanup(std::unique_ptr<AsyncFileAction> action) PURE;
101

            
102
  friend class AsyncFileContextBase;
103
  friend class AsyncFileManagerTest;
104
};
105

            
106
} // namespace AsyncFiles
107
} // namespace Common
108
} // namespace Extensions
109
} // namespace Envoy