diff --git a/include/DocumentPool.h b/include/DocumentPool.h index e6b0c2695b..883cdb97d9 100644 --- a/include/DocumentPool.h +++ b/include/DocumentPool.h @@ -27,7 +27,7 @@ class DocumentPool : public PoolSQL { public: - DocumentPool(SqlDB * db) : PoolSQL(db, Document::table, false){}; + DocumentPool(SqlDB * db) : PoolSQL(db, Document::table, true, false){}; ~DocumentPool(){}; diff --git a/include/GroupPool.h b/include/GroupPool.h index 363135c0a4..fafc0d669a 100644 --- a/include/GroupPool.h +++ b/include/GroupPool.h @@ -28,7 +28,8 @@ class GroupPool : public PoolSQL public: GroupPool(SqlDB * db, vector hook_mads, - const string& remotes_location); + const string& remotes_location, + bool cache); ~GroupPool(){}; diff --git a/include/PoolSQL.h b/include/PoolSQL.h index f1c1b86744..2dbe1a13f3 100644 --- a/include/PoolSQL.h +++ b/include/PoolSQL.h @@ -45,9 +45,10 @@ public: * @param _db a pointer to the database * @param _table the name of the table supporting the pool (to set the oid * counter). If null the OID counter is not updated. + * @param cache True to enable the cache * @param cache_by_name True if the objects can be retrieved by name */ - PoolSQL(SqlDB * _db, const char * _table, bool cache_by_name); + PoolSQL(SqlDB * _db, const char * _table, bool cache, bool cache_by_name); virtual ~PoolSQL(); @@ -368,6 +369,11 @@ private: */ map pool; + /** + * Whether or not this pool uses the cache + */ + bool cache; + /** * Whether or not this pool uses the name_pool index */ @@ -415,6 +421,23 @@ private: */ void replace(); + /** + * Cleans all the objects in the cache, except the ones locked. + * The object with the given oid will not be ignored if locked, the + * method will wait for it to be unlocked and ensure it is erased from + * the cache + * + * @param oid + */ + void flush_cache(int oid); + + /** + * Same as flush_cache(int), but with the object name-uid key + * + * @param name_key + */ + void flush_cache(const string& name_key); + /** * Generate an index key for the object * @param name of the object diff --git a/include/UserPool.h b/include/UserPool.h index 23051f7000..6b9b41bde5 100644 --- a/include/UserPool.h +++ b/include/UserPool.h @@ -42,7 +42,8 @@ public: UserPool(SqlDB * db, time_t __session_expiration_time, vector hook_mads, - const string& remotes_location); + const string& remotes_location, + bool cache); ~UserPool(){}; diff --git a/include/VMTemplatePool.h b/include/VMTemplatePool.h index 026dca5458..1f16d2c4fd 100644 --- a/include/VMTemplatePool.h +++ b/include/VMTemplatePool.h @@ -27,7 +27,7 @@ class VMTemplatePool : public PoolSQL { public: - VMTemplatePool(SqlDB * db) : PoolSQL(db, VMTemplate::table, true){}; + VMTemplatePool(SqlDB * db) : PoolSQL(db, VMTemplate::table, true, true){}; ~VMTemplatePool(){}; diff --git a/include/ZonePool.h b/include/ZonePool.h index c91c1c5c90..34e166f566 100644 --- a/include/ZonePool.h +++ b/include/ZonePool.h @@ -26,7 +26,8 @@ using namespace std; class ZonePool : public PoolSQL { public: - ZonePool(SqlDB * db); + ZonePool(SqlDB * db, + bool cache); ~ZonePool(){}; diff --git a/src/cluster/ClusterPool.cc b/src/cluster/ClusterPool.cc index d36dcc8c28..8284ac456e 100644 --- a/src/cluster/ClusterPool.cc +++ b/src/cluster/ClusterPool.cc @@ -33,7 +33,7 @@ const int ClusterPool::ALL_RESOURCES = 10; /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ -ClusterPool::ClusterPool(SqlDB * db):PoolSQL(db, Cluster::table, true) +ClusterPool::ClusterPool(SqlDB * db):PoolSQL(db, Cluster::table, true, true) { ostringstream oss; string error_str; diff --git a/src/datastore/DatastorePool.cc b/src/datastore/DatastorePool.cc index c3d358ae34..8cee553741 100644 --- a/src/datastore/DatastorePool.cc +++ b/src/datastore/DatastorePool.cc @@ -39,7 +39,7 @@ const int DatastorePool::FILE_DS_ID = 2; /* -------------------------------------------------------------------------- */ DatastorePool::DatastorePool(SqlDB * db): - PoolSQL(db, Datastore::table, true) + PoolSQL(db, Datastore::table, true, true) { ostringstream oss; string error_str; diff --git a/src/group/GroupPool.cc b/src/group/GroupPool.cc index e2bce9336c..bed4739aa2 100644 --- a/src/group/GroupPool.cc +++ b/src/group/GroupPool.cc @@ -39,8 +39,9 @@ const int GroupPool::USERS_ID = 1; GroupPool::GroupPool(SqlDB * db, vector hook_mads, - const string& remotes_location) - :PoolSQL(db, Group::table, true) + const string& remotes_location, + bool cache) + :PoolSQL(db, Group::table, cache, true) { ostringstream oss; string error_str; diff --git a/src/host/HostPool.cc b/src/host/HostPool.cc index 70bb2cd07a..6ed31d4f6c 100644 --- a/src/host/HostPool.cc +++ b/src/host/HostPool.cc @@ -41,7 +41,7 @@ HostPool::HostPool(SqlDB* db, const string& hook_location, const string& remotes_location, time_t expire_time) - : PoolSQL(db, Host::table, true) + : PoolSQL(db, Host::table, true, true) { _monitor_expiration = expire_time; diff --git a/src/image/ImagePool.cc b/src/image/ImagePool.cc index abb3dd9318..6974929157 100644 --- a/src/image/ImagePool.cc +++ b/src/image/ImagePool.cc @@ -41,7 +41,7 @@ ImagePool::ImagePool( const string& remotes_location, const vector& _inherit_image_attrs, const vector& _inherit_datastore_attrs) - :PoolSQL(db, Image::table, true) + :PoolSQL(db, Image::table, true, true) { // Init static defaults _default_type = __default_type; diff --git a/src/nebula/Nebula.cc b/src/nebula/Nebula.cc index 40551905f3..83f4b68e48 100644 --- a/src/nebula/Nebula.cc +++ b/src/nebula/Nebula.cc @@ -607,6 +607,8 @@ void Nebula::start(bool bootstrap_only) bool vm_submit_on_hold; + bool cache = !is_federation_slave(); + vector vm_hooks; vector host_hooks; vector vnet_hooks; @@ -623,7 +625,7 @@ void Nebula::start(bool bootstrap_only) clpool = new ClusterPool(db); docpool = new DocumentPool(db); - zonepool= new ZonePool(db); + zonepool= new ZonePool(db, cache); nebula_configuration->get("VM_HOOK", vm_hooks); nebula_configuration->get("HOST_HOOK", host_hooks); @@ -667,10 +669,10 @@ void Nebula::start(bool bootstrap_only) remotes_location, inherit_vnet_attrs); - gpool = new GroupPool(db, group_hooks, remotes_location); + gpool = new GroupPool(db, group_hooks, remotes_location, cache); nebula_configuration->get("SESSION_EXPIRATION_TIME", expiration_time); - upool = new UserPool(db, expiration_time, user_hooks, remotes_location); + upool = new UserPool(db, expiration_time, user_hooks, remotes_location, cache); nebula_configuration->get("DEFAULT_IMAGE_TYPE", default_image_type); nebula_configuration->get("DEFAULT_DEVICE_PREFIX", diff --git a/src/pool/PoolSQL.cc b/src/pool/PoolSQL.cc index b3c300525e..30aae011a5 100644 --- a/src/pool/PoolSQL.cc +++ b/src/pool/PoolSQL.cc @@ -51,8 +51,8 @@ int PoolSQL::init_cb(void *nil, int num, char **values, char **names) /* -------------------------------------------------------------------------- */ -PoolSQL::PoolSQL(SqlDB * _db, const char * _table, bool cache_by_name): - db(_db), lastOID(-1), table(_table), uses_name_pool(cache_by_name) +PoolSQL::PoolSQL(SqlDB * _db, const char * _table, bool _cache, bool cache_by_name): + db(_db), lastOID(-1), table(_table), cache(_cache), uses_name_pool(cache_by_name) { ostringstream oss; @@ -176,6 +176,11 @@ PoolObjectSQL * PoolSQL::get( lock(); + if (!cache) + { + flush_cache(oid); + } + index = pool.find(oid); if ( index != pool.end() ) @@ -252,11 +257,14 @@ PoolObjectSQL * PoolSQL::get( objectsql->lock(); } - oid_queue.push(objectsql->oid); - - if ( pool.size() > MAX_POOL_SIZE ) + if (cache) { - replace(); + oid_queue.push(objectsql->oid); + + if ( pool.size() > MAX_POOL_SIZE ) + { + replace(); + } } unlock(); @@ -274,16 +282,23 @@ PoolObjectSQL * PoolSQL::get(const string& name, int ouid, bool olock) PoolObjectSQL * objectsql; int rc; - - lock(); + string name_key; if ( uses_name_pool == false ) { - unlock(); return 0; } - index = name_pool.find(key(name,ouid)); + lock(); + + name_key = key(name,ouid); + + if (!cache) + { + flush_cache(name_key); + } + + index = name_pool.find(name_key); if ( index != name_pool.end() && index->second->isValid() == true ) { @@ -342,11 +357,14 @@ PoolObjectSQL * PoolSQL::get(const string& name, int ouid, bool olock) objectsql->lock(); } - oid_queue.push(objectsql->oid); - - if ( pool.size() > MAX_POOL_SIZE ) + if (cache) { - replace(); + oid_queue.push(objectsql->oid); + + if ( pool.size() > MAX_POOL_SIZE ) + { + replace(); + } } unlock(); @@ -446,6 +464,95 @@ void PoolSQL::replace() /* -------------------------------------------------------------------------- */ /* -------------------------------------------------------------------------- */ +void PoolSQL::flush_cache(int oid) +{ + int rc; + PoolObjectSQL * tmp_ptr; + + map::iterator it; + + for (it = pool.begin(); it != pool.end(); ) + { + // The object we are looking for in ::get(). Will wait until it is + // unlocked() + if (it->second->oid == oid) + { + it->second->lock(); + } + else + { + // Any other locked object is just ignored + rc = pthread_mutex_trylock(&(it->second->mutex)); + + if ( rc == EBUSY ) // In use by other thread + { + it++; + continue; + } + } + + tmp_ptr = it->second; + + // map::erase does not invalidate the iterator, except for the current + // one + pool.erase(it++); + + if ( uses_name_pool ) + { + string okey = key(tmp_ptr->name,tmp_ptr->uid); + name_pool.erase(okey); + } + + delete tmp_ptr; + } +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + +void PoolSQL::flush_cache(const string& name_key) +{ + int rc; + PoolObjectSQL * tmp_ptr; + + map::iterator it; + + for (it = name_pool.begin(); it != name_pool.end(); ) + { + string okey = key(it->second->name, it->second->uid); + + // The object we are looking for in ::get(). Will wait until it is + // unlocked() + if (name_key == okey) + { + it->second->lock(); + } + else + { + // Any other locked object is just ignored + rc = pthread_mutex_trylock(&(it->second->mutex)); + + if ( rc == EBUSY ) // In use by other thread + { + it++; + continue; + } + } + + tmp_ptr = it->second; + + // map::erase does not invalidate the iterator, except for the current + // one + name_pool.erase(it++); + pool.erase(tmp_ptr->oid); + + delete tmp_ptr; + } +} + +/* -------------------------------------------------------------------------- */ +/* -------------------------------------------------------------------------- */ + void PoolSQL::clean() { map::iterator it; diff --git a/src/um/UserPool.cc b/src/um/UserPool.cc index 90c0407b02..63e488b88f 100644 --- a/src/um/UserPool.cc +++ b/src/um/UserPool.cc @@ -55,8 +55,9 @@ string UserPool::oneadmin_name; UserPool::UserPool(SqlDB * db, time_t __session_expiration_time, vector hook_mads, - const string& remotes_location): - PoolSQL(db, User::table, true) + const string& remotes_location, + bool cache): + PoolSQL(db, User::table, cache, true) { int one_uid = -1; int server_uid = -1; diff --git a/src/vm/VirtualMachinePool.cc b/src/vm/VirtualMachinePool.cc index 361a27620f..70ac7514f1 100644 --- a/src/vm/VirtualMachinePool.cc +++ b/src/vm/VirtualMachinePool.cc @@ -38,7 +38,7 @@ VirtualMachinePool::VirtualMachinePool( vector& restricted_attrs, time_t expire_time, bool on_hold) - : PoolSQL(db, VirtualMachine::table, false) + : PoolSQL(db, VirtualMachine::table, true, false) { const VectorAttribute * vattr; diff --git a/src/vnm/VirtualNetworkPool.cc b/src/vnm/VirtualNetworkPool.cc index 9d53dd2d6d..8d2666386d 100644 --- a/src/vnm/VirtualNetworkPool.cc +++ b/src/vnm/VirtualNetworkPool.cc @@ -38,7 +38,7 @@ VirtualNetworkPool::VirtualNetworkPool( vector hook_mads, const string& remotes_location, const vector& _inherit_attrs): - PoolSQL(db, VirtualNetwork::table, true) + PoolSQL(db, VirtualNetwork::table, true, true) { istringstream iss; size_t pos = 0; diff --git a/src/zone/ZonePool.cc b/src/zone/ZonePool.cc index 5e971cf356..753fbebd62 100644 --- a/src/zone/ZonePool.cc +++ b/src/zone/ZonePool.cc @@ -20,8 +20,8 @@ /* -------------------------------------------------------------------------- */ -ZonePool::ZonePool(SqlDB * db) - :PoolSQL(db, Zone::table, true) +ZonePool::ZonePool(SqlDB * db, bool cache) + :PoolSQL(db, Zone::table, cache, true) { if (get_lastOID() == -1) //lastOID is set in PoolSQL::init_cb {