package org.basex.examples.server;
import java.io.*;
import java.util.*;
import org.basex.*;
import org.basex.api.client.*;
/**
* This class connects multiple clients to one server instance.
* It sets up three clients with read/write access to the database.
* Database information will be shown before and after the
* clients have been run.
*
* @author BaseX Team 2005-17, BSD License
*/
public final class ServerConcurrency {
/**
* Main method of the example class.
* @param args (ignored) command-line arguments
* @throws Exception exception
*/
public static void main(final String... args) throws Exception {
new ServerConcurrency().run();
}
/**
* Runs the example code.
* @throws Exception on error.
*/
void run() throws Exception {
System.out.println("=== ServerConcurrency ===");
// Start server
System.out.println("\n* Start server.");
BaseXServer server = new BaseXServer();
// Create a client session with host name, port, user name and password
System.out.println("\n* Create a client session.");
try(ClientSession session =
new ClientSession("localhost", 1984, "admin", "admin", System.out)) {
// Create a database
System.out.println("\n* Create a database.");
send("CREATE DB input src/main/resources/xml/input.xml", session);
// Setup some clients that simultaneously read and write from the database
System.out.println("\n* Run one reader and two writers threads.");
ClientExample reader1 = new ClientExample("//li");
ClientExample writer1 = new ClientExample("insert node " +
"<li>new node</li> as last into /html/body//ul");
ClientExample writer2 = new ClientExample("insert node " +
"<new>One more</new> as last into /html/body");
// Let the clients run their query several times:
Thread.sleep(2000);
// Stop the clients
System.out.println("\n* Stop client threads.");
reader1.stop();
writer1.stop();
writer2.stop();
Thread.sleep(1000);
// Show modified database contents
System.out.println("\n* Show modified database contents:");
send("XQUERY //li", session);
// Drop the database
System.out.println("\n* Drop the database.");
send("DROP DB input", session);
// Close the client session
System.out.println("\n* Close the client session.");
}
// Stop the server
System.out.println("\n* Stop server.");
server.stop();
}
/**
* Processes the specified command on the server and returns the output
* or command info.
* @param cmd command to be executed
* @param cs client session reference
* @throws IOException I/O exception
*/
static void send(final String cmd, final ClientSession cs) throws IOException {
// Execute the command
cs.execute(cmd);
}
/**
* This class simulates a database client.
* Within a thread, a query is run several times until the thread is stopped.
*/
private final class ClientExample {
/** Set to false to stop the Client from running.*/
volatile boolean running = true;
/** Random sleep time generator.*/
final Random r = new Random();
/**
* Constructor.
* @param query query to be run
* @throws IOException I/O exception
*/
ClientExample(final String query) throws IOException {
// Create a client session and open database
final ClientSession session = new ClientSession("localhost", 1984, "admin", "admin");
send("OPEN input", session);
// Create and run the query thread
new Thread() {
@Override
public void run() {
try {
// Loop until the running flag has been invalidated
while(running) {
// Run the specified query
send("XQUERY " + query, session);
// Wait for a random time
Thread.sleep(r.nextInt(500));
}
} catch(Exception ex) {
ex.printStackTrace();
} finally {
// Close the client session
try {
session.close();
} catch(Exception ex) {
ex.printStackTrace();
}
}
}
}.start();
}
/**
* Quits the client thread.
*/
void stop() {
running = false;
}
}
}