2008-06-17 20:27:32 +04:00
/* -------------------------------------------------------------------------- */
2010-02-22 20:00:30 +03:00
/* Copyright 2002-2010, OpenNebula Project Leads (OpenNebula.org) */
2008-06-17 20:27:32 +04:00
/* */
/* Licensed under the Apache License, Version 2.0 (the "License"); you may */
/* not use this file except in compliance with the License. You may obtain */
/* a copy of the License at */
/* */
/* http://www.apache.org/licenses/LICENSE-2.0 */
/* */
/* Unless required by applicable law or agreed to in writing, software */
/* distributed under the License is distributed on an "AS IS" BASIS, */
/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. */
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
# ifndef POOL_SQL_H_
# define POOL_SQL_H_
# include <map>
# include <string>
# include <queue>
2010-04-03 18:54:54 +04:00
# include "SqlDB.h"
2008-06-17 20:27:32 +04:00
# include "PoolObjectSQL.h"
# include "Log.h"
2009-03-27 03:32:02 +03:00
# include "Hook.h"
2008-06-17 20:27:32 +04:00
using namespace std ;
/**
* PoolSQL class . Provides a base class to implement persistent generic pools .
2010-04-03 18:54:54 +04:00
* The PoolSQL provides a synchronization mechanism ( mutex ) to operate in
* multithreaded applications . Any modification or access function to the pool
2008-06-17 20:27:32 +04:00
* SHOULD block the mutex .
*/
2010-04-11 00:19:16 +04:00
class PoolSQL : public Callbackable , public Hookable
2008-06-17 20:27:32 +04:00
{
public :
/**
* Initializes the oid counter . This function sets lastOID to
* the last used Object identifier by querying the corresponding database
* table . This function SHOULD be called before any pool related function .
* @ param _db a pointer to the database
2010-04-03 18:54:54 +04:00
* @ param table the name of the table supporting the pool ( to set the oid
2008-06-17 20:27:32 +04:00
* counter ) . If null the OID counter is not updated .
2011-03-05 00:37:21 +03:00
* @ param with_uid the Pool objects have an owner id ( uid )
2008-06-17 20:27:32 +04:00
*/
2011-03-05 01:26:55 +03:00
PoolSQL ( SqlDB * _db , const char * table , bool with_uid ) ;
2008-06-17 20:27:32 +04:00
virtual ~ PoolSQL ( ) ;
/**
* Allocates a new object , writting it in the pool database . No memory is
* allocated for the object .
* @ param objsql an initialized ObjectSQL
* @ return the oid assigned to the object or - 1 in case of failure
*/
virtual int allocate (
2010-08-05 21:28:28 +04:00
PoolObjectSQL * objsql ,
string & error_str ) ;
2008-06-17 20:27:32 +04:00
/**
2010-04-03 18:54:54 +04:00
* Gets an object from the pool ( if needed the object is loaded from the
2008-06-17 20:27:32 +04:00
* database ) .
* @ param oid the object unique identifier
* @ param lock locks the object if true
2010-04-03 18:54:54 +04:00
*
2008-06-17 20:27:32 +04:00
* @ return a pointer to the object , 0 in case of failure
*/
2011-03-05 00:37:21 +03:00
PoolObjectSQL * get (
2008-06-17 20:27:32 +04:00
int oid ,
bool lock ) ;
2011-03-05 00:37:21 +03:00
/**
* Gets an object from the pool ( if needed the object is loaded from the
* database ) .
* @ param name of the object
* @ param uid id of owner
* @ param lock locks the object if true
*
* @ return a pointer to the object , 0 in case of failure
*/
PoolObjectSQL * get ( const string & name , int uid , bool lock )
{
int oid ;
oid = get_oid_by_name ( name , uid ) ;
if ( oid = = - 1 )
{
return 0 ;
}
return get ( oid , lock ) ;
}
2008-06-17 20:27:32 +04:00
/**
* Finds a set objects that satisfies a given condition
* @ param oids a vector with the oids of the objects .
* @ param the name of the DB table .
* @ param where condition in SQL format .
2010-04-03 18:54:54 +04:00
*
* @ return 0 on success
2008-06-17 20:27:32 +04:00
*/
virtual int search (
vector < int > & oids ,
const char * table ,
const string & where ) ;
2010-04-03 18:54:54 +04:00
2008-06-17 20:27:32 +04:00
/**
* Updates the object ' s data in the data base . The object mutex SHOULD be
* locked .
* @ param objsql a pointer to the object
2010-04-03 18:54:54 +04:00
*
2008-06-17 20:27:32 +04:00
* @ return 0 on success .
*/
virtual int update (
PoolObjectSQL * objsql )
{
2009-03-27 03:32:02 +03:00
int rc ;
2010-04-03 18:54:54 +04:00
2009-03-27 03:32:02 +03:00
rc = objsql - > update ( db ) ;
2010-04-03 18:54:54 +04:00
2009-03-27 03:32:02 +03:00
if ( rc = = 0 )
{
2009-03-30 01:34:37 +04:00
do_hooks ( objsql , Hook : : UPDATE ) ;
2009-03-27 03:32:02 +03:00
}
2010-04-03 18:54:54 +04:00
2009-03-27 03:32:02 +03:00
return rc ;
2008-06-17 20:27:32 +04:00
} ;
2010-04-03 18:54:54 +04:00
2010-04-06 01:34:09 +04:00
/**
* Drops the object ' s data in the data base . The object mutex SHOULD be
* locked .
* @ param objsql a pointer to the object
* @ return 0 on success .
*/
virtual int drop (
PoolObjectSQL * objsql )
{
2011-03-05 00:37:21 +03:00
erase ( objsql - > name , objsql - > uid ) ;
2010-04-06 01:34:09 +04:00
return objsql - > drop ( db ) ;
} ;
2008-06-17 20:27:32 +04:00
/**
* Removes all the elements from the pool
*/
void clean ( ) ;
2010-04-03 18:54:54 +04:00
2010-04-21 17:06:26 +04:00
/**
* Dumps the pool in XML format . A filter can be also added to the
* query
* @ param oss the output stream to dump the pool contents
* @ param where filter for the objects , defaults to all
*
* @ return 0 on success
*/
virtual int dump ( ostringstream & oss , const string & where ) = 0 ;
2008-06-17 20:27:32 +04:00
protected :
/**
* Pointer to the database .
*/
2010-04-03 18:54:54 +04:00
SqlDB * db ;
2008-06-17 20:27:32 +04:00
private :
pthread_mutex_t mutex ;
/**
2010-04-03 18:54:54 +04:00
* Max size for the pool , to control the memory footprint of the pool . This
2008-06-17 20:27:32 +04:00
* number MUST be greater than the max . number of objects that are
* accessed simultaneously .
*/
static const unsigned int MAX_POOL_SIZE ;
/**
* Last object ID assigned to an object . It must be initialized by the
* target pool .
*/
int lastOID ;
/**
2010-04-03 18:54:54 +04:00
* The pool is implemented with a Map of SQL object pointers , using the
2008-06-17 20:27:32 +04:00
* OID as key .
*/
2010-06-03 13:47:03 +04:00
map < int , PoolObjectSQL * > pool ;
2008-06-17 20:27:32 +04:00
2011-03-05 00:37:21 +03:00
/**
* This is a name index for the pool map . The key is the name of the object
* , that may be combained with the owner id .
*/
map < string , int > name_index ;
2008-06-17 20:27:32 +04:00
/**
* Factory method , must return an ObjectSQL pointer to an allocated pool
* specific object .
*/
virtual PoolObjectSQL * create ( ) = 0 ;
/**
2010-04-03 18:54:54 +04:00
* OID queue to implement a FIFO - like replacement policy for the pool
* cache .
2008-06-17 20:27:32 +04:00
*/
2010-06-03 13:47:03 +04:00
queue < int > oid_queue ;
/**
* Function to lock the pool
*/
void lock ( )
{
pthread_mutex_lock ( & mutex ) ;
} ;
/**
* Function to unlock the pool
*/
void unlock ( )
{
pthread_mutex_unlock ( & mutex ) ;
} ;
2008-06-17 20:27:32 +04:00
/**
* FIFO - like replacement policy function . Before removing an object ( pop )
2010-04-03 18:54:54 +04:00
* from the cache its lock is checked . The object is removed only if
* the associated mutex IS NOT blocked . Otherwise the oid is sent to the
* back of the queue .
2008-06-17 20:27:32 +04:00
*/
void replace ( ) ;
2010-04-03 18:54:54 +04:00
2011-03-05 00:37:21 +03:00
/* ------------------------------------------------------------------------ */
/* Functions to manage the name index */
/* ------------------------------------------------------------------------ */
/**
* Generate an index key for the object
* @ param name of the object
* @ param uid owner of the object , only used if needed
*
* @ return the key , a string
*/
string key ( const string & name , int uid )
{
ostringstream key ;
key < < name < < ' : ' < < uid ;
return key . str ( ) ;
} ;
/**
* Adds a new key - object_oid entry in the index
* @ param name of the object
* @ param oid of the object
* @ param uid owner of the object , only used if needed
*/
void insert ( const string & name , int oid , int uid )
{
name_index . insert ( make_pair ( key ( name , uid ) , oid ) ) ;
} ;
/**
* Deletes a key - object_oid entry in the index
* @ param name of the object
* @ param uid owner of the object , only used if needed
*/
void erase ( const string & name , int uid )
{
name_index . erase ( key ( name , uid ) ) ;
} ;
/**
* Looks for the oid of an object in the in memory index
* @ param name of the object
* @ param uid owner of the object , only used if needed
*
* @ returns oid or - 1 if the object was not found
*/
int get_oid_by_name ( const string & name , int uid )
{
map < string , int > : : iterator index ;
int oid = - 1 ;
index = name_index . find ( key ( name , uid ) ) ;
if ( index ! = name_index . end ( ) )
{
oid = static_cast < int > ( index - > second ) ;
}
return oid ;
} ;
/* ------------------------------------------------------------------------ */
/* ------------------------------------------------------------------------ */
2010-04-03 18:54:54 +04:00
/**
* Callback to set the lastOID ( PoolSQL : : PoolSQL )
*/
int init_cb ( void * nil , int num , char * * values , char * * names ) ;
/**
* Callback to store the IDs of pool objects ( PoolSQL : : search )
*/
int search_cb ( void * _oids , int num , char * * values , char * * names ) ;
2008-06-17 20:27:32 +04:00
} ;
2010-04-21 17:06:26 +04:00
# endif /*POOL_SQL_H_*/