/***************************************************************************
* 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. *
***************************************************************************/
/* This file is part of VoltDB.
* Copyright (C) 2009 Vertica Systems Inc.
*
* 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 java.util.Arrays;
import org.apache.log4j.Logger;
import org.voltdb.*;
import edu.brown.benchmark.seats.SEATSConstants;
import edu.brown.benchmark.seats.util.ErrorType;
@ProcInfo(
partitionInfo = "RESERVATION.R_F_ID: 0"
)
public class FindOpenSeats extends VoltProcedure {
private static final Logger LOG = Logger.getLogger(FindOpenSeats.class);
private final VoltTable.ColumnInfo outputColumns[] = {
new VoltTable.ColumnInfo("F_ID", VoltType.BIGINT),
new VoltTable.ColumnInfo("SEAT", VoltType.INTEGER),
new VoltTable.ColumnInfo("PRICE", VoltType.FLOAT),
};
public final SQLStmt GetFlight = new SQLStmt(
"SELECT F_ID, F_AL_ID, F_DEPART_AP_ID, F_DEPART_TIME, F_ARRIVE_AP_ID, F_ARRIVE_TIME, " +
" F_BASE_PRICE, F_SEATS_TOTAL, F_SEATS_LEFT, " +
" (F_BASE_PRICE + (F_BASE_PRICE * (1 - (F_SEATS_LEFT / F_SEATS_TOTAL)))) AS F_PRICE " +
" FROM " + SEATSConstants.TABLENAME_FLIGHT +
" WHERE F_ID = ?"
);
public final SQLStmt GetSeats = new SQLStmt(
"SELECT R_ID, R_F_ID, R_SEAT " +
" FROM " + SEATSConstants.TABLENAME_RESERVATION +
" WHERE R_F_ID = ?"
);
public VoltTable[] run(long f_id) {
final boolean debug = LOG.isDebugEnabled();
// Empty seats bitmap
final long seatmap[] = new long[SEATSConstants.FLIGHTS_NUM_SEATS];
Arrays.fill(seatmap, -1);
voltQueueSQL(GetFlight, f_id);
voltQueueSQL(GetSeats, f_id);
final VoltTable[] results = voltExecuteSQL(true);
assert (results.length == 2);
// First calculate the seat price using the flight's base price
// and the number of seats that remaining
if (results[0].advanceRow() == false) {
throw new VoltAbortException(ErrorType.INVALID_FLIGHT_ID +
String.format(" Invalid flight #%d", f_id));
}
int col = 6;
double base_price = results[0].getDouble(col++); // F_BASE_PRICE
long seats_total = results[0].getLong(col++); // F_SEATS_TOTAL
long seats_left = results[0].getLong(col++); // F_SEATS_LEFT
double seat_price = results[0].getDouble(col++); // MATHS!
if (debug) {
// TODO: Figure out why this doesn't match the SQL
double _seat_price = base_price + (base_price * (1.0 - (seats_left/(double)seats_total)));
LOG.debug(String.format("Flight %d - SQL[%.2f] <-> JAVA[%.2f] [basePrice=%f, total=%d, left=%d]",
f_id, seat_price, _seat_price, base_price, seats_total, seats_left));
}
// Then build the seat map of the remaining seats
while (results[1].advanceRow()) {
long r_id = results[1].getLong(0);
int seatnum = (int)results[1].getLong(2);
if (debug)
LOG.debug(String.format("ROW fid %d rid %d seat %d", f_id, r_id, seatnum));
assert(seatmap[seatnum] == -1) : "Duplicate seat reservation: R_ID=" + r_id;
seatmap[seatnum] = 1; // results[1].getLong(1);
} // WHILE
int ctr = 0;
VoltTable returnResults = new VoltTable(outputColumns);
for (int i = 0; i < seatmap.length; ++i) {
if (seatmap[i] == -1) {
Object[] row = new Object[]{ f_id, i, seat_price };
returnResults.addRow(row);
if (ctr == SEATSConstants.FLIGHTS_NUM_SEATS) break;
}
} // FOR
// assert(seats_left == returnResults.getRowCount()) :
// String.format("Flight %d - Expected[%d] != Actual[%d]", f_id, seats_left, returnResults.getRowCount());
if (debug)
LOG.debug(String.format("Flight %d Open Seats:\n%s", f_id, returnResults));
return new VoltTable[]{ results[0], returnResults };
}
}