diff --git a/properties/benchmarks/articles.properties b/properties/benchmarks/articles.properties new file mode 100644 index 0000000000..949c4d2590 --- /dev/null +++ b/properties/benchmarks/articles.properties @@ -0,0 +1,6 @@ +## ------------------------------------------------------------ +## H-Store Benchmark Configuration Parameters +## ------------------------------------------------------------ + +builder = edu.brown.benchmark.articles.ArticlesProjectBuilder +datadir = src/benchmarks/edu/brown/benchmark/articles/data diff --git a/src/benchmarks/edu/brown/benchmark/articles/ArticlesClient.java b/src/benchmarks/edu/brown/benchmark/articles/ArticlesClient.java new file mode 100644 index 0000000000..b98fd975aa --- /dev/null +++ b/src/benchmarks/edu/brown/benchmark/articles/ArticlesClient.java @@ -0,0 +1,79 @@ +package edu.brown.benchmark.articles; +import java.io.IOException; +import java.util.Random; +import org.voltdb.client.*; +import edu.brown.api.BenchmarkComponent; + +public class ArticlesClient extends BenchmarkComponent { + + public static void main(String args[]) { + BenchmarkComponent.main(ArticlesClient.class, args, false); + } + + public ArticlesClient(String[] args) { + super(args); + for (String key : m_extraParams.keySet()) { + // TODO: Retrieve extra configuration parameters + } // FOR + } + + @Override + public void runLoop() { + try { + Client client = this.getClientHandle(); + Random rand = new Random(); + while (true) { + // Select a random transaction to execute and generate its input parameters + // The procedure index (procIdx) needs to the same as the array of procedure + // names returned by getTransactionDisplayNames() + int procIdx = rand.nextInt(ArticlesProjectBuilder.PROCEDURES.length); + String procName = ArticlesProjectBuilder.PROCEDURES[procIdx].getSimpleName(); + Object procParams[] = null; // TODO + + // Create a new Callback handle that will be executed when the transaction completes + Callback callback = new Callback(procIdx); + + // Invoke the stored procedure through the client handle. This is non-blocking + client.callProcedure(callback, procName, procIdx); + + // Check whether all the nodes are backed-up and this client should block + // before sending new requests. + client.backpressureBarrier(); + } // WHILE + } catch (NoConnectionsException e) { + // Client has no clean mechanism for terminating with the DB. + return; + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (IOException e) { + // At shutdown an IOException is thrown for every connection to + // the DB that is lost Ignore the exception here in order to not + // get spammed, but will miss lost connections at runtime + } + } + + private class Callback implements ProcedureCallback { + private final int idx; + + public Callback(int idx) { + this.idx = idx; + } + @Override + public void clientCallback(ClientResponse clientResponse) { + // Increment the BenchmarkComponent's internal counter on the + // number of transactions that have been completed + incrementTransactionCounter(clientResponse, this.idx); + } + } // END CLASS + + @Override + public String[] getTransactionDisplayNames() { + // Return an array of transaction names + String procNames[] = new String[ArticlesProjectBuilder.PROCEDURES.length]; + for (int i = 0; i < procNames.length; i++) { + procNames[i] = ArticlesProjectBuilder.PROCEDURES[i].getSimpleName(); + } + return (procNames); + } + } + diff --git a/src/benchmarks/edu/brown/benchmark/articles/ArticlesLoader.java b/src/benchmarks/edu/brown/benchmark/articles/ArticlesLoader.java new file mode 100644 index 0000000000..aeba0971ed --- /dev/null +++ b/src/benchmarks/edu/brown/benchmark/articles/ArticlesLoader.java @@ -0,0 +1,45 @@ +package edu.brown.benchmark.articles; +import org.voltdb.CatalogContext; +import org.voltdb.VoltTable; +import org.voltdb.catalog.*; +import org.voltdb.client.Client; + +import edu.brown.api.Loader; +import edu.brown.catalog.CatalogUtil; +import edu.brown.api.BenchmarkComponent; + +public class ArticlesLoader extends Loader{ + + public static void main(String args[]) throws Exception { + BenchmarkComponent.main(ArticlesLoader.class, args, true); + } + + public ArticlesLoader(String[] args) { + super(args); + for (String key : m_extraParams.keySet()) { + // TODO: Retrieve extra configuration parameters + } // FOR + } + + @Override + public void load() { + // The catalog contains all the information about the database (e.g., tables, columns, indexes) + // It is loaded from the benchmark's project JAR file + // Catalog + CatalogContext _catalog = this.getCatalogContext(); + Catalog catalog = _catalog.catalog; + + // Iterate over all of the Table handles in the catalog and generate + // tuples to upload into the database + for (Table catalog_tbl : CatalogUtil.getDatabase(catalog).getTables()) { + // TODO: Create an empty VoltTable handle and then populate it in batches to + // be sent to the DBMS + VoltTable table = CatalogUtil.getVoltTable(catalog_tbl); + + // Invoke the BenchmarkComponent's data loading method + // This will upload the contents of the VoltTable into the DBMS cluster + this.loadVoltTable(catalog_tbl.getName(), table); + } // FOR + } + } + diff --git a/src/benchmarks/edu/brown/benchmark/articles/ArticlesProjectBuilder.java b/src/benchmarks/edu/brown/benchmark/articles/ArticlesProjectBuilder.java new file mode 100644 index 0000000000..528742d07c --- /dev/null +++ b/src/benchmarks/edu/brown/benchmark/articles/ArticlesProjectBuilder.java @@ -0,0 +1,32 @@ +package edu.brown.benchmark.articles; +import org.voltdb.VoltProcedure; + +import edu.brown.benchmark.AbstractProjectBuilder; +import edu.brown.api.BenchmarkComponent; +import edu.brown.benchmark.articles.procedures.*; + +public class ArticlesProjectBuilder extends AbstractProjectBuilder{ + + // REQUIRED: Retrieved via reflection by BenchmarkController + public static final Class m_clientClass = ArticlesClient.class; + + // REQUIRED: Retrieved via reflection by BenchmarkController + public static final Class m_loaderClass = ArticlesLoader.class; + + public static final Class PROCEDURES[] = new Class[] { + GetArticle.class, + }; + public static final String PARTITIONING[][] = new String[][] { + // { "TABLE NAME", "PARTITIONING COLUMN NAME" } + {"TABLEA", "A_ID"}, + {"TABLEB", "B_A_ID"}, + }; + + @SuppressWarnings("unchecked") + public ArticlesProjectBuilder() { + super("Articles", ArticlesProjectBuilder.class, (Class[]) PROCEDURES, PARTITIONING); + + } + +} + diff --git a/src/benchmarks/edu/brown/benchmark/articles/articles-ddl.sql b/src/benchmarks/edu/brown/benchmark/articles/articles-ddl.sql new file mode 100644 index 0000000000..a4ca18e69b --- /dev/null +++ b/src/benchmarks/edu/brown/benchmark/articles/articles-ddl.sql @@ -0,0 +1,47 @@ +-- ================================================================ +-- USER +-- Represents users +-- u_id User ID +-- u_firstname User's first name +-- u_lastname User's last name +-- u_password User's password +-- u_email User's email +-- ================================================================ +CREATE TABLE USER ( + u_id BIGINT NOT NULL, + u_firstname VARCHAR(100), + u_lastname VARCHAR(100), + u_password VARCHAR(100), + u_email VARCHAR(100), + PRIMARY KEY (u_id) + ); +-- ================================================================ +-- ARTICLE +-- Represents articles +-- a_id ID +-- a_title Article's title +-- a_text Article's content +-- a_num_comments Number of comments on the article +-- ================================================================ +CREATE TABLE ARTICLES ( + a_id BIGINT NOT NULL, + a_title VARCHAR(100), + a_text VARCHAR(100), + a_num_comments BIGINT, + PRIMARY KEY (a_id) + ); +-- ================================================================ +-- COMMENTS +-- Represents comments provided by buyers +-- c_id Comment's ID +-- a_id Article's ID +-- u_id User's ID +-- c_text Actual comment text +-- ================================================================ +CREATE TABLE COMMENT ( + c_id BIGINT NOT NULL, + a_id BIGINT NOT NULL REFERENCES ARTICLES (a_id), + u_id BIGINT NOT NULL REFERENCES USERS (u_id), + c_text VARCHAR(100), + PRIMARY KEY (c_id) + ); \ No newline at end of file diff --git a/src/benchmarks/edu/brown/benchmark/articles/procedures/GetArticle.java b/src/benchmarks/edu/brown/benchmark/articles/procedures/GetArticle.java new file mode 100644 index 0000000000..d537965f5e --- /dev/null +++ b/src/benchmarks/edu/brown/benchmark/articles/procedures/GetArticle.java @@ -0,0 +1,13 @@ +package edu.brown.benchmark.articles.procedures; +import org.voltdb.*; + +public class GetArticle extends VoltProcedure{ + + public final SQLStmt GetArticle = new SQLStmt("SELECT * FROM ARTICLES WHERE A_ID = ? "); + + public VoltTable[] run(long a_id) { + voltQueueSQL(GetArticle, a_id); + return (voltExecuteSQL()); + } + +} diff --git a/src/frontend/edu/brown/utils/ProjectType.java b/src/frontend/edu/brown/utils/ProjectType.java index 7fe1355f36..7459700601 100644 --- a/src/frontend/edu/brown/utils/ProjectType.java +++ b/src/frontend/edu/brown/utils/ProjectType.java @@ -50,6 +50,7 @@ public enum ProjectType { VOTER("Voter", "edu.brown.benchmark.voter"), SMALLBANK("SmallBank", "edu.brown.benchmark.smallbank"), EXAMPLE("Example", "edu.brown.benchmark.example"), + ARTICLES ("Articles", "edu.brown.benchmark.articles"), TEST("Test", null), ;