ConnectionFactory.h
Go to the documentation of this file.
1 #ifndef cetlib_sqlite_ConnectionFactory_h
2 #define cetlib_sqlite_ConnectionFactory_h
3 // vim: set sw=2 expandtab :
4 
5 // ====================================================================
6 // ConnectionFactory
7 //
8 // This factory is the only way in which a cet::sqlite::Connection
9 // object can be created.
10 //
11 // For each database filename, there is an associated mutex that is
12 // shared across Connections referring to the same filename. Whenever
13 // an insertion is being performed across multiple Connections, the
14 // shared mutex guarantees that the database is updated in a
15 // thread-safe manner.
16 //
17 // This facility is necessary because the locking mechanisms that
18 // SQLite relies on are deficient for NFS systems.
19 //
20 // The typical use case is:
21 //
22 // ConnectionFactory factory;
23 // auto c1 = factory.make(":memory:");
24 // auto c2 = factory.make<MyDBOpenPolicy>("a.db", openPolicyArgs...);
25 // auto c3 = factory.make(":memory:");
26 //
27 // In the above, c1 and c3 will refer to the same in-memory database.
28 // To enable thread-safe insertion of data into the DB, consider using
29 // the Ntuple facility.
30 // ====================================================================
31 
34 
35 #include <map>
36 #include <memory>
37 #include <mutex>
38 #include <string>
39 #include <utility>
40 
41 namespace cet::sqlite {
42 
44  public:
45  template <typename DatabaseOpenPolicy = detail::DefaultDatabaseOpenPolicy,
46  typename... PolicyArgs>
47  auto make_connection(std::string const& file_name, PolicyArgs&&...)
48  -> Connection*;
49 
50  private:
51  std::map<std::string, std::weak_ptr<std::recursive_mutex>> databaseLocks_;
52  std::recursive_mutex mutex_;
53  };
54 
55  template <typename DatabaseOpenPolicy, typename... PolicyArgs>
56  auto
58  PolicyArgs&&... policyArgs) -> Connection*
59  {
60  // Implementation a la Herb Sutter's favorite 10-liner
61  std::lock_guard sentry{mutex_};
62  // Note: Convert the weak_ptr to a shared_ptr using the member
63  // function lock(), this is not an operation on the mutex.
64  auto shared_ptr_to_mutex = databaseLocks_[filename].lock();
65  if (!shared_ptr_to_mutex) {
66  using namespace std::string_literals;
67  databaseLocks_[filename] = shared_ptr_to_mutex =
68  std::make_shared<std::recursive_mutex>();
69  }
70  auto ret = new Connection{
71  filename,
72  shared_ptr_to_mutex,
73  DatabaseOpenPolicy{std::forward<PolicyArgs>(policyArgs)...}};
74  return ret;
75  }
76 
77 } // namespace cet::sqlite
78 
79 #endif /* cetlib_sqlite_ConnectionFactory_h */
80 
81 // Local Variables:
82 // mode: c++
83 // End:
std::string string
Definition: nybbler.cc:12
auto make_connection(std::string const &file_name, PolicyArgs &&...) -> Connection *
QCString file_name
string filename
Definition: train.py:213
std::map< std::string, std::weak_ptr< std::recursive_mutex > > databaseLocks_