/* ============================================================================= * TMnet_findDescendants * -- Contents of bitmapPtr set to 1 if descendants, else 0 * -- Returns false if id is not root node (i.e., has cycle back id) * ============================================================================= */ bool_t TMnet_findDescendants (TM_ARGDECL net_t* netPtr, long id, bitmap_t* descendantBitmapPtr, queue_t* workQueuePtr) { bool_t status; vector_t* nodeVectorPtr = netPtr->nodeVectorPtr; assert(descendantBitmapPtr->numBit == vector_getSize(nodeVectorPtr)); PBITMAP_CLEARALL(descendantBitmapPtr); PQUEUE_CLEAR(workQueuePtr); { net_node_t* nodePtr = (net_node_t*)vector_at(nodeVectorPtr, id); list_t* childIdListPtr = nodePtr->childIdListPtr; list_iter_t it; TMLIST_ITER_RESET(&it, childIdListPtr); while (TMLIST_ITER_HASNEXT(&it, childIdListPtr)) { long childId = (long)TMLIST_ITER_NEXT(&it, childIdListPtr); status = PBITMAP_SET(descendantBitmapPtr, childId); assert(status); status = PQUEUE_PUSH(workQueuePtr, (void*)childId); assert(status); } } while (!PQUEUE_ISEMPTY(workQueuePtr)) { long childId = (long)PQUEUE_POP(workQueuePtr); if (childId == id) { queue_clear(workQueuePtr); return FALSE; } net_node_t* nodePtr = (net_node_t*)vector_at(nodeVectorPtr, childId); list_t* grandChildIdListPtr = nodePtr->childIdListPtr; list_iter_t it; TMLIST_ITER_RESET(&it, grandChildIdListPtr); while (TMLIST_ITER_HASNEXT(&it, grandChildIdListPtr)) { long grandChildId = (long)TMLIST_ITER_NEXT(&it, grandChildIdListPtr); if (!PBITMAP_ISSET(descendantBitmapPtr, grandChildId)) { status = PBITMAP_SET(descendantBitmapPtr, grandChildId); assert(status); status = PQUEUE_PUSH(workQueuePtr, (void*)grandChildId); assert(status); } } } return TRUE; }
/* ============================================================================= * TMnet_findAncestors * -- Contents of bitmapPtr set to 1 if ancestor, else 0 * -- Returns false if id is not root node (i.e., has cycle back id) * ============================================================================= */ bool_t TMnet_findAncestors (TM_ARGDECL net_t* netPtr, long id, bitmap_t* ancestorBitmapPtr, queue_t* workQueuePtr) { bool_t status; vector_t* nodeVectorPtr = netPtr->nodeVectorPtr; assert(ancestorBitmapPtr->numBit == vector_getSize(nodeVectorPtr)); PBITMAP_CLEARALL(ancestorBitmapPtr); PQUEUE_CLEAR(workQueuePtr); { net_node_t* nodePtr = (net_node_t*)vector_at(nodeVectorPtr, id); list_t* parentIdListPtr = nodePtr->parentIdListPtr; list_iter_t it; TMLIST_ITER_RESET(&it, parentIdListPtr); while (TMLIST_ITER_HASNEXT(&it, parentIdListPtr)) { long parentId = (long)TMLIST_ITER_NEXT(&it, parentIdListPtr); status = PBITMAP_SET(ancestorBitmapPtr, parentId); assert(status); status = PQUEUE_PUSH(workQueuePtr, (void*)parentId); assert(status); } } while (!PQUEUE_ISEMPTY(workQueuePtr)) { long parentId = (long)PQUEUE_POP(workQueuePtr); if (parentId == id) { PQUEUE_CLEAR(workQueuePtr); return FALSE; } net_node_t* nodePtr = (net_node_t*)vector_at(nodeVectorPtr, parentId); list_t* grandParentIdListPtr = nodePtr->parentIdListPtr; list_iter_t it; TMLIST_ITER_RESET(&it, grandParentIdListPtr); while (TMLIST_ITER_HASNEXT(&it, grandParentIdListPtr)) { long grandParentId = (long)TMLIST_ITER_NEXT(&it, grandParentIdListPtr); if (!PBITMAP_ISSET(ancestorBitmapPtr, grandParentId)) { status = PBITMAP_SET(ancestorBitmapPtr, grandParentId); assert(status); status = PQUEUE_PUSH(workQueuePtr, (void*)grandParentId); assert(status); } } } return TRUE; }
/* ============================================================================= * TMhashtable_iter_next * ============================================================================= */ void* TMhashtable_iter_next (TM_ARGDECL hashtable_iter_t* itPtr, hashtable_t* hashtablePtr) { long bucket; long numBucket = hashtablePtr->numBucket; list_t** buckets = hashtablePtr->buckets; list_iter_t it = itPtr->it; void* dataPtr = NULL; for (bucket = itPtr->bucket; bucket < numBucket; /* inside body */) { list_t* chainPtr = hashtablePtr->buckets[bucket]; if (TMLIST_ITER_HASNEXT(&it, chainPtr)) { pair_t* pairPtr = (pair_t*)TMLIST_ITER_NEXT(&it, chainPtr); dataPtr = pairPtr->secondPtr; break; } /* May use dummy bucket; see allocBuckets() */ TMLIST_ITER_RESET(&it, buckets[++bucket]); } itPtr->bucket = bucket; itPtr->it = it; return dataPtr; }
/* ============================================================================= * customer_getBill * -- Returns total cost of reservations * ============================================================================= */ __attribute__((transaction_safe)) long customer_getBill (customer_t* customerPtr) { long bill = 0; list_iter_t it; list_t* reservationInfoListPtr = customerPtr->reservationInfoListPtr; TMLIST_ITER_RESET(&it, reservationInfoListPtr); while (TMLIST_ITER_HASNEXT(&it, reservationInfoListPtr)) { reservation_info_t* reservationInfoPtr = (reservation_info_t*)TMLIST_ITER_NEXT(&it, reservationInfoListPtr); bill += reservationInfoPtr->price; } return bill; }
/* ============================================================================= * manager_deleteCustomer * -- Delete this customer and associated reservations * -- If customer does not exist, returns success * -- Returns true on success, else false * ============================================================================= */ bool manager_deleteCustomer (TM_ARGDECL manager_t* managerPtr, long customerId) { customer_t* customerPtr; MAP_T* reservationTables[NUM_RESERVATION_TYPE]; list_t* reservationInfoListPtr; list_iter_t it; bool status; customerPtr = (customer_t*)TMMAP_FIND(managerPtr->customerTablePtr, customerId); if (customerPtr == NULL) { return false; } reservationTables[RESERVATION_CAR] = managerPtr->carTablePtr; reservationTables[RESERVATION_ROOM] = managerPtr->roomTablePtr; reservationTables[RESERVATION_FLIGHT] = managerPtr->flightTablePtr; /* Cancel this customer's reservations */ reservationInfoListPtr = customerPtr->reservationInfoListPtr; TMLIST_ITER_RESET(&it, reservationInfoListPtr); while (TMLIST_ITER_HASNEXT(&it, reservationInfoListPtr)) { reservation_info_t* reservationInfoPtr; reservation_t* reservationPtr; reservationInfoPtr = (reservation_info_t*)TMLIST_ITER_NEXT(&it, reservationInfoListPtr); reservationPtr = (reservation_t*)TMMAP_FIND(reservationTables[reservationInfoPtr->type], reservationInfoPtr->id); if (reservationPtr == NULL) { TM_RESTART(); } status = RESERVATION_CANCEL(reservationPtr); if (!status) { TM_RESTART(); } RESERVATION_INFO_FREE(reservationInfoPtr); } status = TMMAP_REMOVE(managerPtr->customerTablePtr, customerId); if (!status) { TM_RESTART(); } CUSTOMER_FREE(customerPtr); return true; }
/* ============================================================================= * customer_getBill * -- Returns total cost of reservations * ============================================================================= */ long customer_getBill (TM_ARGDECL customer_t* customerPtr) { long bill = 0; list_iter_t it; list_t* reservationInfoListPtr = (list_t*)TM_SHARED_READ_P(customerPtr->reservationInfoListPtr); TMLIST_ITER_RESET(&it, reservationInfoListPtr); while (TMLIST_ITER_HASNEXT(&it, reservationInfoListPtr)) { reservation_info_t* reservationInfoPtr = (reservation_info_t*)TMLIST_ITER_NEXT(&it, reservationInfoListPtr); bill += reservationInfoPtr->price; } return bill; }
/* ============================================================================= * TMnet_hasEdge * ============================================================================= */ bool_t TMnet_hasEdge (TM_ARGDECL net_t* netPtr, long fromId, long toId) { vector_t* nodeVectorPtr = netPtr->nodeVectorPtr; net_node_t* childNodePtr = (net_node_t*)vector_at(nodeVectorPtr, toId); list_t* parentIdListPtr = childNodePtr->parentIdListPtr; list_iter_t it; TMLIST_ITER_RESET(&it, parentIdListPtr); while (TMLIST_ITER_HASNEXT(&it, parentIdListPtr)) { long parentId = (long)TMLIST_ITER_NEXT(&it, parentIdListPtr); if (parentId == fromId) { return TRUE; } } return FALSE; }
/* ============================================================================= * TMnet_isPath * ============================================================================= */ bool_t TMnet_isPath (TM_ARGDECL net_t* netPtr, long fromId, long toId, bitmap_t* visitedBitmapPtr, queue_t* workQueuePtr) { bool_t status; vector_t* nodeVectorPtr = netPtr->nodeVectorPtr; assert(visitedBitmapPtr->numBit == vector_getSize(nodeVectorPtr)); PBITMAP_CLEARALL(visitedBitmapPtr); PQUEUE_CLEAR(workQueuePtr); status = PQUEUE_PUSH(workQueuePtr, (void*)fromId); assert(status); while (!PQUEUE_ISEMPTY(workQueuePtr)) { long id = (long)queue_pop(workQueuePtr); if (id == toId) { queue_clear(workQueuePtr); return TRUE; } status = PBITMAP_SET(visitedBitmapPtr, id); assert(status); net_node_t* nodePtr = (net_node_t*)vector_at(nodeVectorPtr, id); list_t* childIdListPtr = nodePtr->childIdListPtr; list_iter_t it; TMLIST_ITER_RESET(&it, childIdListPtr); while (TMLIST_ITER_HASNEXT(&it, childIdListPtr)) { long childId = (long)TMLIST_ITER_NEXT(&it, childIdListPtr); if (!PBITMAP_ISSET(visitedBitmapPtr, childId)) { status = PQUEUE_PUSH(workQueuePtr, (void*)childId); assert(status); } } } return FALSE; }
/* ============================================================================= * TMdecoder_process * ============================================================================= */ int_error_t TMdecoder_process (TM_ARGDECL decoder_t* decoderPtr, char* bytes, long numByte) { bool_t status; /* * Basic error checking */ if (numByte < (long)PACKET_HEADER_LENGTH) { return ERROR_SHORT; } packet_t* packetPtr = (packet_t*)bytes; long flowId = packetPtr->flowId; long fragmentId = packetPtr->fragmentId; long numFragment = packetPtr->numFragment; long length = packetPtr->length; if (flowId < 0) { return ERROR_FLOWID; } if ((fragmentId < 0) || (fragmentId >= numFragment)) { return ERROR_FRAGMENTID; } if (length < 0) { return ERROR_LENGTH; } #if 0 /* * With the above checks, this one is redundant */ if (numFragment < 1) { return ERROR_NUMFRAGMENT; } #endif /* * Add to fragmented map for reassembling */ if (numFragment > 1) { MAP_T* fragmentedMapPtr = decoderPtr->fragmentedMapPtr; list_t* fragmentListPtr = (list_t*)TMMAP_FIND(fragmentedMapPtr, (void*)flowId); if (fragmentListPtr == NULL) { fragmentListPtr = TMLIST_ALLOC(&decoder_comparator); assert(fragmentListPtr); status = TMLIST_INSERT(fragmentListPtr, (void*)packetPtr); assert(status); status = TMMAP_INSERT(fragmentedMapPtr, (void*)flowId, (void*)fragmentListPtr); assert(status); } else { list_iter_t it; TMLIST_ITER_RESET(&it, fragmentListPtr); assert(TMLIST_ITER_HASNEXT(&it, fragmentListPtr)); packet_t* firstFragmentPtr = (packet_t*)TMLIST_ITER_NEXT(&it, fragmentListPtr); long expectedNumFragment = firstFragmentPtr->numFragment; if (numFragment != expectedNumFragment) { status = TMMAP_REMOVE(fragmentedMapPtr, (void*)flowId); assert(status); return ERROR_NUMFRAGMENT; } status = TMLIST_INSERT(fragmentListPtr, (void*)packetPtr); assert(status); /* * If we have all the fragments we can reassemble them */ if (TMLIST_GETSIZE(fragmentListPtr) == numFragment) { long numByte = 0; long i = 0; TMLIST_ITER_RESET(&it, fragmentListPtr); while (TMLIST_ITER_HASNEXT(&it, fragmentListPtr)) { packet_t* fragmentPtr = (packet_t*)TMLIST_ITER_NEXT(&it, fragmentListPtr); if(fragmentPtr->flowId != flowId) printf("fragflow %lx floId %lx\n", fragmentPtr->flowId, flowId); assert(fragmentPtr->flowId == flowId); if (fragmentPtr->fragmentId != i) { status = TMMAP_REMOVE(fragmentedMapPtr, (void*)flowId); assert(status); return ERROR_INCOMPLETE; /* should be sequential */ } numByte += fragmentPtr->length; i++; } char* data = (char*)TM_MALLOC(numByte + 1); assert(data); data[numByte] = '\0'; char* dst = data; TMLIST_ITER_RESET(&it, fragmentListPtr); while (TMLIST_ITER_HASNEXT(&it, fragmentListPtr)) { packet_t* fragmentPtr = (packet_t*)TMLIST_ITER_NEXT(&it, fragmentListPtr); memcpy(dst, (void*)fragmentPtr->data, fragmentPtr->length); dst += fragmentPtr->length; } assert(dst == data + numByte); decoded_t* decodedPtr = (decoded_t*)TM_MALLOC(sizeof(decoded_t)); assert(decodedPtr); decodedPtr->flowId = flowId; decodedPtr->data = data; queue_t* decodedQueuePtr = decoderPtr->decodedQueuePtr; status = TMQUEUE_PUSH(decodedQueuePtr, (void*)decodedPtr); assert(status); TMLIST_FREE(fragmentListPtr); status = TMMAP_REMOVE(fragmentedMapPtr, (void*)flowId); assert(status); } } } else { /* * This is the only fragment, so it is ready */ if (fragmentId != 0) { return ERROR_FRAGMENTID; } char* data = (char*)TM_MALLOC(length + 1); assert(data); data[length] = '\0'; memcpy(data, (void*)packetPtr->data, length); decoded_t* decodedPtr = (decoded_t*)TM_MALLOC(sizeof(decoded_t)); assert(decodedPtr); decodedPtr->flowId = flowId; decodedPtr->data = data; queue_t* decodedQueuePtr = decoderPtr->decodedQueuePtr; status = TMQUEUE_PUSH(decodedQueuePtr, (void*)decodedPtr); assert(status); } return ERROR_NONE; }
/* ============================================================================= * TMgrowRegion * -- Return NULL if success, else pointer to encroached boundary * ============================================================================= */ element_t* TMgrowRegion (TM_ARGDECL element_t* centerElementPtr, region_t* regionPtr, mesh_t* meshPtr, MAP_T* edgeMapPtr) { bool_t isBoundary = FALSE; if (element_getNumEdge(centerElementPtr) == 1) { isBoundary = TRUE; } list_t* beforeListPtr = regionPtr->beforeListPtr; list_t* borderListPtr = regionPtr->borderListPtr; queue_t* expandQueuePtr = regionPtr->expandQueuePtr; PLIST_CLEAR(beforeListPtr); PLIST_CLEAR(borderListPtr); PQUEUE_CLEAR(expandQueuePtr); coordinate_t centerCoordinate = TMelement_getNewPoint(TM_ARG centerElementPtr); coordinate_t* centerCoordinatePtr = ¢erCoordinate; PQUEUE_PUSH(expandQueuePtr, (void*)centerElementPtr); while (!PQUEUE_ISEMPTY(expandQueuePtr)) { element_t* currentElementPtr = (element_t*)PQUEUE_POP(expandQueuePtr); PLIST_INSERT(beforeListPtr, (void*)currentElementPtr); /* no duplicates */ list_t* neighborListPtr = TMelement_getNeighborListPtr(TM_ARG currentElementPtr); list_iter_t it; TMLIST_ITER_RESET(&it, neighborListPtr); while (TMLIST_ITER_HASNEXT(&it, neighborListPtr)) { element_t* neighborElementPtr = (element_t*)TMLIST_ITER_NEXT(&it, neighborListPtr); TMELEMENT_ISGARBAGE(neighborElementPtr); /* so we can detect conflicts */ if (!list_find(beforeListPtr, (void*)neighborElementPtr)) { if (element_isInCircumCircle(neighborElementPtr, centerCoordinatePtr)) { /* This is part of the region */ if (!isBoundary && (element_getNumEdge(neighborElementPtr) == 1)) { /* Encroached on mesh boundary so split it and restart */ return neighborElementPtr; } else { /* Continue breadth-first search */ bool_t isSuccess; isSuccess = PQUEUE_PUSH(expandQueuePtr, (void*)neighborElementPtr); assert(isSuccess); } } else { /* This element borders region; save info for retriangulation */ edge_t* borderEdgePtr = TMelement_getCommonEdge(TM_ARG neighborElementPtr, currentElementPtr); if (!borderEdgePtr) { TM_RESTART(); } PLIST_INSERT(borderListPtr, (void*)borderEdgePtr); /* no duplicates */ if (!MAP_CONTAINS(edgeMapPtr, borderEdgePtr)) { PMAP_INSERT(edgeMapPtr, borderEdgePtr, neighborElementPtr); } } } /* not visited before */ } /* for each neighbor */ } /* breadth-first search */ return NULL; }
/* ============================================================================= * TMretriangulate * -- Returns net amount of elements added to mesh * ============================================================================= */ long TMretriangulate (TM_ARGDECL element_t* elementPtr, region_t* regionPtr, mesh_t* meshPtr, MAP_T* edgeMapPtr) { vector_t* badVectorPtr = regionPtr->badVectorPtr; /* private */ list_t* beforeListPtr = regionPtr->beforeListPtr; /* private */ list_t* borderListPtr = regionPtr->borderListPtr; /* private */ list_iter_t it; long numDelta = 0L; assert(edgeMapPtr); coordinate_t centerCoordinate = element_getNewPoint(elementPtr); /* * Remove the old triangles */ TMLIST_ITER_RESET(&it, beforeListPtr); while (TMLIST_ITER_HASNEXT(&it, beforeListPtr)) { element_t* beforeElementPtr = (element_t*)TMLIST_ITER_NEXT(&it, beforeListPtr); TMMESH_REMOVE(meshPtr, beforeElementPtr); } numDelta -= PLIST_GETSIZE(beforeListPtr); /* * If segment is encroached, split it in half */ if (element_getNumEdge(elementPtr) == 1) { coordinate_t coordinates[2]; edge_t* edgePtr = element_getEdge(elementPtr, 0); coordinates[0] = centerCoordinate; coordinates[1] = *(coordinate_t*)(edgePtr->firstPtr); element_t* aElementPtr = TMELEMENT_ALLOC(coordinates, 2); assert(aElementPtr); TMMESH_INSERT(meshPtr, aElementPtr, edgeMapPtr); coordinates[1] = *(coordinate_t*)(edgePtr->secondPtr); element_t* bElementPtr = TMELEMENT_ALLOC(coordinates, 2); assert(bElementPtr); TMMESH_INSERT(meshPtr, bElementPtr, edgeMapPtr); bool_t status; status = TMMESH_REMOVEBOUNDARY(meshPtr, element_getEdge(elementPtr, 0)); assert(status); status = TMMESH_INSERTBOUNDARY(meshPtr, element_getEdge(aElementPtr, 0)); assert(status); status = TMMESH_INSERTBOUNDARY(meshPtr, element_getEdge(bElementPtr, 0)); assert(status); numDelta += 2; } /* * Insert the new triangles. These are contructed using the new * point and the two points from the border segment. */ list_iter_reset(&it, borderListPtr); while (list_iter_hasNext(&it, borderListPtr)) { element_t* afterElementPtr; coordinate_t coordinates[3]; edge_t* borderEdgePtr = (edge_t*)list_iter_next(&it, borderListPtr); assert(borderEdgePtr); coordinates[0] = centerCoordinate; coordinates[1] = *(coordinate_t*)(borderEdgePtr->firstPtr); coordinates[2] = *(coordinate_t*)(borderEdgePtr->secondPtr); afterElementPtr = TMELEMENT_ALLOC(coordinates, 3); assert(afterElementPtr); TMMESH_INSERT(meshPtr, afterElementPtr, edgeMapPtr); if (element_isBad(afterElementPtr)) { TMaddToBadVector(TM_ARG badVectorPtr, afterElementPtr); } } numDelta += PLIST_GETSIZE(borderListPtr); return numDelta; }