| [5284] | 1 | /// ----------------------------------------*- mode: C++; -*--
 | 
|---|
 | 2 | /// @file queuemanager.cpp
 | 
|---|
 | 3 | /// queuemanager which records queues and message source IDs
 | 
|---|
 | 4 | /// ----------------------------------------------------------
 | 
|---|
 | 5 | /// $Id: queuemanager.cpp 2774 2007-08-08 12:32:08Z bless $
 | 
|---|
 | 6 | /// $HeadURL: https://svn.ipv6.tm.uka.de/nsis/protlib/trunk/src/queuemanager.cpp $
 | 
|---|
 | 7 | // ===========================================================
 | 
|---|
 | 8 | //                      
 | 
|---|
 | 9 | // Copyright (C) 2005-2007, all rights reserved by
 | 
|---|
 | 10 | // - Institute of Telematics, Universitaet Karlsruhe (TH)
 | 
|---|
 | 11 | //
 | 
|---|
 | 12 | // More information and contact:
 | 
|---|
 | 13 | // https://projekte.tm.uka.de/trac/NSIS
 | 
|---|
 | 14 | //                      
 | 
|---|
 | 15 | // This program is free software; you can redistribute it and/or modify
 | 
|---|
 | 16 | // it under the terms of the GNU General Public License as published by
 | 
|---|
 | 17 | // the Free Software Foundation; version 2 of the License
 | 
|---|
 | 18 | //
 | 
|---|
 | 19 | // This program is distributed in the hope that it will be useful,
 | 
|---|
 | 20 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
 | 21 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
 | 22 | // GNU General Public License for more details.
 | 
|---|
 | 23 | //
 | 
|---|
 | 24 | // You should have received a copy of the GNU General Public License along
 | 
|---|
 | 25 | // with this program; if not, write to the Free Software Foundation, Inc.,
 | 
|---|
 | 26 | // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
|---|
 | 27 | //
 | 
|---|
 | 28 | // ===========================================================
 | 
|---|
 | 29 | /** @ingroup queuemanager
 | 
|---|
 | 30 |  *
 | 
|---|
 | 31 |  */
 | 
|---|
 | 32 | #include <stdexcept>
 | 
|---|
 | 33 | 
 | 
|---|
 | 34 | #include "queuemanager.h"
 | 
|---|
 | 35 | #include "logfile.h"
 | 
|---|
 | 36 | 
 | 
