TAction* HashCreateXdbKeys(Transaction *t, const char *hash_name, const char *db_name) { size_t existvar = t->MakeVariable(); size_t keylistvar = t->MakeVariable(); size_t keyvar = t->MakeVariable(); TOperand *existarg = new TOperandVariable(t, existvar); TOperand *keylistarg = new TOperandVariable(t, keylistvar); TOperand *keyarg = new TOperandVariable(t, keyvar); TActionIterate *key_iter = new TActionIterate(t, keyvar, keylistarg); key_iter->PushAction(HashInsertKey(t, hash_name, keyarg)); TActionTest *nex_test = new TActionTest(t, existarg, false); nex_test->PushAction(HashClear(t, hash_name)); nex_test->PushAction(XdbAllKeys(t, db_name, keylistvar)); nex_test->PushAction(key_iter); TActionSequence *sequence = new TActionSequence(t); sequence->PushAction(HashExists(t, hash_name, existvar)); sequence->PushAction(nex_test); return sequence; }
// Add the node to the chain. First we must verify that the chain // is large enough for nArg; if not, grow it. Than add it at // the appropriate index. status_t ArpIndexedList::pAddNode(ArpIndexedNode *node) { long hash = HashForIndex(node->Index()); #if 0 // why did I write this? Isn't the POINT that if the hash is // too large, then the list grows? if (not HashExists(hash)) { delete node; return B_ERROR; } #endif if (hash >= count) { GrowToAtLeast(hash + ARP_CHAIN_INCREMENT); } if (chain[hash] == NULL) { chain[hash] = node; pAddNodeAtChainHead(node, hash); } else if (node->Index() < chain[hash]->Index()) { chain[hash]->AddNode(node); chain[hash] = node; } else { chain[hash]->AddNode(node); } // If the node is the new last node in the list then assign it // to the cached tailNode. // if ((tailNode == NULL) or (tailNode->Index() < node->Index())) // tailNode = node; AddedNode(node); return B_OK; }
status_t ArpIndexedList::NodeAfter(int32 index, ArpIndexedNode **answer, int32 findNode) { long hash = HashForIndex(index); if (! HashExists(hash)) return B_ERROR; ArpIndexedNode *nodeAfter = NULL, *node = NULL; node = NextChainHeadFrom(hash); // Find the first node on or after index. while (node != NULL) { if (node->Index() >= index) { nodeAfter = node; node = NULL; } else { node = node->next; } } if (nodeAfter == NULL) return B_ERROR; node = nodeAfter; // Now find whichever of the n nodes with the same index that // the client has requested. for (int32 k=0; k< findNode; k++) { node = node->next; if (node == NULL) return B_ERROR; } if (node->Index() != nodeAfter->Index()) return B_ERROR; *answer = node; return B_OK; }
ArpIndexedNode* ArpIndexedList::NextChainHeadFrom(int32 hash) { int32 k = hash; while (HashExists(k)) { if (chain[k] != NULL) return chain[k]; k++; } return NULL; }
void ArpIndexedList::SyncTailNode() { for (int32 i=count-1; i>=0; i--) { if (! HashExists(i)) assert(false); if (chain[i] != 0) { tailNode = chain[i]->TailNode(); return; } } tailNode = 0; }
TAction* XdbClearIfNotHash(Transaction *t, const char *dbname, const char *hashname) { size_t existvar = t->MakeVariable(); TOperand *existarg = new TOperandVariable(t, existvar); TActionTest *nexist_test = new TActionTest(t, existarg, false); nexist_test->PushAction(XdbClear(t, dbname)); TActionSequence *sequence = new TActionSequence(t); sequence->PushAction(HashExists(t, hashname, existvar)); sequence->PushAction(nexist_test); return sequence; }
status_t ArpIndexedList::pRemoveNode(ArpIndexedNode *node) { assert(node != 0); int32 hash = HashForIndex(node->Index()); if (! HashExists(hash)) return B_ERROR; if (chain[hash] == 0) return B_ERROR; if (node == chain[hash]) { status_t answer; ArpIndexedNode *unusedVar; answer = pRemoveChainHeadAt(hash, &unusedVar); if (answer != B_OK) return answer; } RemovingNode(node); node->RemoveNode(); RemovedNode(node); return B_OK; }
status_t ArpIndexedList::ChainHeadFrom(int32 index, ArpIndexedNode **node) { long hash = HashForIndex(index); // We used to hash to 1 minus the hash of the index, but we've removed that. // If clients want that, they can send it themselves. *node = 0; while (*node == 0) { if (! HashExists(hash)) return B_ERROR; *node = chain[hash]; hash++; } return B_OK; #if 0 *node = chain[hash]; printf("ArpIndexedList::ChainHeadFrom() 5\n"); fflush(stdout); Print(); if (*node == 0) return B_ERROR; return B_OK; #endif }
status_t ArpIndexedList::NodeBefore(int32 index, ArpIndexedNode **answer, int32 findNode) { long hash = HashForIndex(index); if (hash >= count) hash = count - 1; if (! HashExists(hash)) return B_ERROR; ArpIndexedNode *nodeBefore = 0, *node = 0; // Find the first chain before the index that isn't NULL bool keepLooking = true; for (int32 k = hash; keepLooking; k--) { if (! HashExists(k)) { keepLooking = false; } else if ( (chain[k] != 0) && (chain[k]->Index() <= index) ) { node = chain[k]; keepLooking = false; } } if (node == 0) return B_ERROR; // Find the first node on or before index. while (node != 0) { if (node->next == 0) { nodeBefore = node; node = 0; } else if (node->Index() == index) { nodeBefore = node; node = 0; } else if (node->next->Index() == index) { nodeBefore = node->next; node = 0; } else if ( (node->Index() <= index) && (node->next->Index() >= index) ) { nodeBefore = node; node = 0; } else { node = node->next; } } if (nodeBefore == 0) return B_ERROR; node = nodeBefore; // The above routines might put us on the last node in a // series of nodes with the same index -- no real way around // that, I don't think. If that's the case, rewind us back // to the first node. while ( (node->prev != 0) && (node->prev->Index() == node->Index()) ) node = node->prev; // Now find whichever of the n nodes with the same index that // the client has requested. for (int32 k=1; k<= findNode; k++) { node = node->next; if (node == 0) return B_ERROR; } if (node->Index() != nodeBefore->Index()) return B_ERROR; *answer = node; return B_OK; }
int32 ArpIndexedList::IndexHeadFrom(int32 index) { long hash = HashForIndex(index); if (! HashExists(hash)) return B_ERROR; return hash * ChainIndexes(); }