📄 osptransids.c
字号:
void /* returns nothing */OSPPTransIdPurge( OSPTTRANSID *ospvSentinel, OSPTPROVIDER *ospvProvider){ OSPTTRANSID *ptransid = OSPC_OSNULL; unsigned long now = 0;#ifdef TN_TRANSDBG char buf[20];#endif /* Get the current time. Anything older will be deleted. */ now = OSPPTransIdSecNow(); for ( ptransid = ospvSentinel->ospmTransactionIdOlderPtr; (ptransid != ospvSentinel) && (ptransid->ospmTransactionIdExpires < now); ptransid = ospvSentinel->ospmTransactionIdNewerPtr) { /* this one's expired, remove it from the list */ ptransid->ospmTransactionIdOlderPtr->ospmTransactionIdNewerPtr = ptransid->ospmTransactionIdNewerPtr; ptransid->ospmTransactionIdNewerPtr->ospmTransactionIdOlderPtr = ptransid->ospmTransactionIdOlderPtr;#ifdef TN_TRANSDBG OSPM_MEMSET(&buf, 0, sizeof(buf)); sprintf(buf, "%u", ptransid->ospmTransactionId); fprintf(stderr, "\n ****del TID: %s, @=0x%p\n", buf, ptransid);#endif /* and then delete it completely */ OSPPTransIdRemove(ptransid, ospvProvider); }}/*-----------------------------------------------------------------------*//* OSPPTransIdRemove - remove a transaction ID from the ordered tree */void /* no return value */OSPPTransIdRemove( OSPTTRANSID *ospvTransId, /* transaction ID to remove */ OSPTPROVIDER *ospvProvider /* osp provider object */){ OSPTTRANSID *splice = OSPC_OSNULL; /* node to be spliced */ OSPTTRANSID *child = OSPC_OSNULL; /* child of spliced node */ int errorcode = OSPC_ERR_NO_ERROR; OSPTTRANSID** root = OSPC_OSNULL; /* tree's root */ /* * Yep, the worst part of any binary tree stuff -- removing * a single node from the tree. (Why is this routine always * left as an exercise to the reader in algorithm and data * structures text books?) The approach is pretty standard, * though. Three cases: * * 1) Node has no children! Piece of cake, just update its * parent to point to null. * * 2) Node has only a single child. Not too much harder, just * "splice" the current node out of the tree. (I.e. update * its parent to point to the node's only child.) * * 3) Node has two children. This one's the hard one. We "splice" * out the node's successor and replace the current node * with its successor. See details below. */ /* figure out which node to splice out */ if ((ospvTransId->ospmTransactionIdLessPtr == 0) || (ospvTransId->ospmTransactionIdMorePtr == 0)) { /* * If the node has no more than one child, then it is * itself the one to remove from the tree. This actually * takes care of cases 1 and 2 above, since we'll be * sure to "splice" correctly even the node has no * children. */ splice = ospvTransId; } else { /* * Okay, the node we want to delete has two children. That * means we can't simply splice it out, because we'd have * to leave one of those poor children orphaned. What we * want to do is find the "successor" of the node to * delete. The successor is the next greatest node after * the current one (the smallest transaction ID greater * that the current node's.) In a tree structure, the * successor is the left-most node (the "tidLessPtr" path) * in the right (the "tidMorePtr" path) subtree. */ splice = ospvTransId->ospmTransactionIdMorePtr; while (splice->ospmTransactionIdLessPtr) { splice = splice->ospmTransactionIdLessPtr; } } /* * Now we've found the node to splice out. Next figure out which * of that node's children is going to get "promoted". */ if (splice->ospmTransactionIdLessPtr) { child = splice->ospmTransactionIdLessPtr; } else { /* * This handles case 1 in the introduction. If the node * had no children, the pChild will end up being null. */ child = splice->ospmTransactionIdMorePtr; } /* * Okay, we've identified the child to promote, change it's * parent to the spliced node's parent. */ if (child) { if(!(*(child->ospmTransactionIdParent) == splice->ospmTransactionIdLessPtr) || !(*(child->ospmTransactionIdParent) == splice->ospmTransactionIdMorePtr) ) { errorcode = OSPC_ERR_TRANSID; } if(errorcode == OSPC_ERR_NO_ERROR) { child->ospmTransactionIdParent = splice->ospmTransactionIdParent; } } /* * Last part of the splice: update the parent to point to the * new child. */ if(errorcode == OSPC_ERR_NO_ERROR) { *(splice->ospmTransactionIdParent) = child; /* * Final cleanup, if the node we spliced out wasn't the actual * node to delete, then we need to replace the deleted node's * contents with the spliced node's. */ if (splice != ospvTransId) { /* good place for some checks */ if(!(splice->ospmTransactionIdOlderPtr->ospmTransactionIdNewerPtr == splice) || !(splice->ospmTransactionIdNewerPtr->ospmTransactionIdOlderPtr == splice)) { errorcode = OSPC_ERR_TRANSID; } if(errorcode == OSPC_ERR_NO_ERROR) { /* first extract the spliced node from the linked list */ splice->ospmTransactionIdOlderPtr->ospmTransactionIdNewerPtr = ospvTransId; splice->ospmTransactionIdNewerPtr->ospmTransactionIdOlderPtr = ospvTransId; /* now insert the existing node into the linked list */ ospvTransId->ospmTransactionIdOlderPtr = splice->ospmTransactionIdOlderPtr; ospvTransId->ospmTransactionIdNewerPtr = splice->ospmTransactionIdNewerPtr; /* finally, update the existing node's actual data */ ospvTransId->ospmTransactionId = splice->ospmTransactionId; ospvTransId->ospmTransactionIdExpires = splice->ospmTransactionIdExpires; } } } if(splice != OSPC_OSNULL) { /* wbr: double check to see if splice is root, if so, update the root: */ root = OSPPProviderGetTransIdRoot( ospvProvider ); if (*root == splice) /* about to prune off the root */ { *root = child;#ifdef TN_TRANSDBG fprintf( stderr, "\n ********** updating new root to point to 0x%p\n", *root);#endif } /* release the memory */ OSPPTransIdDelete(splice); }}/*-----------------------------------------------------------------------*//* OSPPTransIdSecNow - current time in seconds since midnight 1Jan1970 */unsigned long /* returns current time in seconds */OSPPTransIdSecNow(){ time_t now; time(&now); return(now);}/*-----------------------------------------------------------------------*//* OSPPTransIdTimeAdd - add transaction in time-ordered linked list */void /* no return value */OSPPTransIdTimeAdd( OSPTTRANSID *ospvTransId, /* transaction ID to add */ OSPTPROVIDER *ospvProvider){ OSPTTRANSID *curr = OSPC_OSNULL; /* current position on list */ OSPTTRANSID *sentinel = OSPPProviderGetTransIdSentinel(ospvProvider); int errorcode = OSPC_ERR_NO_ERROR; /* * We put this transaction on the list in sorted order. To * do that, we start with the newest transaction and move * to older ones until we find where the current transaction * needs to go. */ if(sentinel != OSPC_OSNULL) { for (curr = sentinel->ospmTransactionIdOlderPtr; ((curr != sentinel) && (curr->ospmTransactionIdExpires > ospvTransId->ospmTransactionIdExpires)); ) { /* * The loop iteration could be moved into the for statement, * but we wanted to go ahead and use the for loop to check * pointer consistency using the assert statements below. * If the asserts were the only thing inside the braces, then * some compilers might complain when a non-assert (e.g. * production version) is built. To be on the safe side, * then, we've moved the iteration statement inside the * body of the for statement. */ curr = curr->ospmTransactionIdOlderPtr; /* now do the checks we were just talking about */ if(!(curr->ospmTransactionIdOlderPtr->ospmTransactionIdNewerPtr == curr) && !(curr->ospmTransactionIdOlderPtr->ospmTransactionIdOlderPtr == curr)) { errorcode = OSPC_ERR_TRANSID; break; } } if(errorcode == OSPC_ERR_NO_ERROR) { /* Now just plop the new transaction in the list */ ospvTransId->ospmTransactionIdOlderPtr = curr; ospvTransId->ospmTransactionIdNewerPtr = curr->ospmTransactionIdNewerPtr; curr->ospmTransactionIdNewerPtr->ospmTransactionIdOlderPtr = ospvTransId; curr->ospmTransactionIdNewerPtr = ospvTransId; } }}/*------------------------------------------- * OSPPTransIDTreeDelete - delete the whole tree */voidOSPPTransIDTreeDelete( OSPTPROVIDER *ospvProvider){ OSPTTRANSID *ptransid = OSPC_OSNULL; OSPTTRANSID *sentinel = OSPPProviderGetTransIdSentinel(ospvProvider); /* LOCK GLOBAL DATA NOW */ OSPPProviderLockTransIdMutex(ospvProvider); if(sentinel != OSPC_OSNULL) { for ( ptransid = sentinel->ospmTransactionIdOlderPtr; (ptransid != sentinel); ptransid = sentinel->ospmTransactionIdOlderPtr) { /* remove it from the list */ ptransid->ospmTransactionIdOlderPtr->ospmTransactionIdNewerPtr = ptransid->ospmTransactionIdNewerPtr; ptransid->ospmTransactionIdNewerPtr->ospmTransactionIdOlderPtr = ptransid->ospmTransactionIdOlderPtr; /* and then delete it completely */ OSPPTransIdRemove(ptransid, ospvProvider); } } /* RELEASE LOCK ON GLOBAL DATA NOW */ OSPPProviderUnLockTransIdMutex(ospvProvider); return;}/*-----------------------------------------------------------------------*//* tnTransById - list transactions in order of ID */#ifdef TN_TRANSDBGvoid /* no return value */tnTransById( OSPTPROVIDER *ospvProvider){ /* LOCK MUTEX ON GLOBAL DATA NOW */ OSPPProviderLockTransIdMutex(ospvProvider); /* * Since this function is really only for debug purposes, we * can be inefficient and use a recursive algorithm. */ tnPrintTree(*(OSPPProviderGetTransIdRoot(ospvProvider))); /* RELEASE MUTEX ON GLOBAL DATA NOW */ OSPPProviderUnLockTransIdMutex(ospvProvider);}#endif/*-----------------------------------------------------------------------*//* tnPrintTree - print the contents of a tree of transactions */#ifdef TN_TRANSDBGvoidtnPrintTree( OSPTTRANSID *pTrans){ char buf[30]; if (pTrans) { /* use the opportunity to check consistency */ assert( (pTrans->ospmTransactionIdLessPtr == 0) || (pTrans->ospmTransactionIdLessPtr->ospmTransactionIdParent == &(pTrans->ospmTransactionIdLessPtr)) ); assert( (pTrans->ospmTransactionIdMorePtr == 0) || (pTrans->ospmTransactionIdMorePtr->ospmTransactionIdParent == &(pTrans->ospmTransactionIdMorePtr)) ); tnPrintTree(pTrans->ospmTransactionIdLessPtr);/* #ifdef _DEBUG */ OSPM_MEMSET(&buf, 0, sizeof(buf)); sprintf(buf, "%u", pTrans->ospmTransactionId); fprintf(stderr, "\n** TID:%s, @=0x%p\n", buf, pTrans);/* #endif */ tnPrintTree(pTrans->ospmTransactionIdMorePtr); }}#endif/*-----------------------------------------------------------------------*//* tnTransByTime - list transactions in order of expiration time */#ifdef TN_TRANSDBGvoid /* no return value */tnTransByTime( OSPTPROVIDER *ospvProvider){ OSPTTRANSID *pTrans; char buf[30]; /* LOCK MUTEX ON GLOBAL DATA NOW */ OSPPProviderLockTransIdMutex(ospvProvider); for (pTrans=(OSPPProviderGetTransIdSentinel(ospvProvider))->ospmTransactionIdNewerPtr; pTrans != OSPPProviderGetTransIdSentinel(ospvProvider); pTrans = pTrans->ospmTransactionIdNewerPtr) { assert(pTrans->ospmTransactionIdNewerPtr->ospmTransactionIdOlderPtr == pTrans); assert(pTrans->ospmTransactionIdOlderPtr->ospmTransactionIdNewerPtr == pTrans);#ifdef _DEBUG OSPM_MEMSET(&buf, 0, sizeof(buf)); sprintf(buf, "%d", pTrans->ospmTransactionId); fprintf(stderr, "\nAt %s transaction %s expires.", ctime( &(pTrans->ospmTransactionIdExpires)), buf); /*afxDump << "\nAt " <<pTrans->tidExpires << ", transaction " << buf << "expires.";*/#endif } /* RELEASE SEMAPHORE ON GLOBAL DATA NOW */ OSPPProviderUnLockTransIdMutex(ospvProvider);}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -