/******************************************************************************* * oltpbenchmark.com * * Project Info: http://oltpbenchmark.com * Project Members: Carlo Curino <carlo.curino@gmail.com> * Evan Jones <ej@evanjones.ca> * DIFALLAH Djellel Eddine <djelleleddine.difallah@unifr.ch> * Andy Pavlo <pavlo@cs.brown.edu> * CUDRE-MAUROUX Philippe <philippe.cudre-mauroux@unifr.ch> * Yang Zhang <yaaang@gmail.com> * * This library is free software; you can redistribute it and/or modify it under the terms * of the GNU General Public License as published by the Free Software Foundation; * either version 3.0 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU Lesser General Public License for more details. ******************************************************************************/ package edu.brown.benchmark.wikipedia.procedures; import org.voltdb.ProcInfo; import org.voltdb.VoltProcedure; import org.voltdb.SQLStmt; import org.voltdb.VoltTable; import org.voltdb.types.TimestampType; import edu.brown.benchmark.wikipedia.WikipediaConstants; @ProcInfo( partitionInfo = "PAGE.PAGE_ID: 0", singlePartition = false ) public class UpdatePage extends VoltProcedure { // ----------------------------------------------------------------- // STATEMENTS // ----------------------------------------------------------------- public SQLStmt selectLastPageRevision = new SQLStmt( "SELECT page_latest FROM " + WikipediaConstants.TABLENAME_PAGE + " WHERE page_id = ?" ); public SQLStmt insertText = new SQLStmt( "INSERT INTO " + WikipediaConstants.TABLENAME_TEXT + " (" + "old_id, " + "old_page, " + "old_text, " + "old_flags" + ") VALUES (" + "?, " + // old_id "?, " + // old_page "?, " + // old_text "?" + // old_flags ")" ); public SQLStmt insertRevision = new SQLStmt( "INSERT INTO " + WikipediaConstants.TABLENAME_REVISION + " (" + "rev_id," + "rev_page, " + "rev_text_id, " + "rev_comment, " + "rev_minor_edit, " + "rev_user, " + "rev_user_text, " + "rev_timestamp, " + "rev_deleted, " + "rev_len, " + "rev_parent_id" + ") VALUES (" + "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?" + ")" ); public SQLStmt updatePage = new SQLStmt( "UPDATE " + WikipediaConstants.TABLENAME_PAGE + " SET page_latest = page_latest + 1, " + " page_touched = ?, " + " page_is_new = 0, " + " page_is_redirect = 0, " + " page_len = ? " + " WHERE page_id = ?" ); public SQLStmt insertRecentChanges = new SQLStmt( "INSERT INTO " + WikipediaConstants.TABLENAME_RECENTCHANGES + " (" + "rc_id, " + "rc_timestamp, " + "rc_cur_time, " + "rc_namespace, " + "rc_page, " + "rc_type, " + "rc_minor, " + "rc_cur_id, " + "rc_user, " + "rc_user_text, " + "rc_comment, " + "rc_this_oldid, " + "rc_last_oldid, " + "rc_bot, " + "rc_moved_to_ns, " + "rc_moved_to_title, " + "rc_ip, " + "rc_old_len, " + "rc_new_len " + ") VALUES (" + "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?" + ")" ); public SQLStmt selectWatchList = new SQLStmt( "SELECT wl_user FROM " + WikipediaConstants.TABLENAME_WATCHLIST + " WHERE wl_page = ?" + " AND wl_namespace = ?" + " AND wl_user != ?" + " AND wl_notificationtimestamp = ?" ); public SQLStmt updateWatchList = new SQLStmt( "UPDATE " + WikipediaConstants.TABLENAME_WATCHLIST + " SET wl_notificationtimestamp = ? " + " WHERE wl_page = ?" + " AND wl_namespace = ?" + " AND wl_user = ?" ); public SQLStmt selectUser = new SQLStmt( "SELECT * FROM " + WikipediaConstants.TABLENAME_USER + " WHERE user_id = ?" ); public SQLStmt insertLogging = new SQLStmt( "INSERT INTO " + WikipediaConstants.TABLENAME_LOGGING + " (" + "log_id," + "log_type, " + "log_action, " + "log_timestamp, " + "log_user, " + "log_namespace, " + "log_page, " + "log_comment, " + "log_params, " + "log_user_text " + ") VALUES (" + "?," + // log_id "?," + // log_type "?," + // log_action "?," + // log_timestamp "?," + // log_user "?," + // log_namespace "?," + // log_page "''," + // log_comment "?," + // log_params "?" + // log_user_text ")" ); public SQLStmt updateUserEdit = new SQLStmt( "UPDATE " + WikipediaConstants.TABLENAME_USER + " SET user_editcount=user_editcount+1" + " WHERE user_id = ?" ); public SQLStmt updateUserTouched = new SQLStmt( "UPDATE " + WikipediaConstants.TABLENAME_USER + " SET user_touched = ?" + " WHERE user_id = ?" ); // ----------------------------------------------------------------- // RUN // ----------------------------------------------------------------- public long run(long pageId, int textId, int pageNamespace, String pageText, int userId, String userIp, String userText, int revisionId, String revComment, int revMinorEdit) { boolean adv; VoltTable rs[] = null; final TimestampType timestamp = new TimestampType(); // Get the next id from the PAGE voltQueueSQL(selectLastPageRevision, pageId); rs = voltExecuteSQL(); int nextId = (int)rs[0].asScalarLong() + 1; // INSERT NEW TEXT voltQueueSQL(insertText, nextId, pageId, pageText, "utf-8"); rs = voltExecuteSQL(); adv = rs[0].advanceRow(); assert(adv) : "Problem inserting new tuples in table text"; int nextTextId = (int)rs[0].getLong(0); // INSERT NEW REVISION voltQueueSQL(insertRevision, nextId, pageId, nextTextId, revComment, revMinorEdit, userId, userText, timestamp, 0, pageText.length(), revisionId); rs = voltExecuteSQL(); adv = rs[0].advanceRow(); // I'm removing AND page_latest = "+a.revisionId+" from the query, since // it creates sometimes problem with the data, and page_id is a PK // anyway voltQueueSQL(updatePage, timestamp, pageText.length(), pageId); voltQueueSQL(insertRecentChanges, nextId, timestamp, new TimestampType(), pageNamespace, pageId, 0, 0, pageId, userId, userText, revComment, nextTextId, textId, 0, 0, "", userIp, pageText.length(), pageText.length()); // SELECT WATCHING USERS voltQueueSQL(selectWatchList, pageId, pageNamespace, userId, null); rs = voltExecuteSQL(); // ===================================================================== // UPDATING WATCHLIST: txn3 (not always, only if someone is watching the // page, might be part of txn2) // ===================================================================== if (rs[0].getRowCount() > 0) { // NOTE: this commit is skipped if none is watching the page, and // the transaction merge with the following one while (rs[0].advanceRow()) { int otherUserId = (int)rs[0].getLong(0); voltQueueSQL(updateWatchList, timestamp, pageId, pageNamespace, otherUserId); voltExecuteSQL(); } // WHILE // ===================================================================== // UPDATING USER AND LOGGING STUFF: txn4 (might still be part of // txn2) // ===================================================================== // This seems to be executed only if the page is watched, and once // for each "watcher" rs[0].resetRowPosition(); while (rs[0].advanceRow()) { int otherUserId = (int)rs[0].getLong(0); voltQueueSQL(selectUser, otherUserId); } // WHILE rs = voltExecuteSQL(); while (rs[0].advanceRow()) { // Nothing to do } // WHILE } // This is always executed, sometimes as a separate transaction, // sometimes together with the previous one long logId = pageId | ((long)nextId)<<32; String logParams = String.format("%d -- %d -- %d", nextId, revisionId, 1); voltQueueSQL(insertLogging, logId, // log_id WikipediaConstants.UPDATEPAGE_LOG_TYPE, // log_type WikipediaConstants.UPDATEPAGE_LOG_ACTION, // log_action timestamp, // log_timestamp userId, // log_user pageNamespace, // log_namespace pageId, // log_page logParams, // log_params userText); // log_user_text voltQueueSQL(updateUserEdit, userId); voltQueueSQL(updateUserTouched, timestamp, userId); voltExecuteSQL(true); return (1); } }