def generateNewOrderParams(self): """Return parameters for NEW_ORDER""" w_id = self.makeWarehouseId() d_id = self.makeDistrictId() c_id = self.makeCustomerId() ol_cnt = rand.number(constants.MIN_OL_CNT, constants.MAX_OL_CNT) o_entry_d = datetime.now() ## 1% of transactions roll back rollback = False # FIXME rand.number(1, 100) == 1 i_ids = [] i_w_ids = [] i_qtys = [] for i in range(0, ol_cnt): if rollback and i + 1 == ol_cnt: i_ids.append(self.scaleParameters.items + 1) else: i_ids.append(self.makeItemId()) ## 1% of items are from a remote warehouse remote = (rand.number(1, 100) == 1) if self.scaleParameters.warehouses > 1 and remote: i_w_ids.append( rand.numberExcluding( self.scaleParameters.starting_warehouse, self.scaleParameters.ending_warehouse, w_id)) else: i_w_ids.append(w_id) i_qtys.append(rand.number(1, constants.MAX_OL_QUANTITY)) ## FOR return makeParameterDict(locals(), "w_id", "d_id", "c_id", "o_entry_d", "i_ids", "i_w_ids", "i_qtys")
def generatePaymentParams(self): """Return parameters for PAYMENT""" x = rand.number(1, 100) y = rand.number(1, 100) w_id = self.makeWarehouseId() d_id = self.makeDistrictId() c_w_id = None c_d_id = None c_id = None c_last = None h_amount = rand.fixedPoint(2, constants.MIN_PAYMENT, constants.MAX_PAYMENT) h_date = datetime.now() ## 85%: paying through own warehouse (or there is only 1 warehouse) if self.scaleParameters.warehouses == 1 or x <= 85: c_w_id = w_id c_d_id = d_id ## 15%: paying through another warehouse: else: ## select in range [1, num_warehouses] excluding w_id c_w_id = rand.numberExcluding(self.scaleParameters.starting_warehouse, self.scaleParameters.ending_warehouse, w_id) assert c_w_id != w_id c_d_id = self.makeDistrictId() ## 60%: payment by last name if y <= 60: c_last = rand.makeRandomLastName(self.scaleParameters.customersPerDistrict) ## 40%: payment by id else: assert y > 60 c_id = self.makeCustomerId() return makeParameterDict(locals(), "w_id", "d_id", "h_amount", "c_w_id", "c_d_id", "c_id", "c_last", "h_date")
def generateNewOrderParams(self): """Return parameters for NEW_ORDER""" w_id = self.makeWarehouseId() d_id = self.makeDistrictId() c_id = self.makeCustomerId() ol_cnt = rand.number(constants.MIN_OL_CNT, constants.MAX_OL_CNT) o_entry_d = datetime.now() ## 1% of transactions roll back rollback = False # FIXME rand.number(1, 100) == 1 i_ids = [ ] i_w_ids = [ ] i_qtys = [ ] for i in range(0, ol_cnt): if rollback and i + 1 == ol_cnt: i_ids.append(self.scaleParameters.items + 1) else: i_ids.append(self.makeItemId()) ## 1% of items are from a remote warehouse remote = (rand.number(1, 100) == 1) if self.scaleParameters.warehouses > 1 and remote: i_w_ids.append(rand.numberExcluding(self.scaleParameters.starting_warehouse, self.scaleParameters.ending_warehouse, w_id)) else: i_w_ids.append(w_id) i_qtys.append(rand.number(1, constants.MAX_OL_QUANTITY)) ## FOR return makeParameterDict(locals(), "w_id", "d_id", "c_id", "o_entry_d", "i_ids", "i_w_ids", "i_qtys")
def makeForRun(loadC): """Create random NURand constants for running TPC-C. TPC-C 2.1.6.1. (page 20) specifies the valid range for these constants.""" cRun = rand.number(0, 255) while validCRun(cRun, loadC.cLast) == False: cRun = rand.number(0, 255) assert validCRun(cRun, loadC.cLast) cId = rand.number(0, 1023) orderLineItemId = rand.number(0, 8191) return NURandC(cRun, cId, orderLineItemId)
def doOne(self): """Selects and executes a transaction at random. The number of new order transactions executed per minute is the official "tpmC" metric. See TPC-C 5.4.2 (page 71).""" ## This is not strictly accurate: The requirement is for certain ## *minimum* percentages to be maintained. This is close to the right ## thing, but not precisely correct. See TPC-C 5.2.4 (page 68). x = rand.number(1, 100) params = None txn = None if x <= 4: ## 4% txn, params = (constants.TransactionTypes.STOCK_LEVEL, self.generateStockLevelParams()) elif x <= 4 + 4: ## 4% txn, params = (constants.TransactionTypes.DELIVERY, self.generateDeliveryParams()) elif x <= 4 + 4 + 4: ## 4% txn, params = (constants.TransactionTypes.ORDER_STATUS, self.generateOrderStatusParams()) elif x <= 43 + 4 + 4 + 4: ## 43% txn, params = (constants.TransactionTypes.PAYMENT, self.generatePaymentParams()) else: ## 45% assert x > 100 - 45 txn, params = (constants.TransactionTypes.NEW_ORDER, self.generateNewOrderParams()) return (txn, params)
def generateStockLevelParams(self): """Returns parameters for STOCK_LEVEL""" w_id = self.makeWarehouseId() d_id = self.makeDistrictId() threshold = rand.number(constants.MIN_STOCK_LEVEL_THRESHOLD, constants.MAX_STOCK_LEVEL_THRESHOLD) return makeParameterDict(locals(), "w_id", "d_id", "threshold")
def makeWarehouseId(self): w_id = rand.number(self.scaleParameters.starting_warehouse, self.scaleParameters.ending_warehouse) assert (w_id >= self.scaleParameters.starting_warehouse ), "Invalid W_ID: %d" % w_id assert (w_id <= self.scaleParameters.ending_warehouse ), "Invalid W_ID: %d" % w_id return w_id
def generateDeliveryParams(self): """Return parameters for DELIVERY""" w_id = self.makeWarehouseId() o_carrier_id = rand.number(constants.MIN_CARRIER_ID, constants.MAX_CARRIER_ID) ol_delivery_d = datetime.now() return makeParameterDict(locals(), "w_id", "o_carrier_id", "ol_delivery_d")
def generateItem(self, id, original): i_id = id i_im_id = rand.number(constants.MIN_IM, constants.MAX_IM) i_name = rand.astring(constants.MIN_I_NAME, constants.MAX_I_NAME) i_price = rand.fixedPoint(constants.MONEY_DECIMALS, constants.MIN_PRICE, constants.MAX_PRICE) i_data = rand.astring(constants.MIN_I_DATA, constants.MAX_I_DATA) if original: i_data = self.fillOriginal(i_data) return [i_id, i_im_id, i_name, i_price, i_data]
def generateOrder(self, o_w_id, o_d_id, o_id, o_c_id, o_ol_cnt, newOrder): """Returns the generated o_ol_cnt value.""" o_entry_d = datetime.now() o_carrier_id = constants.NULL_CARRIER_ID if newOrder else rand.number( constants.MIN_CARRIER_ID, constants.MAX_CARRIER_ID) o_all_local = constants.INITIAL_ALL_LOCAL return [ o_id, o_c_id, o_d_id, o_w_id, o_entry_d, o_carrier_id, o_ol_cnt, o_all_local ]
def fillOriginal(self, data): """ a string with ORIGINAL_STRING at a random position """ originalLength = len(constants.ORIGINAL_STRING) position = rand.number(0, len(data) - originalLength) out = data[:position] + constants.ORIGINAL_STRING + data[position + originalLength:] assert len(out) == len(data) return out ## DEF ## CLASS
def generatePaymentParams(self): """Return parameters for PAYMENT""" x = rand.number(1, 100) y = rand.number(1, 100) w_id = self.makeWarehouseId() d_id = self.makeDistrictId() c_w_id = None c_d_id = None c_id = None c_last = None h_amount = rand.fixedPoint(2, constants.MIN_PAYMENT, constants.MAX_PAYMENT) h_date = datetime.now() ## 85%: paying through own warehouse (or there is only 1 warehouse) if self.scaleParameters.warehouses == 1 or x <= 85: c_w_id = w_id c_d_id = d_id ## 15%: paying through another warehouse: else: ## select in range [1, num_warehouses] excluding w_id c_w_id = rand.numberExcluding( self.scaleParameters.starting_warehouse, self.scaleParameters.ending_warehouse, w_id) assert c_w_id != w_id c_d_id = self.makeDistrictId() ## 60%: payment by last name if y <= 60: c_last = rand.makeRandomLastName( self.scaleParameters.customersPerDistrict) ## 40%: payment by id else: assert y > 60 c_id = self.makeCustomerId() return makeParameterDict(locals(), "w_id", "d_id", "h_amount", "c_w_id", "c_d_id", "c_id", "c_last", "h_date")
def generateOrderLine(self, ol_w_id, ol_d_id, ol_o_id, ol_number, max_items, newOrder): ol_i_id = rand.number(1, max_items) ol_supply_w_id = ol_w_id ol_delivery_d = datetime.now() ol_quantity = constants.INITIAL_QUANTITY if newOrder == False: ol_amount = 0.00 else: ol_amount = rand.fixedPoint(constants.MONEY_DECIMALS, constants.MIN_AMOUNT, constants.MAX_PRICE * constants.MAX_OL_QUANTITY) ol_delivery_d = None ol_dist_info = rand.astring(constants.DIST, constants.DIST) return [ ol_o_id, ol_d_id, ol_w_id, ol_number, ol_i_id, ol_supply_w_id, ol_delivery_d, ol_quantity, ol_amount, ol_dist_info ]
def fillOriginal(self, data): """ a string with ORIGINAL_STRING at a random position """ originalLength = len(constants.ORIGINAL_STRING) position = rand.number(0, len(data) - originalLength) out = data[:position] + constants.ORIGINAL_STRING + data[ position + originalLength:] assert len(out) == len(data) return out ## DEF ## CLASS
def generateOrderStatusParams(self): """Return parameters for ORDER_STATUS""" w_id = self.makeWarehouseId() d_id = self.makeDistrictId() c_last = None c_id = None ## 60%: order status by last name if rand.number(1, 100) <= 60: c_last = rand.makeRandomLastName(self.scaleParameters.customersPerDistrict) ## 40%: order status by id else: c_id = self.makeCustomerId() return makeParameterDict(locals(), "w_id", "d_id", "c_id", "c_last")
def generateStock(self, s_w_id, s_i_id, original): s_quantity = rand.number(constants.MIN_QUANTITY, constants.MAX_QUANTITY); s_ytd = 0; s_order_cnt = 0; s_remote_cnt = 0; s_data = rand.astring(constants.MIN_I_DATA, constants.MAX_I_DATA); if original: self.fillOriginal(s_data) s_dists = [ ] for i in range(0, constants.DISTRICTS_PER_WAREHOUSE): s_dists.append(rand.astring(constants.DIST, constants.DIST)) return [ s_i_id, s_w_id, s_quantity ] + \ s_dists + \ [ s_ytd, s_order_cnt, s_remote_cnt, s_data ]
def generateStock(self, s_w_id, s_i_id, original): s_quantity = rand.number(constants.MIN_QUANTITY, constants.MAX_QUANTITY) s_ytd = 0 s_order_cnt = 0 s_remote_cnt = 0 s_data = rand.astring(constants.MIN_I_DATA, constants.MAX_I_DATA) if original: self.fillOriginal(s_data) s_dists = [] for i in range(0, constants.DISTRICTS_PER_WAREHOUSE): s_dists.append(rand.astring(constants.DIST, constants.DIST)) return [ s_i_id, s_w_id, s_quantity ] + \ s_dists + \ [ s_ytd, s_order_cnt, s_remote_cnt, s_data ]
def generateOrderStatusParams(self): """Return parameters for ORDER_STATUS""" w_id = self.makeWarehouseId() d_id = self.makeDistrictId() c_last = None c_id = None ## 60%: order status by last name if rand.number(1, 100) <= 60: c_last = rand.makeRandomLastName( self.scaleParameters.customersPerDistrict) ## 40%: order status by id else: c_id = self.makeCustomerId() return makeParameterDict(locals(), "w_id", "d_id", "c_id", "c_last")
def generateOrderLine(self, ol_w_id, ol_d_id, ol_o_id, ol_number, max_items, newOrder): ol_i_id = rand.number(1, max_items) ol_supply_w_id = ol_w_id ol_delivery_d = datetime.now() ol_quantity = constants.INITIAL_QUANTITY if newOrder == False: ol_amount = 0.00 else: ol_amount = rand.fixedPoint( constants.MONEY_DECIMALS, constants.MIN_AMOUNT, constants.MAX_PRICE * constants.MAX_OL_QUANTITY) ol_delivery_d = None ol_dist_info = rand.astring(constants.DIST, constants.DIST) return [ ol_o_id, ol_d_id, ol_w_id, ol_number, ol_i_id, ol_supply_w_id, ol_delivery_d, ol_quantity, ol_amount, ol_dist_info ]
def makeWarehouseId(self): w_id = rand.number(self.scaleParameters.starting_warehouse, self.scaleParameters.ending_warehouse) assert(w_id >= self.scaleParameters.starting_warehouse), "Invalid W_ID: %d" % w_id assert(w_id <= self.scaleParameters.ending_warehouse), "Invalid W_ID: %d" % w_id return w_id
def makeForLoad(): """Create random NURand constants, appropriate for loading the database.""" cLast = rand.number(0, 255) cId = rand.number(0, 1023) orderLineItemId = rand.number(0, 8191) return NURandC(cLast, cId, orderLineItemId)
def loadWarehouse(self, w_id): logging.debug("LOAD - %s: %d / %d" % (constants.TABLENAME_WAREHOUSE, w_id, len(self.w_ids))) ## WAREHOUSE w_tuples = [ self.generateWarehouse(w_id) ] self.handle.loadTuples(constants.TABLENAME_WAREHOUSE, w_tuples) ## DISTRICT d_tuples = [ ] for d_id in range(1, self.scaleParameters.districtsPerWarehouse+1): d_next_o_id = self.scaleParameters.customersPerDistrict + 1 d_tuples = [ self.generateDistrict(w_id, d_id, d_next_o_id) ] c_tuples = [ ] h_tuples = [ ] ## Select 10% of the customers to have bad credit selectedRows = rand.selectUniqueIds(self.scaleParameters.customersPerDistrict / 10, 1, self.scaleParameters.customersPerDistrict) ## TPC-C 4.3.3.1. says that o_c_id should be a permutation of [1, 3000]. But since it ## is a c_id field, it seems to make sense to have it be a permutation of the ## customers. For the "real" thing this will be equivalent cIdPermutation = [ ] for c_id in range(1, self.scaleParameters.customersPerDistrict+1): badCredit = (c_id in selectedRows) c_tuples.append(self.generateCustomer(w_id, d_id, c_id, badCredit, True)) h_tuples.append(self.generateHistory(w_id, d_id, c_id)) cIdPermutation.append(c_id) ## FOR assert cIdPermutation[0] == 1 assert cIdPermutation[self.scaleParameters.customersPerDistrict - 1] == self.scaleParameters.customersPerDistrict shuffle(cIdPermutation) o_tuples = [ ] ol_tuples = [ ] no_tuples = [ ] for o_id in range(1, self.scaleParameters.customersPerDistrict): o_ol_cnt = rand.number(constants.MIN_OL_CNT, constants.MAX_OL_CNT) ## The last newOrdersPerDistrict are new orders newOrder = ((self.scaleParameters.customersPerDistrict - self.scaleParameters.newOrdersPerDistrict) < o_id) o_tuples.append(self.generateOrder(w_id, d_id, o_id, cIdPermutation[o_id - 1], o_ol_cnt, newOrder)) ## Generate each OrderLine for the order for ol_number in range(0, o_ol_cnt): ol_tuples.append(self.generateOrderLine(w_id, d_id, o_id, ol_number, self.scaleParameters.items, newOrder)) ## FOR ## This is a new order: make one for it if newOrder: no_tuples.append([o_id, d_id, w_id]) ## FOR self.handle.loadTuples(constants.TABLENAME_DISTRICT, d_tuples) self.handle.loadTuples(constants.TABLENAME_CUSTOMER, c_tuples) self.handle.loadTuples(constants.TABLENAME_ORDERS, o_tuples) self.handle.loadTuples(constants.TABLENAME_ORDER_LINE, ol_tuples) self.handle.loadTuples(constants.TABLENAME_NEW_ORDER, no_tuples) self.handle.loadTuples(constants.TABLENAME_HISTORY, h_tuples) self.handle.loadFinishDistrict(w_id, d_id) ## FOR ## Select 10% of the stock to be marked "original" s_tuples = [ ] selectedRows = rand.selectUniqueIds(self.scaleParameters.items / 10, 1, self.scaleParameters.items) total_tuples = 0 for i_id in range(1, self.scaleParameters.items+1): original = (i_id in selectedRows) s_tuples.append(self.generateStock(w_id, i_id, original)) total_tuples += 1 if len(s_tuples) >= self.batch_size: logging.debug("LOAD - %s [W_ID=%d]: %5d / %d" % (constants.TABLENAME_STOCK, w_id, total_tuples, self.scaleParameters.items)) self.handle.loadTuples(constants.TABLENAME_STOCK, s_tuples) s_tuples = [ ] ## FOR if len(s_tuples) > 0: logging.debug("LOAD - %s [W_ID=%d]: %5d / %d" % (constants.TABLENAME_STOCK, w_id, total_tuples, self.scaleParameters.items)) self.handle.loadTuples(constants.TABLENAME_STOCK, s_tuples)
def makeDistrictId(self): return rand.number(1, self.scaleParameters.districtsPerWarehouse)
def number(definition: Definition) -> Union[Base, float]: value = rand.number(interval=definition.interval) return base(definition.name, value)
def loadWarehouse(self, w_id): logging.debug("LOAD - %s: %d / %d" % (constants.TABLENAME_WAREHOUSE, w_id, len(self.w_ids))) ## WAREHOUSE w_tuples = [self.generateWarehouse(w_id)] self.handle.loadTuples(constants.TABLENAME_WAREHOUSE, w_tuples) ## DISTRICT d_tuples = [] for d_id in range(1, self.scaleParameters.districtsPerWarehouse + 1): d_next_o_id = self.scaleParameters.customersPerDistrict + 1 d_tuples = [self.generateDistrict(w_id, d_id, d_next_o_id)] c_tuples = [] h_tuples = [] ## Select 10% of the customers to have bad credit selectedRows = rand.selectUniqueIds( self.scaleParameters.customersPerDistrict / 10, 1, self.scaleParameters.customersPerDistrict) ## TPC-C 4.3.3.1. says that o_c_id should be a permutation of [1, 3000]. But since it ## is a c_id field, it seems to make sense to have it be a permutation of the ## customers. For the "real" thing this will be equivalent cIdPermutation = [] for c_id in range(1, self.scaleParameters.customersPerDistrict + 1): badCredit = (c_id in selectedRows) c_tuples.append( self.generateCustomer(w_id, d_id, c_id, badCredit, True)) h_tuples.append(self.generateHistory(w_id, d_id, c_id)) cIdPermutation.append(c_id) ## FOR assert cIdPermutation[0] == 1 assert cIdPermutation[ self.scaleParameters.customersPerDistrict - 1] == self.scaleParameters.customersPerDistrict shuffle(cIdPermutation) o_tuples = [] ol_tuples = [] no_tuples = [] for o_id in range(1, self.scaleParameters.customersPerDistrict): o_ol_cnt = rand.number(constants.MIN_OL_CNT, constants.MAX_OL_CNT) ## The last newOrdersPerDistrict are new orders newOrder = ((self.scaleParameters.customersPerDistrict - self.scaleParameters.newOrdersPerDistrict) < o_id) o_tuples.append( self.generateOrder(w_id, d_id, o_id, cIdPermutation[o_id - 1], o_ol_cnt, newOrder)) ## Generate each OrderLine for the order for ol_number in range(0, o_ol_cnt): ol_tuples.append( self.generateOrderLine(w_id, d_id, o_id, ol_number, self.scaleParameters.items, newOrder)) ## FOR ## This is a new order: make one for it if newOrder: no_tuples.append([o_id, d_id, w_id]) ## FOR self.handle.loadTuples(constants.TABLENAME_DISTRICT, d_tuples) self.handle.loadTuples(constants.TABLENAME_CUSTOMER, c_tuples) self.handle.loadTuples(constants.TABLENAME_ORDERS, o_tuples) self.handle.loadTuples(constants.TABLENAME_ORDER_LINE, ol_tuples) self.handle.loadTuples(constants.TABLENAME_NEW_ORDER, no_tuples) self.handle.loadTuples(constants.TABLENAME_HISTORY, h_tuples) self.handle.loadFinishDistrict(w_id, d_id) ## FOR ## Select 10% of the stock to be marked "original" s_tuples = [] selectedRows = rand.selectUniqueIds(self.scaleParameters.items / 10, 1, self.scaleParameters.items) total_tuples = 0 for i_id in range(1, self.scaleParameters.items + 1): original = (i_id in selectedRows) s_tuples.append(self.generateStock(w_id, i_id, original)) total_tuples += 1 if len(s_tuples) >= self.batch_size: logging.debug("LOAD - %s [W_ID=%d]: %5d / %d" % (constants.TABLENAME_STOCK, w_id, total_tuples, self.scaleParameters.items)) self.handle.loadTuples(constants.TABLENAME_STOCK, s_tuples) s_tuples = [] ## FOR if len(s_tuples) > 0: logging.debug("LOAD - %s [W_ID=%d]: %5d / %d" % (constants.TABLENAME_STOCK, w_id, total_tuples, self.scaleParameters.items)) self.handle.loadTuples(constants.TABLENAME_STOCK, s_tuples)
def generateOrder(self, o_w_id, o_d_id, o_id, o_c_id, o_ol_cnt, newOrder): """Returns the generated o_ol_cnt value.""" o_entry_d = datetime.now() o_carrier_id = constants.NULL_CARRIER_ID if newOrder else rand.number(constants.MIN_CARRIER_ID, constants.MAX_CARRIER_ID) o_all_local = constants.INITIAL_ALL_LOCAL return [ o_id, o_c_id, o_d_id, o_w_id, o_entry_d, o_carrier_id, o_ol_cnt, o_all_local ]