public int newCustomer(int id) throws RemoteException { Trace.info("INFO: RM::newCustomer(" + id + ") called"); // Generate a globally unique ID for the new customer int cid = Integer.parseInt( String.valueOf(id) + String.valueOf(Calendar.getInstance().get(Calendar.MILLISECOND)) + String.valueOf(Math.round(Math.random() * 100 + 1))); Customer cust = new Customer(cid); writeData(id, cust.getKey(), cust); Customer temp = cust.clone(); temp.setID(-1); temp.setType(1); writeDataToLog(id, cust.getKey(), temp); Trace.info("RM::newCustomer(" + cid + ") returns ID=" + cid); return cid; }
public ReturnTuple<Integer> newCustomer(int id, Timestamp timestamp) throws RemoteException, TransactionAbortedException, InvalidTransactionException { if (!isMaster) { System.out.println("Slave retransmitting newCustomer to master"); return this.getMaster().newCustomer(id, timestamp); } else { timestamp.stamp(); int rid = Integer.parseInt( String.valueOf(id) + String.valueOf(Calendar.getInstance().get(Calendar.MILLISECOND)) + String.valueOf(Math.round(Math.random() * 100 + 1))); NewCustomerWithIdRMICommand nc = new NewCustomerWithIdRMICommand(carGroup, flightGroup, roomGroup, id, rid); nc.setTimestampObject(timestamp); ReturnTuple<Integer> result = null; try { overseer.validTransaction(id); lm.Lock(id, Customer.getKey(rid), nc.getRequiredLock()); nc.execute(); result = new ReturnTuple<Integer>(rid, nc.success.timestamp); overseer.addCommandToTransaction(id, nc); } catch (DeadlockException d) { timestamp.stamp(); overseer.abort(id); timestamp.stamp(); throw new TransactionAbortedException(timestamp); } catch (TransactionAbortedException tae) { tae.t = timestamp; throw tae; } catch (InvalidTransactionException ite) { ite.t = timestamp; throw ite; } result.timestamp.stamp(); return result; } }
// Deletes customer from the database. public boolean deleteCustomer(int id, int customerID) throws RemoteException { Trace.info("RM::deleteCustomer(" + id + ", " + customerID + ") called"); Customer cust = (Customer) readData(id, Customer.getKey(customerID)); if (cust == null) { Trace.warn( "RM::deleteCustomer(" + id + ", " + customerID + ") failed--customer doesn't exist"); return false; } else { Customer temp = cust.clone(); // Increase the reserved numbers of all reservable items which the customer reserved. RMHashtable reservationHT = cust.getReservations(); for (Enumeration e = reservationHT.keys(); e.hasMoreElements(); ) { String reservedkey = (String) (e.nextElement()); ReservedItem reserveditem = cust.getReservedItem(reservedkey); Trace.info( "RM::deleteCustomer(" + id + ", " + customerID + ") has reserved " + reserveditem.getKey() + " " + reserveditem.getCount() + " times"); ReservableItem item = (ReservableItem) readData(id, reserveditem.getKey()); Trace.info( "RM::deleteCustomer(" + id + ", " + customerID + ") has reserved " + reserveditem.getKey() + "which is reserved" + item.getReserved() + " times and is still available " + item.getCount() + " times"); Flight tempItem = new Flight(Integer.parseInt(item.getLocation()), item.getCount(), item.getPrice()); tempItem.setReserved(item.getReserved()); tempItem.setType(0); item.setReserved(item.getReserved() - reserveditem.getCount()); item.setCount(item.getCount() + reserveditem.getCount()); if (readDataFromLog(id, item.getKey(), id) == null) writeDataToLog(id, item.getKey(), tempItem); } // remove the customer from the storage temp.setType(1); if (readDataFromLog(id, cust.getKey(), id) == null) writeDataToLog(id, cust.getKey(), temp); removeData(id, cust.getKey()); Trace.info("RM::deleteCustomer(" + id + ", " + customerID + ") succeeded"); return true; } // if }
// Deletes customer from the database. public ReturnTuple<Boolean> deleteCustomer(int id, int customerID, Timestamp timestamp) throws RemoteException, TransactionAbortedException, InvalidTransactionException { if (!isMaster) { System.out.println("Slave retransmitting deleteCustomer to master"); return this.getMaster().deleteCustomer(id, customerID, timestamp); } else { timestamp.stamp(); DeleteCustomerRMICommand dc = new DeleteCustomerRMICommand(carGroup, flightGroup, roomGroup, id, customerID); dc.setTimestampObject(timestamp); ReturnTuple<Boolean> result = null; try { overseer.validTransaction(id); lm.Lock(id, Customer.getKey(customerID), dc.getRequiredLock()); dc.execute(); result = dc.success; if (result.result) overseer.addCommandToTransaction(id, dc); } catch (DeadlockException d) { timestamp.stamp(); overseer.abort(id); timestamp.stamp(); throw new TransactionAbortedException(timestamp); } catch (TransactionAbortedException tae) { tae.t = timestamp; throw tae; } catch (InvalidTransactionException ite) { ite.t = timestamp; throw ite; } result.timestamp.stamp(); return result; } }
// Adds flight reservation to this customer. public ReturnTuple<Boolean> reserveFlight( int id, int customerID, int flightNum, Timestamp timestamp) throws RemoteException, TransactionAbortedException, InvalidTransactionException { if (!isMaster) { System.out.println("Slave retransmitting reserveFlight to master"); return this.getMaster().reserveFlight(id, customerID, flightNum, timestamp); } else { timestamp.stamp(); ReserveFlightRMICommand rf = new ReserveFlightRMICommand(flightGroup, id, customerID, flightNum); rf.setTimestampObject(timestamp); ReturnTuple<Boolean> result = null; try { overseer.validTransaction(id); lm.Lock(id, Customer.getKey(customerID), rf.getRequiredLock()); lm.Lock(id, Flight.getKey(flightNum), rf.getRequiredLock()); rf.execute(); result = rf.success; if (result.result) overseer.addCommandToTransaction(id, rf); } catch (DeadlockException d) { timestamp.stamp(); overseer.abort(id); timestamp.stamp(); throw new TransactionAbortedException(timestamp); } catch (TransactionAbortedException tae) { tae.t = timestamp; throw tae; } catch (InvalidTransactionException ite) { ite.t = timestamp; throw ite; } result.timestamp.stamp(); return result; } }
// I opted to pass in customerID instead. This makes testing easier public boolean newCustomer(int id, int customerID) throws RemoteException { Trace.info("INFO: RM::newCustomer(" + id + ", " + customerID + ") called"); Customer cust = (Customer) readData(id, Customer.getKey(customerID)); if (cust == null) { cust = new Customer(customerID); writeData(id, cust.getKey(), cust); Customer temp = cust.clone(); temp.setType(1); temp.setID(-1); writeDataToLog(id, cust.getKey(), temp); Trace.info("INFO: RM::newCustomer(" + id + ", " + customerID + ") created a new customer"); return true; } else { Trace.info( "INFO: RM::newCustomer(" + id + ", " + customerID + ") failed--customer already exists"); return false; } // else }
// return a bill public String queryCustomerInfo(int id, int customerID) throws RemoteException { Trace.info("RM::queryCustomerInfo(" + id + ", " + customerID + ") called"); Customer cust = (Customer) readData(id, Customer.getKey(customerID)); if (cust == null) { Trace.warn( "RM::queryCustomerInfo(" + id + ", " + customerID + ") failed--customer doesn't exist"); return ""; // NOTE: don't change this--WC counts on this value indicating a customer does not // exist... } else { String s = cust.printBill(); Trace.info("RM::queryCustomerInfo(" + id + ", " + customerID + "), bill follows..."); System.out.println(s); return s; } // if }
// Returns data structure containing customer reservation info. Returns null if the // customer doesn't exist. Returns empty RMHashtable if customer exists but has no // reservations. public RMHashtable getCustomerReservations(int id, int customerID) throws RemoteException { Trace.info("RM::getCustomerReservations(" + id + ", " + customerID + ") called"); Customer cust = (Customer) readData(id, Customer.getKey(customerID)); if (cust == null) { Trace.warn( "RM::getCustomerReservations failed(" + id + ", " + customerID + ") failed--customer doesn't exist"); return null; } else { return cust.getReservations(); } // if }
/* reserve an itinerary */ public ReturnTuple<Boolean> itinerary( int id, int customer, Vector flightNumbers, String location, boolean Car, boolean Room, Timestamp timestamp) throws RemoteException, TransactionAbortedException, InvalidTransactionException { if (!isMaster) { System.out.println("Slave retransmitting itinerary to master"); return this.getMaster() .itinerary(id, customer, flightNumbers, location, Car, Room, timestamp); } else { timestamp.stamp(); ItineraryRMICommand i = new ItineraryRMICommand( carGroup, flightGroup, roomGroup, id, customer, flightNumbers, location, Car, Room); i.setTimestampObject(timestamp); ReturnTuple<Boolean> result = null; try { overseer.validTransaction(id); lm.Lock(id, Customer.getKey(customer), i.getRequiredLock()); lm.Lock(id, ResImpl.Car.getKey(location), i.getRequiredLock()); lm.Lock(id, Hotel.getKey(location), i.getRequiredLock()); for (Object flightNo : flightNumbers) { int flightNum = Integer.parseInt((String) flightNo); lm.Lock(id, Flight.getKey(flightNum), i.getRequiredLock()); } i.execute(); result = i.success; if (result.result && !i.error()) overseer.addCommandToTransaction(id, i); } catch (DeadlockException d) { timestamp.stamp(); overseer.abort(id); timestamp.stamp(); throw new TransactionAbortedException(timestamp); } catch (TransactionAbortedException tae) { tae.t = timestamp; throw tae; } catch (InvalidTransactionException ite) { ite.t = timestamp; throw ite; } result.timestamp.stamp(); return result; } }
// return a bill public ReturnTuple<String> queryCustomerInfo(int id, int customerID, Timestamp timestamp) throws RemoteException, TransactionAbortedException, InvalidTransactionException { if (!isMaster) { System.out.println("Slave retransmitting queryCustomerInfo to master"); return this.getMaster().queryCustomerInfo(id, customerID, timestamp); } else { timestamp.stamp(); QueryCustomerInfoRMICommand qci = new QueryCustomerInfoRMICommand(carGroup, flightGroup, roomGroup, id, customerID); qci.setTimestampObject(timestamp); ReturnTuple<String> result = null; try { Vector<Integer> flightNos; Vector<String> locations; overseer.validTransaction(id); lm.Lock(id, Customer.getKey(customerID), qci.getRequiredLock()); qci.execute(); flightNos = qci.getCustomerFlightReservations(); for (int flightNo : flightNos) { lm.Lock(id, Flight.getKey(flightNo), qci.getRequiredLock()); } locations = qci.getCustomerRoomReservations(); for (String location : locations) { lm.Lock(id, Hotel.getKey(location), qci.getRequiredLock()); } locations = qci.getCustomerCarReservations(); for (String location : locations) { lm.Lock(id, Car.getKey(location), qci.getRequiredLock()); } qci.execute(); result = qci.customerInfo; } catch (DeadlockException d) { timestamp.stamp(); overseer.abort(id); timestamp.stamp(); throw new TransactionAbortedException(timestamp); } catch (TransactionAbortedException tae) { tae.t = timestamp; throw tae; } catch (InvalidTransactionException ite) { ite.t = timestamp; throw ite; } result.timestamp.stamp(); return result; } }
// reserve an item protected boolean reserveItem(int id, int customerID, String key, String location) { Trace.info( "RM::reserveItem( " + id + ", customer=" + customerID + ", " + key + ", " + location + " ) called"); // Read customer object if it exists (and read lock it) Customer cust = (Customer) readData(id, Customer.getKey(customerID)); if (cust == null) { Trace.warn( "RM::reserveCar( " + id + ", " + customerID + ", " + key + ", " + location + ") failed--customer doesn't exist"); return false; } // check if the item is available ReservableItem item = (ReservableItem) readData(id, key); if (item == null) { Trace.warn( "RM::reserveItem( " + id + ", " + customerID + ", " + key + ", " + location + ") failed--item doesn't exist"); return false; } else if (item.getCount() == 0) { Trace.warn( "RM::reserveItem( " + id + ", " + customerID + ", " + key + ", " + location + ") failed--No more items"); return false; } else { Flight tempItem = new Flight(Integer.parseInt(item.getLocation()), item.getCount(), item.getPrice()); tempItem.setReserved(item.getReserved()); Customer temp = cust.clone(); temp.setType(1); if (readDataFromLog(id, cust.getKey(), id) == null) { writeDataToLog(id, cust.getKey(), temp); } cust.reserve(key, location, item.getPrice()); writeData(id, cust.getKey(), cust); // decrease the number of available items in the storage item.setCount(item.getCount() - 1); item.setReserved(item.getReserved() + 1); if (readDataFromLog(id, item.getKey(), id) == null) { tempItem.setType(0); writeDataToLog(id, item.getKey(), tempItem); } Trace.info( "RM::reserveItem( " + id + ", " + customerID + ", " + key + ", " + location + ") succeeded"); return true; } }