/* ============================================================================= * cancel * -- Customer is not allowed to cancel multiple times * -- Returns true on success, else false * ============================================================================= */ static TM_CALLABLE bool cancel (TM_ARGDECL MAP_T* tablePtr, MAP_T* customerTablePtr, long customerId, long id, reservation_type_t type) { customer_t* customerPtr; reservation_t* reservationPtr; customerPtr = (customer_t*)TMMAP_FIND(customerTablePtr, customerId); if (customerPtr == NULL) { return false; } reservationPtr = (reservation_t*)TMMAP_FIND(tablePtr, id); if (reservationPtr == NULL) { return false; } if (!RESERVATION_CANCEL(reservationPtr)) { return false; } if (!CUSTOMER_REMOVE_RESERVATION_INFO(customerPtr, type, id)) { /* Undo previous successful cancellation */ bool status = RESERVATION_MAKE(reservationPtr); if (!status) { TM_RESTART(); } return false; } return true; }
/* ============================================================================= * addReservation * -- If 'num' > 0 then add, if < 0 remove * -- Adding 0 seats is error if does not exist * -- If 'price' < 0, do not update price * -- Returns true on success, else false * ============================================================================= */ bool addReservation (TM_ARGDECL MAP_T* tablePtr, long id, long num, long price) { reservation_t* reservationPtr; reservationPtr = (reservation_t*)TMMAP_FIND(tablePtr, id); if (reservationPtr == NULL) { /* Create new reservation */ if (num < 1 || price < 0) { return false; } reservationPtr = RESERVATION_ALLOC(id, num, price); assert(reservationPtr != NULL); TMMAP_INSERT(tablePtr, id, reservationPtr); } else { /* Update existing reservation */ if (!RESERVATION_ADD_TO_TOTAL(reservationPtr, num)) { return false; } if ((long)TM_SHARED_READ_L(reservationPtr->numTotal) == 0) { bool status = TMMAP_REMOVE(tablePtr, id); if (!status) { TM_RESTART(); } RESERVATION_FREE(reservationPtr); } else { RESERVATION_UPDATE_PRICE(reservationPtr, price); } } return true; }
/* ============================================================================= * 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; }
/* ============================================================================= * queryPrice * -- Return price of a reservation, -1 if failure * ============================================================================= */ static long queryPrice (TM_ARGDECL MAP_T* tablePtr, long id) { long price = -1; reservation_t* reservationPtr; reservationPtr = (reservation_t*)TMMAP_FIND(tablePtr, id); if (reservationPtr != NULL) { price = (long)TM_SHARED_READ_L(reservationPtr->price); } return price; }
/* ============================================================================= * queryNumFree * -- Return numFree of a reservation, -1 if failure * ============================================================================= */ static long queryNumFree (TM_ARGDECL MAP_T* tablePtr, long id) { long numFree = -1; reservation_t* reservationPtr; reservationPtr = (reservation_t*)TMMAP_FIND(tablePtr, id); if (reservationPtr != NULL) { numFree = (long)TM_SHARED_READ_L(reservationPtr->numFree); } return numFree; }
/* ============================================================================= * reserve * -- Customer is not allowed to reserve same (type, id) multiple times * -- Returns true on success, else false * ============================================================================= */ static bool reserve (TM_ARGDECL MAP_T* tablePtr, MAP_T* customerTablePtr, long customerId, long id, reservation_type_t type) { customer_t* customerPtr; reservation_t* reservationPtr; customerPtr = (customer_t*)TMMAP_FIND(customerTablePtr, customerId); if (customerPtr == NULL) { return false; } reservationPtr = (reservation_t*)TMMAP_FIND(tablePtr, id); if (reservationPtr == NULL) { return false; } if (!RESERVATION_MAKE(reservationPtr)) { return false; } if (!CUSTOMER_ADD_RESERVATION_INFO( customerPtr, type, id, (long)TM_SHARED_READ_L(reservationPtr->price))) { /* Undo previous successful reservation */ bool status = RESERVATION_CANCEL(reservationPtr); if (!status) { TM_RESTART(); } return false; } return true; }
/* ============================================================================= * manager_queryCustomerBill * -- Return the total price of all reservations held for a customer * -- Returns -1 if the customer does not exist * ============================================================================= */ long manager_queryCustomerBill (TM_ARGDECL manager_t* managerPtr, long customerId) { long bill = -1; customer_t* customerPtr; customerPtr = (customer_t*)TMMAP_FIND(managerPtr->customerTablePtr, customerId); if (customerPtr != NULL) { bill = CUSTOMER_GET_BILL(customerPtr); } return bill; }
/* ============================================================================= * manager_deleteFlight * -- Delete an entire flight * -- Fails if customer has reservation on this flight * -- Returns true on success, else false * ============================================================================= */ bool manager_deleteFlight (TM_ARGDECL manager_t* managerPtr, long flightId) { reservation_t* reservationPtr; reservationPtr = (reservation_t*)TMMAP_FIND(managerPtr->flightTablePtr, flightId); if (reservationPtr == NULL) { return false; } if ((long)TM_SHARED_READ_L(reservationPtr->numUsed) > 0) { return false; /* somebody has a reservation */ } return addReservation(TM_ARG managerPtr->flightTablePtr, flightId, -1*(long)TM_SHARED_READ_L(reservationPtr->numTotal), -1 /* -1 keeps old price */); }
/*** Run a bunch of increment transactions */ void bench_test(uintptr_t, uint32_t* seed) { int val = rand_r(seed) % CFG.elements; uint32_t act = rand_r(seed) % 100; if (act < CFG.lookpct) { TM_BEGIN(/*atomic*/); TMMAP_FIND(SET, val); // SET->lookup(val TM_PARAM); TM_END(); } else if (act < CFG.inspct) { TM_BEGIN(/*atomic*/); TMMAP_INSERT(SET, val, val); // SET->insert(val TM_PARAM); TM_END(); } else { TM_BEGIN(/*atomic*/); //std::cout << " val " << val << std::endl; TMMAP_REMOVE(SET, val); //SET->remove(val TM_PARAM); TM_END(); } }
/* ============================================================================= * 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; }