|---|
 | 37 | namespace protlib { 
 | 
|---|
 | 38 | 
 | 
|---|
 | 39 | /** @addtogroup queuemanager Queue Manager
 | 
|---|
 | 40 |  * \ingroup fastqueue
 | 
|---|
 | 41 |  * @{
 | 
|---|
 | 42 |  */
 | 
|---|
 | 43 | 
 | 
|---|
 | 44 | using namespace log;
 | 
|---|
 | 45 | 
 | 
|---|
 | 46 | /***** class QueueManagerError *****/
 | 
|---|
 | 47 | 
 | 
|---|
 | 48 | QueueManagerError::QueueManagerError(error_t e) : err(e) {}
 | 
|---|
 | 49 | 
 | 
|---|
 | 50 | const char* QueueManagerError::getstr() const { return errstr[err]; }
 | 
|---|
 | 51 | 
 | 
|---|
 | 52 | const char* const QueueManagerError::errstr[] = {
 | 
|---|
 | 53 |         "Unable to create QueueManager.",
 | 
|---|
 | 54 |         "Cannot register FastQueue. No memory or registered queue more than once."
 | 
|---|
 | 55 | }; // end errstr
 | 
|---|
 | 56 | 
 | 
|---|
 | 57 | /***** class QueueManager *****/
 | 
|---|
 | 58 | 
 | 
|---|
 | 59 | /** Return QueueManager singleton. */
 | 
|---|
 | 60 | QueueManager* QueueManager::instance() {
 | 
|---|
 | 61 |         if (!inst) {
 | 
|---|
 | 62 |                 // try to create singleton
 | 
|---|
 | 63 |                 inst = new(nothrow) QueueManager();
 | 
|---|
 | 64 |                 if (!inst) {
 | 
|---|
 | 65 |                   Log(INFO_LOG,LOG_NORMAL, "QueueManager" ,"Cannot created QueueManager singleton.");
 | 
|---|
 | 66 |                   throw QueueManagerError(QueueManagerError::ERROR_NO_QUEUE_MANAGER);
 | 
|---|
 | 67 |                 } else {
 | 
|---|
 | 68 |                   Log(DEBUG_LOG,LOG_NORMAL, "QueueManager", "Just created QueueManager singleton.");
 | 
|---|
 | 69 |                 } // end if not inst
 | 
|---|
 | 70 |         } // end if not inst
 | 
|---|
 | 71 |         return inst;
 | 
|---|
 | 72 | } // end QueueManager
 | 
|---|
 | 73 | 
 | 
|---|
 | 74 | /**
 | 
|---|
 | 75 |  * Delete the QueueManager singleton object.
 | 
|---|
 | 76 |  *
 | 
|---|
 | 77 |  * After a call to clear references to that object become invalid and must
 | 
|---|
 | 78 |  * be updated by a call to instance().
 | 
|---|
 | 79 |  */
 | 
|---|
 | 80 | void QueueManager::clear() {
 | 
|---|
 | 81 | 
 | 
|---|
 | 82 |         if (inst) {
 | 
|---|
 | 83 |                 QueueManager *tmp = inst;
 | 
|---|
 | 84 |                 inst = 0;
 | 
|---|
 | 85 |                 DLog("QueueManager", "Destroying QueueManager singleton ...");
 | 
|---|
 | 86 |                 delete tmp;
 | 
|---|
 | 87 |         }
 | 
|---|
 | 88 | 
 | 
|---|
 | 89 |         DLog("QueueManager", "The QueueManager singleton has been destroyed");
 | 
|---|
 | 90 | }
 | 
|---|
 | 91 | 
 | 
|---|
 | 92 | 
 | 
|---|
 | 93 | /**
 | 
|---|
 | 94 |  * Register a queue.
 | 
|---|
 | 95 |  *
 | 
|---|
 | 96 |  * This registers a FastQueue for the given message source ID with the
 | 
|---|
 | 97 |  * QueueManager.
 | 
|---|
 | 98 |  *
 | 
|---|
 | 99 |  * The registered queue (and all its entries) is deleted as soon as the
 | 
|---|
 | 100 |  * QueueManager is deleted. Because of this, a queue may only be registered
 | 
|---|
 | 101 |  * once.
 | 
|---|
 | 102 |  *
 | 
|---|
 | 103 |  * @param fq pointer to an already allocated fastqueue 
 | 
|---|
 | 104 |  * @param s  message source ID
 | 
|---|
 | 105 |  */
 | 
|---|
 | 106 | void QueueManager::register_queue(FastQueue* fq, message::qaddr_t s) {
 | 
|---|
 | 107 |   pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
 | 
|---|
 | 108 |   // expand array if necessary
 | 
|---|
 | 109 |   if (((uint32)s)>=queue_arr.capacity()) {
 | 
|---|
 | 110 |     Log(DEBUG_LOG,LOG_NORMAL, "QueueManager", "expanding queue array from " << s << " to " << s+5);
 | 
|---|
 | 111 |     // get more memory
 | 
|---|
 | 112 |     queue_arr.reserve(s+5);
 | 
|---|
 | 113 |     while (queue_arr.size()<queue_arr.capacity()) queue_arr.push_back(NULL);
 | 
|---|
 | 114 |   } // end get more memory
 | 
|---|
 | 115 |   
 | 
|---|
 | 116 |   if (queue_arr[s]) 
 | 
|---|
 | 117 |   {
 | 
|---|
 | 118 |     // queue already exists
 | 
|---|
 | 119 |     Log(ERROR_LOG,LOG_CRIT, "QueueManager", "A queue for " << s << " is already  registered");
 | 
|---|
 | 120 |     throw QueueManagerError(QueueManagerError::ERROR_REGISTER);
 | 
|---|
 | 121 |   } // end if queue exists
 | 
|---|
 | 122 |   else 
 | 
|---|
 | 123 |   {
 | 
|---|
 | 124 |     // register queue
 | 
|---|
 | 125 |     if (fq)
 | 
|---|
 | 126 |     {
 | 
|---|
 | 127 |       queue_arr[s] = fq;
 | 
|---|
 | 128 |     }
 | 
|---|
 | 129 |     else
 | 
|---|
 | 130 |     {
 | 
|---|
 | 131 |       Log(ERROR_LOG,LOG_CRIT, "QueueManager", "Cannot register queue for " << s);
 | 
|---|
 | 132 |       throw QueueManagerError(QueueManagerError::ERROR_REGISTER);
 | 
|---|
 | 133 |     }
 | 
|---|
 | 134 |   } // end else no queue exists
 | 
|---|
 | 135 |   pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
 | 
|---|
 | 136 | } // end register_queue
 | 
|---|
 | 137 | 
 | 
|---|
 | 138 | 
 | 
|---|
 | 139 | void 
 | 
|---|
 | 140 | QueueManager::unregister_queue(message::qaddr_t s) 
 | 
|---|
 | 141 | {
 | 
|---|
 | 142 |   pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
 | 
|---|
 | 143 |   try {
 | 
|---|
 | 144 |           queue_arr.at(s) = 0;
 | 
|---|
 | 145 |   }
 | 
|---|
 | 146 |   catch ( std::out_of_range ) {
 | 
|---|
 | 147 |         /*
 | 
|---|
 | 148 |          * Nothing to do, queue has probably already been unregistered,
 | 
|---|
 | 149 |          * probably by calling QueueManager::clear().
 | 
|---|
 | 150 |          */
 | 
|---|
 | 151 |   }
 | 
|---|
 | 152 |   pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
 | 
|---|
 | 153 | }
 | 
|---|
 | 154 | 
 | 
|---|
 | 155 | FastQueue* QueueManager::get_queue(message::qaddr_t s) const {
 | 
|---|
 | 156 |         FastQueue* fq = NULL;
 | 
|---|
 | 157 |         pthread_mutex_lock(&mutex); // install_cleanup_mutex_lock(&mutex);
 | 
|---|
 | 158 |         if (((uint32)s)<queue_arr.size()) {
 | 
|---|
 | 159 |                 fq = queue_arr[s];
 | 
|---|
 | 160 |         } else {
 | 
|---|
 | 161 |                 fq = NULL;
 | 
|---|
 | 162 |         } // end if
 | 
|---|
 | 163 |         pthread_mutex_unlock(&mutex); // uninstall_cleanup(1);
 | 
|---|
 | 164 |         return fq;
 | 
|---|
 | 165 | } // end get
 | 
|---|
 | 166 | 
 | 
|---|
 | 167 | QueueManager* QueueManager::inst = NULL;
 | 
|---|
 | 168 | 
 | 
|---|
 | 169 | /**
 | 
|---|
 | 170 |  * Constructor.
 | 
|---|
 | 171 |  */
 | 
|---|
 | 172 | QueueManager::QueueManager() : queue_arr(QueueManager::INITIAL_ARRAY_SIZE) {
 | 
|---|
 | 173 |         pthread_mutexattr_t mutex_attr;
 | 
|---|
 | 174 | 
 | 
|---|
 | 175 |         pthread_mutexattr_init(&mutex_attr);
 | 
|---|
 | 176 | 
 | 
|---|
 | 177 | #ifdef _DEBUG
 | 
|---|
 | 178 |         pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK);
 | 
|---|
 | 179 | #else
 | 
|---|
 | 180 |         pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_NORMAL);
 | 
