1
#include "source/extensions/common/async_files/async_file_manager_factory.h"
2

            
3
#include <memory>
4
#include <string>
5

            
6
#include "source/common/api/os_sys_calls_impl.h"
7
#include "source/common/protobuf/utility.h"
8
#include "source/extensions/common/async_files/async_file_manager_thread_pool.h"
9

            
10
#include "absl/base/thread_annotations.h"
11
#include "absl/container/flat_hash_map.h"
12

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

            
18
namespace {
19
struct ManagerAndConfig {
20
  std::shared_ptr<AsyncFileManager> manager;
21
  const envoy::extensions::common::async_files::v3::AsyncFileManagerConfig config;
22
};
23
} // namespace
24

            
25
SINGLETON_MANAGER_REGISTRATION(async_file_manager_factory_singleton);
26

            
27
class AsyncFileManagerFactoryImpl : public AsyncFileManagerFactory {
28
public:
29
  static std::shared_ptr<AsyncFileManagerFactory> singleton(Singleton::Manager* singleton_manager);
30
  std::shared_ptr<AsyncFileManager> getAsyncFileManager(
31
      const envoy::extensions::common::async_files::v3::AsyncFileManagerConfig& config,
32
      Api::OsSysCalls* substitute_posix_file_operations = nullptr)
33
      ABSL_LOCKS_EXCLUDED(mu_) override;
34

            
35
private:
36
  absl::Mutex mu_;
37
  absl::flat_hash_map<std::string, ManagerAndConfig> managers_ ABSL_GUARDED_BY(mu_);
38
};
39

            
40
std::shared_ptr<AsyncFileManagerFactory>
41
236
AsyncFileManagerFactory::singleton(Singleton::Manager* singleton_manager) {
42
236
  return singleton_manager->getTyped<AsyncFileManagerFactory>(
43
236
      SINGLETON_MANAGER_REGISTERED_NAME(async_file_manager_factory_singleton),
44
236
      [] { return std::make_shared<AsyncFileManagerFactoryImpl>(); });
45
236
}
46

            
47
std::shared_ptr<AsyncFileManager> AsyncFileManagerFactoryImpl::getAsyncFileManager(
48
    const envoy::extensions::common::async_files::v3::AsyncFileManagerConfig& config,
49
184
    Api::OsSysCalls* substitute_posix_file_operations) {
50
184
  Api::OsSysCalls& posix = substitute_posix_file_operations == nullptr
51
184
                               ? Api::OsSysCallsSingleton::get()
52
184
                               : *substitute_posix_file_operations;
53
184
  absl::MutexLock lock(mu_);
54
184
  auto it = managers_.find(config.id());
55
184
  if (it == managers_.end()) {
56
177
    switch (config.manager_type_case()) {
57
176
    case envoy::extensions::common::async_files::v3::AsyncFileManagerConfig::kThreadPool:
58
176
      it = managers_
59
176
               .insert({config.id(),
60
176
                        ManagerAndConfig{
61
176
                            std::make_shared<AsyncFileManagerThreadPool>(config, posix), config}})
62
176
               .first;
63
176
      break;
64
1
    case envoy::extensions::common::async_files::v3::AsyncFileManagerConfig::MANAGER_TYPE_NOT_SET:
65
      // This is theoretically unreachable due to proto validation 'required', but it's possible
66
      // for code to have modified the proto post-validation.
67
1
      throw EnvoyException("unrecognized AsyncFileManagerConfig::ManagerType");
68
177
    };
69
175
  } else if (!Protobuf::util::MessageDifferencer::Equivalent(it->second.config, config)) {
70
3
    throw EnvoyException("AsyncFileManager mismatched config");
71
3
  }
72
179
  return it->second.manager;
73
184
}
74

            
75
} // namespace AsyncFiles
76
} // namespace Common
77
} // namespace Extensions
78
} // namespace Envoy