CAChainTable.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "../StdAfx.h"
00033 #ifndef ONLY_LOCAL_PROXY
00034 #include "CAChainTable.hpp"
00035 #include "typedefsb.hpp"
00036 #include "../CAUtil.hpp"
00037
00038
00039 CAChainTable::CAChainTable(void) {
00040 m_pChainTable = new (t_chaintableEntry*[0x10000]);
00041 for (UINT32 i = 0; i < 0x10000; i++) {
00042 m_pChainTable[i] = NULL;
00043 }
00044 m_pMutex = new CAMutex();
00045 m_chaintableSize = 0;
00046 m_pChaintableIterator = NULL;
00047 #ifdef DELAY_CHANNELS
00048 m_initialBucketSize = DELAY_CHANNEL_TRAFFIC;
00049 m_delayBucketGrow = DELAY_BUCKET_GROW;
00050 m_delayBucketGrowInterval = DELAY_BUCKET_GROW_INTERVALL;
00051 m_pDelayBucketMutex = new CAMutex();
00052 m_pDelayBuckets = new SINT32[MAX_POLLFD];
00053 for (UINT32 i = 0; i < MAX_POLLFD; i++) {
00054 m_pDelayBuckets[i] = -1;
00055 }
00056
00057 m_delayBucketsLoopRun = true;
00058 m_pDelayBucketsLoop = new CAThread((UINT8*)"CAChainTable: delay-buckets refill thread");
00059 m_pDelayBucketsLoop->setMainLoop(lml_chaintableDelayBucketsLoop);
00060 m_pDelayBucketsLoop->start(this);
00061 #endif
00062 }
00063
00064 CAChainTable::~CAChainTable(void) {
00065
00066 getFirstEntry();
00067 while (m_pChaintableIterator != NULL) {
00068
00069 m_pChaintableIterator->removeEntry = true;
00070
00071
00072
00073 getNextEntry();
00074 }
00075 #ifdef DELAY_CHANNELS
00076 m_delayBucketsLoopRun = false;
00077
00078 m_pDelayBucketsLoop->join();
00079 delete m_pDelayBucketsLoop;
00080 m_pDelayBucketsLoop = NULL;
00081 delete m_pDelayBucketMutex;
00082 m_pDelayBucketMutex = NULL;
00083 delete []m_pDelayBuckets;
00084 m_pDelayBuckets = NULL;
00085 #endif
00086 delete m_pMutex;
00087 m_pMutex = NULL;
00088 delete []m_pChainTable;
00089 m_pChainTable = NULL;
00090 }
00091
00092 CAChain* CAChainTable::getEntry(UINT8* a_chainId) {
00093 m_pMutex->lock();
00094 CAChain* returnedChain = NULL;
00095 t_chaintableEntry* chaintableEntry = getEntryInternal(a_chainId);
00096 if (chaintableEntry != NULL) {
00097 returnedChain = chaintableEntry->chain;
00098 }
00099 m_pMutex->unlock();
00100 return returnedChain;
00101 }
00102
00103 void CAChainTable::deleteEntry(UINT8* a_chainId) {
00104 m_pMutex->lock();
00105 t_chaintableEntry* chaintableEntry = getEntryInternal(a_chainId);
00106 if (chaintableEntry != NULL) {
00107
00108
00109
00110 if (m_pChaintableIterator != NULL) {
00111 if (m_pChaintableIterator->currentEntry == chaintableEntry) {
00112
00113 m_pChaintableIterator->removeEntry = true;
00114 }
00115 else {
00116 removeEntryInternal(chaintableEntry);
00117 }
00118 }
00119 else {
00120 removeEntryInternal(chaintableEntry);
00121 }
00122 }
00123 m_pMutex->unlock();
00124 }
00125
00126 CAChain* CAChainTable::getFirstEntry() {
00127 CAChain* firstChain = NULL;
00128 m_pMutex->lock();
00129 if (m_pChaintableIterator == NULL) {
00130 m_pChaintableIterator = new t_chaintableIterator;
00131 }
00132 else {
00133
00134 if (m_pChaintableIterator->removeEntry) {
00135 removeEntryInternal(m_pChaintableIterator->currentEntry);
00136 }
00137 }
00138 m_pChaintableIterator->nextHashkey = 0;
00139 m_pChaintableIterator->removeEntry = false;
00140 m_pChaintableIterator->currentEntry = NULL;
00141 getNextEntryInternal(m_pChaintableIterator);
00142 if (m_pChaintableIterator->currentEntry == NULL) {
00143
00144 delete m_pChaintableIterator;
00145 m_pChaintableIterator = NULL;
00146 }
00147 else {
00148 firstChain = m_pChaintableIterator->currentEntry->chain;
00149 }
00150 m_pMutex->unlock();
00151 return firstChain;
00152 }
00153
00154 CAChain* CAChainTable::getNextEntry() {
00155 CAChain* nextChain = NULL;
00156 m_pMutex->lock();
00157 if (m_pChaintableIterator != NULL) {
00158 getNextEntryInternal(m_pChaintableIterator);
00159 if (m_pChaintableIterator->currentEntry == NULL) {
00160
00161 delete m_pChaintableIterator;
00162 m_pChaintableIterator = NULL;
00163 }
00164 else {
00165 nextChain = m_pChaintableIterator->currentEntry->chain;
00166 }
00167 }
00168 m_pMutex->unlock();
00169 return nextChain;
00170 }
00171
00172 CAChain* CAChainTable::createEntry() {
00173 m_pMutex->lock();
00174 if (m_chaintableSize >= MAX_POLLFD) {
00175
00176
00177
00178 m_pMutex->unlock();
00179 return NULL;
00180 }
00181
00182 UINT8* chainId = new UINT8[CHAIN_ID_LENGTH];
00183 do {
00184 if (getRandom(chainId, CHAIN_ID_LENGTH) != E_SUCCESS) {
00185 m_pMutex->unlock();
00186 delete []chainId;
00187 chainId = NULL;
00188 return NULL;
00189 }
00190 }
00191 while (getEntryInternal(chainId) != NULL);
00192 t_chaintableEntry* newEntry = new t_chaintableEntry;
00193 #ifndef DELAY_CHANNELS
00194 newEntry->chain = new CAChain(chainId);
00195 #else
00196
00197 m_pDelayBucketMutex->lock();
00198 UINT32 i = 0;
00199 bool bucketFound = false;
00200 while ((!bucketFound) && (i < MAX_POLLFD)) {
00201 if (m_pDelayBuckets[i] == -1) {
00202 bucketFound = true;
00203 }
00204 else {
00205 i++;
00206 }
00207 }
00208 if (!bucketFound) {
00209
00210
00211
00212 m_pDelayBucketMutex->unlock();
00213 delete newEntry;
00214 newEntry = NULL;
00215 delete []chainId;
00216 chainId = NULL;
00217 m_pMutex->unlock();
00218 return NULL;
00219 }
00220
00221 m_pDelayBuckets[i] = (SINT32)m_initialBucketSize;
00222 m_pDelayBucketMutex->unlock();
00223 newEntry->chain = new CAChain(chainId, m_pDelayBucketMutex, &(m_pDelayBuckets[i]));
00224 #endif
00225
00226 UINT16 hashKey = (((UINT16)(chainId[CHAIN_ID_LENGTH - 2])) << 8) | (UINT16)(chainId[CHAIN_ID_LENGTH - 1]);
00227
00228 newEntry->rightEntry = m_pChainTable[hashKey];
00229 newEntry->rightEntryPointerOfLeftEntry = &(m_pChainTable[hashKey]);
00230 m_pChainTable[hashKey] = newEntry;
00231 if (newEntry->rightEntry != NULL) {
00232 newEntry->rightEntry->rightEntryPointerOfLeftEntry = &(newEntry->rightEntry);
00233 }
00234 m_chaintableSize++;
00235 m_pMutex->unlock();
00236 return (newEntry->chain);
00237 }
00238
00239 UINT32 CAChainTable::getSize() {
00240 UINT32 chaintableSize;
00241 m_pMutex->lock();
00242 chaintableSize = m_chaintableSize;
00243 m_pMutex->unlock();
00244 return chaintableSize;
00245 }
00246
00247
00248 t_chaintableEntry* CAChainTable::getEntryInternal(UINT8* a_chainId) {
00249
00250
00251 UINT16 hashKey = (((UINT16)(a_chainId[CHAIN_ID_LENGTH - 2])) << 8) | (UINT16)(a_chainId[CHAIN_ID_LENGTH - 1]);
00252 bool entryFound = false;
00253 t_chaintableEntry* currentEntry = m_pChainTable[hashKey];
00254 while ((currentEntry != NULL) && !entryFound) {
00255
00256
00257
00258 bool entryVirtualRemoved = false;
00259 if (m_pChaintableIterator != NULL) {
00260 if ((m_pChaintableIterator->currentEntry == currentEntry) && (m_pChaintableIterator->removeEntry)) {
00261 entryVirtualRemoved = true;
00262
00263 currentEntry = currentEntry->rightEntry;
00264 }
00265 }
00266 if (!entryVirtualRemoved) {
00267
00268
00269
00270 if (memcmp(currentEntry->chain->getChainId(), a_chainId, CHAIN_ID_LENGTH - 2) == 0) {
00271
00272 entryFound = true;
00273 }
00274 else {
00275 currentEntry = currentEntry->rightEntry;
00276 }
00277 }
00278 }
00279 return currentEntry;
00280 }
00281
00282 void CAChainTable::removeEntryInternal(t_chaintableEntry* a_entry) {
00283
00284 *(a_entry->rightEntryPointerOfLeftEntry) = a_entry->rightEntry;
00285 if (a_entry->rightEntry != NULL) {
00286 a_entry->rightEntry->rightEntryPointerOfLeftEntry = a_entry->rightEntryPointerOfLeftEntry;
00287 }
00288
00289 delete a_entry->chain;
00290 a_entry->chain = NULL;
00291
00292 delete a_entry;
00293 a_entry = NULL;
00294 m_chaintableSize--;
00295 }
00296
00297 void CAChainTable::getNextEntryInternal(t_chaintableIterator* a_iterator) {
00298
00299 t_chaintableEntry* nextEntry;
00300 if (a_iterator->currentEntry == NULL) {
00301 nextEntry = NULL;
00302 }
00303 else {
00304 nextEntry = a_iterator->currentEntry->rightEntry;
00305
00306 if (a_iterator->removeEntry) {
00307 removeEntryInternal(a_iterator->currentEntry);
00308 a_iterator->removeEntry = false;
00309 }
00310 }
00311 if (nextEntry == NULL) {
00312
00313
00314
00315 do {
00316 a_iterator->currentEntry = m_pChainTable[a_iterator->nextHashkey];
00317 (a_iterator->nextHashkey)++;
00318 }
00319 while ((a_iterator->currentEntry == NULL) && (a_iterator->nextHashkey != 0));
00320 if (a_iterator->nextHashkey == 0) {
00321
00322 a_iterator->currentEntry = NULL;
00323 }
00324 }
00325 else {
00326
00327 a_iterator->currentEntry = nextEntry;
00328 }
00329 }
00330
00331 #ifdef DELAY_CHANNELS
00332 THREAD_RETURN lml_chaintableDelayBucketsLoop(void* a_param) {
00333
00334 CAChainTable* pChainTable = (CAChainTable*)a_param;
00335 while (pChainTable->m_delayBucketsLoopRun) {
00336 pChainTable->m_pDelayBucketMutex->lock();
00337 SINT32 bucketGrow = (SINT32)(pChainTable->m_delayBucketGrow);
00338 for (UINT32 i = 0; i < MAX_POLLFD; i++) {
00339 if ((pChainTable->m_pDelayBuckets[i]) != -1) {
00340
00341 pChainTable->m_pDelayBuckets[i] = min((pChainTable->m_pDelayBuckets[i]) + bucketGrow, MAX_DELAY_BUCKET_SIZE);
00342 }
00343 }
00344 pChainTable->m_pDelayBucketMutex->unlock();
00345
00346 msSleep((UINT16)(pChainTable->m_delayBucketGrowInterval));
00347 }
00348 THREAD_RETURN_SUCCESS;
00349 }
00350
00351 void CAChainTable::setDelayParameters(UINT32 a_initialBucketSize, UINT32 a_delayBucketGrow, UINT32 a_delayBucketGrowInterval) {
00352 CAMsg::printMsg(LOG_DEBUG, "CAChainTable - Set new traffic limit per channel: inital size: %u bucket grow: %u interval: %u\n", a_initialBucketSize, a_delayBucketGrow, a_delayBucketGrowInterval);
00353 m_pDelayBucketMutex->lock();
00354 m_initialBucketSize = a_initialBucketSize;
00355 m_delayBucketGrow = a_delayBucketGrow;
00356 m_delayBucketGrowInterval = a_delayBucketGrowInterval;
00357
00358 for (UINT32 i = 0; i < MAX_POLLFD; i++) {
00359 if (m_pDelayBuckets[i] != -1) {
00360
00361 m_pDelayBuckets[i] = a_initialBucketSize;
00362 }
00363 }
00364 m_pDelayBucketMutex->unlock();
00365 }
00366 #endif //DELAY_CHANNELS
00367 #endif//onlyLOCAL_PROXY