|---|
 | 181 | #endif
 | 
|---|
 | 182 | 
 | 
|---|
 | 183 |         pthread_mutex_init(&mutex, &mutex_attr);
 | 
|---|
 | 184 | 
 | 
|---|
 | 185 |         pthread_mutexattr_destroy(&mutex_attr); // doesn't affect mutex
 | 
|---|
 | 186 | }
 | 
|---|
 | 187 | 
 | 
|---|
 | 188 | 
 | 
|---|
 | 189 | /**
 | 
|---|
 | 190 |  * Destructor.
 | 
|---|
 | 191 |  *
 | 
|---|
 | 192 |  * Delete this object and all FastQueue objects that are still registered.
 | 
|---|
 | 193 |  */
 | 
|---|
 | 194 | QueueManager::~QueueManager() {
 | 
|---|
 | 195 | 
 | 
|---|
 | 196 |         pthread_mutex_lock(&mutex);
 | 
|---|
 | 197 | 
 | 
|---|
 | 198 |         // count queues which are still registered
 | 
|---|
 | 199 |         for ( qm_array_it_t i = queue_arr.begin(); i != queue_arr.end(); i++) 
 | 
|---|
 | 200 |                 if ( *i != 0 )
 | 
|---|
 | 201 |                         WLog("QueueManager",
 | 
|---|
 | 202 |                                 "~QueueManager(): queue " << (*i)->get_name()
 | 
|---|
 | 203 |                                 << " has not been unregistered");
 | 
|---|
 | 204 | 
 | 
|---|
 | 205 |         pthread_mutex_unlock(&mutex);
 | 
|---|
 | 206 | 
 | 
|---|
 | 207 |         pthread_mutex_destroy(&mutex);
 | 
|---|
 | 208 | }
 | 
|---|
 | 209 | 
 | 
|---|
 | 210 | //@}
 | 
|---|
 | 211 | 
 | 
|---|
 | 212 | } // end namespace protlib
 | 
|---|