package org.basex.server; import org.basex.*; import org.basex.api.client.*; import org.basex.core.cmd.*; import org.basex.util.*; import org.junit.Test; /** * Testing concurrent XQUF statements on a single database. * * @author BaseX Team 2005-17, BSD License * @author Lukas Kircher */ public final class XQUFServerStressTest extends SandboxTest { /** * Runs the test. * @throws Exception exception */ @Test public void clients10runs10() throws Exception { run(10, 10); } /** * Runs the test. * @throws Exception exception */ @Test public void clients10runs50() throws Exception { run(10, 50); } /** * Runs the test. * @throws Exception exception */ @Test public void clients50runs10() throws Exception { run(50, 10); } /** * Runs the test. * @throws Exception exception */ @Test public void clients50runs50() throws Exception { run(50, 50); } /** * Runs the stress test. * @param clients number of clients * @param runs number of runs per client * @throws Exception exception */ private void run(final int clients, final int runs) throws Exception { // run server instance final BaseXServer server = createServer(); insert(clients, runs); delete(clients, runs); try(ClientSession cs = createClient()) { cs.execute(new DropDB(NAME)); } stopServer(server); } /** * Performs the query. * @param clients number of clients * @param runs number of runs * @throws Exception exception */ private static void insert(final int clients, final int runs) throws Exception { try(ClientSession cs = createClient()) { cs.execute(new CreateDB(NAME, "<doc/>")); } run("insert node <node/> into doc('" + NAME + "')/doc", clients, runs); } /** * Performs the query. * @param clients number of clients * @param runs number of runs * @throws Exception exception */ private static void delete(final int clients, final int runs) throws Exception { try(ClientSession cs = createClient()) { cs.execute(new CreateDB(NAME, "<doc/>")); final int c = 100 + clients * clients; cs.execute(new XQuery("for $i in 1 to " + c + " return insert node <node/> into doc('" + NAME + "')/doc")); } run("delete nodes (doc('" + NAME + "')/doc/node)[1]", clients, runs); } /** * Starts concurrent client operations. * @param query test query * @param clt number of clients * @param runs number of runs * @throws Exception exception */ private static void run(final String query, final int clt, final int runs) throws Exception { final Client[] cl = new Client[clt]; for(int i = 0; i < clt; ++i) cl[i] = new Client(query, runs); for(final Client c : cl) c.start(); for(final Client c : cl) c.join(); } /** Single client. */ static final class Client extends Thread { /** Client session. */ private final ClientSession session; /** Query to be executed by this client. */ final String query; /** Number of runs. */ private final int runs; /** * Default constructor. * @param query query string * @param runs number of runs * @throws Exception exception */ Client(final String query, final int runs) throws Exception { session = createClient(); this.query = query; this.runs = runs; } @Override public void run() { try { for(int i = 0; i < runs; ++i) { Performance.sleep(100); session.execute("xquery " + query); } session.close(); } catch(final Exception ex) { ex.printStackTrace(); } } } }