@@ -34,7 +34,12 @@ namespace rbac {
3434// Every time we create a new PrivilegeDatabase we bump the generation.
3535// The PrivilegeContext contains the generation number it was generated
3636// from so that we can easily detect if the PrivilegeContext is stale.
37- static std::atomic<uint32_t > generation{0 };
37+ // The current_generation contains the version number of the PrivilegeDatabase
38+ // currently in use, and create_generation is the counter being used
39+ // to work around race conditions where multiple threads is trying to
40+ // create and update the RBAC database (last one wins)
41+ static std::atomic<uint32_t > current_generation{0 };
42+ static std::atomic<uint32_t > create_generation{0 };
3843
3944// The read write lock needed when you want to build a context
4045cb::RWLock rwlock;
@@ -128,7 +133,7 @@ PrivilegeMask UserEntry::parsePrivileges(const cJSON* priv, bool buckets) {
128133}
129134
130135PrivilegeDatabase::PrivilegeDatabase (const cJSON* json)
131- : generation(cb::rbac::generation .operator ++()) {
136+ : generation(cb::rbac::create_generation .operator ++()) {
132137
133138 if (json != nullptr ) {
134139 for (auto it = json->child ; it != nullptr ; it = it->next ) {
@@ -172,7 +177,7 @@ std::pair<PrivilegeContext, bool> PrivilegeDatabase::createInitialContext(
172177}
173178
174179PrivilegeAccess PrivilegeContext::check (Privilege privilege) const {
175- if (generation != cb::rbac::generation ) {
180+ if (generation != cb::rbac::current_generation ) {
176181 return PrivilegeAccess::Stale;
177182 }
178183
@@ -275,6 +280,7 @@ void loadPrivilegeDatabase(const std::string& filename) {
275280 // Handle race conditions
276281 if (db->generation < database->generation ) {
277282 db.swap (database);
283+ current_generation = db->generation ;
278284 }
279285}
280286
0 commit comments