/*************************************************************************** * Copyright (C) 2011 by H-Store Project * * Brown University * * Massachusetts Institute of Technology * * Yale University * * * * http://hstore.cs.brown.edu/ * * * * Permission is hereby granted, free of charge, to any person obtaining * * a copy of this software and associated documentation files (the * * "Software"), to deal in the Software without restriction, including * * without limitation the rights to use, copy, modify, merge, publish, * * distribute, sublicense, and/or sell copies of the Software, and to * * permit persons to whom the Software is furnished to do so, subject to * * the following conditions: * * * * The above copyright notice and this permission notice shall be * * included in all copies or substantial portions of the Software. * * * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR * * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * * OTHER DEALINGS IN THE SOFTWARE. * ***************************************************************************/ package edu.brown.benchmark.seats.procedures; import org.apache.log4j.Logger; import org.voltdb.ProcInfo; import org.voltdb.SQLStmt; import org.voltdb.VoltProcedure; import org.voltdb.VoltTable; import org.voltdb.VoltType; import org.voltdb.types.TimestampType; import edu.brown.benchmark.seats.SEATSConstants; import edu.brown.benchmark.seats.util.ErrorType; @ProcInfo( partitionInfo = "RESERVATION.R_F_ID: 2" ) public class NewReservation extends VoltProcedure { private static final Logger LOG = Logger.getLogger(NewReservation.class); public final SQLStmt GetFlight = new SQLStmt( "SELECT F_AL_ID, F_SEATS_LEFT, " + SEATSConstants.TABLENAME_AIRLINE + ".* " + " FROM " + SEATSConstants.TABLENAME_FLIGHT + ", " + SEATSConstants.TABLENAME_AIRLINE + " WHERE F_ID = ? AND F_AL_ID = AL_ID"); public final SQLStmt GetCustomer = new SQLStmt( "SELECT C_BASE_AP_ID, C_BALANCE, C_SATTR00 " + " FROM " + SEATSConstants.TABLENAME_CUSTOMER + " WHERE C_ID = ? "); public final SQLStmt CheckSeat = new SQLStmt( "SELECT R_ID " + " FROM " + SEATSConstants.TABLENAME_RESERVATION + " WHERE R_F_ID = ? and R_SEAT = ?"); public final SQLStmt CheckCustomer = new SQLStmt( "SELECT R_ID " + " FROM " + SEATSConstants.TABLENAME_RESERVATION + " WHERE R_F_ID = ? AND R_C_ID = ?"); public final SQLStmt UpdateFlight = new SQLStmt( "UPDATE " + SEATSConstants.TABLENAME_FLIGHT + " SET F_SEATS_LEFT = F_SEATS_LEFT - 1 " + " WHERE F_ID = ? "); public final SQLStmt UpdateCustomer = new SQLStmt( "UPDATE " + SEATSConstants.TABLENAME_CUSTOMER + " SET C_IATTR10 = C_IATTR10 + 1, " + " C_IATTR11 = C_IATTR11 + 1, " + " C_IATTR12 = ?, " + " C_IATTR13 = ?, " + " C_IATTR14 = ?, " + " C_IATTR15 = ? " + " WHERE C_ID = ? "); public final SQLStmt UpdateFrequentFlyer = new SQLStmt( "UPDATE " + SEATSConstants.TABLENAME_FREQUENT_FLYER + " SET FF_IATTR10 = FF_IATTR10 + 1, " + " FF_IATTR11 = ?, " + " FF_IATTR12 = ?, " + " FF_IATTR13 = ?, " + " FF_IATTR14 = ? " + " WHERE FF_C_ID = ? " + " AND FF_AL_ID = ?"); public final SQLStmt InsertReservation = new SQLStmt( "INSERT INTO " + SEATSConstants.TABLENAME_RESERVATION + " (" + " R_ID, " + " R_C_ID, " + " R_F_ID, " + " R_SEAT, " + " R_PRICE, " + " R_IATTR00, " + " R_IATTR01, " + " R_IATTR02, " + " R_IATTR03, " + " R_IATTR04, " + " R_IATTR05, " + " R_IATTR06, " + " R_IATTR07, " + " R_IATTR08, " + " R_CREATED, " + " R_UPDATED " + ") VALUES (" + " ?, " + // R_ID " ?, " + // R_C_ID " ?, " + // R_F_ID " ?, " + // R_SEAT " ?, " + // R_PRICE " ?, " + // R_ATTR00 " ?, " + // R_ATTR01 " ?, " + // R_ATTR02 " ?, " + // R_ATTR03 " ?, " + // R_ATTR04 " ?, " + // R_ATTR05 " ?, " + // R_ATTR06 " ?, " + // R_ATTR07 " ?, " + // R_ATTR08 " ?, " + // R_CREATED " ? " + // R_UPDATED ")"); public VoltTable[] run(long r_id, long c_id, long f_id, long seatnum, double price, long attrs[], TimestampType timestamp) { final boolean debug = LOG.isDebugEnabled(); assert(attrs.length == SEATSConstants.NEW_RESERVATION_ATTRS_SIZE); voltQueueSQL(GetFlight, f_id); voltQueueSQL(CheckSeat, f_id, seatnum); voltQueueSQL(CheckCustomer, f_id, c_id); final VoltTable[] initialResults = voltExecuteSQL(); assert(initialResults.length == 3); // Flight Information if (initialResults[0].advanceRow() == false) { throw new VoltAbortException(ErrorType.INVALID_FLIGHT_ID + String.format(" Invalid flight #%d", f_id)); } long airline_id = initialResults[0].getLong(0); long seats_left = initialResults[0].getLong(1); if (seats_left <= 0) { throw new VoltAbortException(ErrorType.NO_MORE_SEATS + String.format(" No more seats available for flight #%d", f_id)); } // Check for existing reservation if (initialResults[1].advanceRow()) { throw new VoltAbortException(ErrorType.SEAT_ALREADY_RESERVED + String.format(" Seat %d is already reserved on flight #%d", seatnum, f_id)); } // Or the customer trying to book themselves twice else if (initialResults[2].advanceRow()) { throw new VoltAbortException(ErrorType.CUSTOMER_ALREADY_HAS_SEAT + String.format(" Customer %d already owns on a reservations on flight #%d", c_id, f_id)); } if (c_id != VoltType.NULL_BIGINT) { voltQueueSQL(GetCustomer, c_id); VoltTable[] customerResults = voltExecuteSQL(); assert(customerResults.length == 1); // Customer Information if (customerResults[0].advanceRow() == false) { throw new VoltAbortException(ErrorType.INVALID_CUSTOMER_ID + String.format(" Invalid customer id: %d", c_id)); } } voltQueueSQL(InsertReservation, r_id, c_id, f_id, seatnum, price, attrs[0], attrs[1], attrs[2], attrs[3], attrs[4], attrs[5], attrs[6], attrs[7], attrs[8], timestamp, timestamp); voltQueueSQL(UpdateFlight, f_id); voltQueueSQL(UpdateCustomer, attrs[0], attrs[1], attrs[2], attrs[3], c_id); voltQueueSQL(UpdateFrequentFlyer, attrs[4], attrs[5], attrs[6], attrs[7], c_id, airline_id); // We don't care if we updated FrequentFlyer final VoltTable[] results = voltExecuteSQL(true); for (int i = 0; i < results.length - 1; i++) { if (results[i].getRowCount() != 1) { String msg = String.format("Failed to add reservation for flight #%d - No rows returned for %s", f_id, voltLastQueriesExecuted()[i]); if (debug) LOG.warn(msg); throw new VoltAbortException(ErrorType.VALIDITY_ERROR + " " + msg); } long updated = results[i].asScalarLong(); if (updated != 1) { String msg = String.format("Failed to add reservation for flight #%d - Updated %d records for %s", f_id, updated, voltLastQueriesExecuted()[i]); if (debug) LOG.warn(msg); throw new VoltAbortException(ErrorType.VALIDITY_ERROR + " " + msg); } } // FOR if (debug) LOG.debug(String.format("Reserved new seat on flight %d for customer %d [seatsLeft=%d]", f_id, c_id, seats_left-1)); return (results); } }