1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
|
/* -------------------------------------------------------------------------- */
/* Copyright 2002-2012, OpenNebula Project Leads (OpenNebula.org) */
/* */
/* 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>
#include "SqlDB.h"
#include "PoolObjectSQL.h"
#include "Log.h"
#include "Hook.h"
using namespace std;
/**
* PoolSQL class. Provides a base class to implement persistent generic pools.
* The PoolSQL provides a synchronization mechanism (mutex) to operate in
* multithreaded applications. Any modification or access function to the pool
* SHOULD block the mutex.
*/
class PoolSQL: public Callbackable, public Hookable
{
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
* @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_by_name True if the objects can be retrieved by name
*/
PoolSQL(SqlDB * _db, const char * _table, bool cache_by_name);
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(
PoolObjectSQL *objsql,
string& error_str);
/**
* Gets an object from the pool (if needed the object is loaded from the
* database).
* @param oid the object unique identifier
* @param lock locks the object if true
*
* @return a pointer to the object, 0 in case of failure
*/
PoolObjectSQL * get(int oid, bool lock);
/**
* Updates the cache name index. Must be called when the owner of an object
* is changed
*
* @param old_name Object's name before the change
* @param old_uid Object's owner ID before the change
* @param new_name Object's name after the change
* @param new_uid Object's owner ID after the change
*/
void update_cache_index(string& old_name,
int old_uid,
string& new_name,
int new_uid);
/**
* 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.
*
* @return 0 on success
*/
virtual int search(
vector<int>& oids,
const char * table,
const string& where);
/**
* Updates 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 update(
PoolObjectSQL * objsql)
{
int rc;
rc = objsql->update(db);
if ( rc == 0 )
{
do_hooks(objsql, Hook::UPDATE);
}
return rc;
};
/**
* Drops the object's data in the data base. The object mutex SHOULD be
* locked.
* @param objsql a pointer to the object
* @param error_msg Error reason, if any
* @return 0 on success, -1 DB error
*/
virtual int drop(PoolObjectSQL * objsql, string& error_msg)
{
int rc = objsql->drop(db);
if ( rc != 0 )
{
error_msg = "SQL DB error";
return -1;
}
return 0;
};
/**
* Removes all the elements from the pool
*/
void clean();
/**
* 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;
protected:
/**
* 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);
/**
* Pointer to the database.
*/
SqlDB * db;
/**
* 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 elem_name Name of the root xml pool name
* @param table Pool table name
* @param where filter for the objects, defaults to all
*
* @return 0 on success
*/
int dump(ostringstream& oss, const string& elem_name,
const char * table, const string& where);
/* ---------------------------------------------------------------------- */
/* Interface to access the lastOID assigned by the pool */
/* ---------------------------------------------------------------------- */
/**
* Gets the value of the last identifier assigned by the pool
* @return the lastOID of the pool
*/
int get_lastOID()
{
return lastOID;
};
/**
* Sets the lastOID of the pool and updates the control database
* @param _lastOID for the pool
*/
void set_update_lastOID(int _lastOID)
{
lastOID = _lastOID;
update_lastOID();
};
private:
pthread_mutex_t mutex;
/**
* Max size for the pool, to control the memory footprint of the pool. This
* 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;
/**
* Tablename for this pool
*/
string table;
/**
* The pool is implemented with a Map of SQL object pointers, using the
* OID as key.
*/
map<int,PoolObjectSQL *> pool;
/**
* Whether or not this pool uses the name_pool index
*/
bool uses_name_pool;
/**
* 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,PoolObjectSQL *> name_pool;
/**
* Factory method, must return an ObjectSQL pointer to an allocated pool
* specific object.
*/
virtual PoolObjectSQL * create() = 0;
/**
* OID queue to implement a FIFO-like replacement policy for the pool
* cache.
*/
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);
};
/**
* FIFO-like replacement policy function. Before removing an object (pop)
* 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.
*/
void replace();
/**
* 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
*/
virtual string key(const string& name, int uid)
{
ostringstream key;
key << name << ':' << uid;
return key.str();
};
/**
* Inserts the last oid into the pool_control table
*/
void update_lastOID();
/* ---------------------------------------------------------------------- */
/* ---------------------------------------------------------------------- */
/**
* 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);
/**
* Callback function to get output in XML format
* @param num the number of columns read from the DB
* @param names the column names
* @param vaues the column values
* @return 0 on success
*/
int dump_cb(void * _oss, int num, char **values, char **names);
};
#endif /*POOL_SQL_H_*/
|