If you want to achieve concurrently access on your databases, you need to use the client-server architecture.
Which sample did you mean? This one works for sure...
package org.basex.examples.server;
import org.basex.BaseXServer; import org.basex.core.BaseXException; import org.basex.server.ClientSession;
/** * This class demonstrates database access via the client/server architecture. * * @author Workgroup DBIS, University of Konstanz 2005-10, ISC License * @author BaseX Team */ public final class ServerCommands { /** Session reference. */ static ClientSession session;
/** * Runs the example code. * @param args (ignored) command-line arguments * @throws Exception exception */ public static void main(final String[] args) throws Exception {
System.out.println("=== ServerExample ===");
// ------------------------------------------------------------------------ // Start server on default port 1984 BaseXServer server = new BaseXServer();
// ------------------------------------------------------------------------ // Create a client session with host name, port, user name and password System.out.println("\n* Create a client session.");
session = new ClientSession("localhost", 1984, "admin", "admin");
// ------------------------------------------------------------------------ // Create a database System.out.println("\n* Create a database.");
session.execute("CREATE DB input etc/xml/input.xml");
// ------------------------------------------------------------------------ // Run a query System.out.println("\n* Run a query:");
System.out.println(session.execute("XQUERY //li"));
// ------------------------------------------------------------------------ // Faster version: specify an output stream and run a query System.out.println("\n* Run a query (faster):");
session.setOutputStream(System.out); session.execute("XQUERY //li");
// Reset output stream session.setOutputStream(null);
// ------------------------------------------------------------------------ // Run a query System.out.println("\n* Run a buggy query: ");
try { session.execute("XQUERY ///"); } catch(final BaseXException ex) { System.out.println(ex.getMessage()); }
// ------------------------------------------------------------------------ // Drop the database System.out.println("\n* Close and drop the database.");
session.execute("DROP DB input");
// ------------------------------------------------------------------------ // Close the client session System.out.println("\n* Close the client session.");
session.close();
// ------------------------------------------------------------------------ // Stop the server System.out.println("\n* Stop the server.");
server.stop(); } }
Andreas
Am 06.01.11 15:46, schrieb Charles F. Munat:
The latest version.
That's good to know. I haven't changed the query yet because I've been struggling to fix other bugs, but I should be fixing that today.
Do you think that performance would be better running client/server instead? If so, do you know any example code that is up-to-date with the latest version. The sample on the website doesn't work as it's currently written (at least it didn't for me).
Thanks,
Chas.
On 01/06/2011 8:08 AM, Andreas Weiler wrote:
Hi Chas,
what BaseX version are you running?
As a first hint, you don't have to open the database, when you are using the doc('database') function in your queries. So you don't have to close it, too.
Kind regards, Andreas
Am 06.01.11 05:20, schrieb Charles F. Munat:
So I went live with my embedded Base-X website and that has been a very painful learning experience.
I had been opening the DB on each request and running various queries, but assumed that the process would close it when it exited. That was bad, bad, bad. About an hour after I uploaded the new site (and after I'd gone to bed for a nine hour snooze), the site started serving a 500 error code because too many files were open.
OK, figured that out. So I created a singleton and with a method that opens the database in a try/catch block, and closes it in the finally block. Problem solved.
Sort of.
Apologies for the Scala, but here is the singleton code:
object DB { private val context = new Context() new org.basex.core.cmd.Set("dbpath", "/var/www/db").execute(context)
def executeQuery(query: String): String = { try { new Open("data").execute(context) new XQuery(query).execute(context) } catch { case _ => new CreateDB("data", "<data/>").execute(context) new XQuery(query).execute(context) } finally { new Close().execute(context) } } }
Try blocks in Scala return a value, so this method returns the output of the passed-in XQuery. Works like a charm.
When a request is received, my servlet (using Circumflex, a Scala web framework) creates a new RequestRouter class. A "get" method is called and passed the URL. Here is that class and method, which shows how I am calling the above DB object:
class Main extends RequestRouter { get(url) = { val query = Rx.getQuery(url) val output = DB.executeQuery(qry)
"<!DOCTYPE html>\n" + output } }
This passes the URL (url) to a method on another singleton (Rx.getQuery) which returns an XQuery based on the URL. That query is passed to DB.executeQuery which stores the output in the immutable variable "output." I then prepend a doctype and serve it as text/html.
This runs great... for about an hour. Then the server stops responding altogether. I've searched the logs, and I found this error:
java.io.IOException: Stream Closed java.io.RandomAccessFile.seek(Native Method) org.basex.io.TableDiskAccess.readBlock(TableDiskAccess.java:349) org.basex.io.TableDiskAccess.cursor(TableDiskAccess.java:326) org.basex.io.TableDiskAccess.read1(TableDiskAccess.java:92) org.basex.data.Data.kind(Data.java:305) org.basex.query.item.DBNode$4.next(DBNode.java:273) org.basex.query.path.IterStep$1.next(IterStep.java:45) org.basex.query.path.AxisPath.iter(AxisPath.java:437) org.basex.query.path.AxisPath.iter(AxisPath.java:406) org.basex.query.QueryContext.iter(QueryContext.java:306) org.basex.query.expr.For$1.init(For.java:127) org.basex.query.expr.For$1.next(For.java:92) org.basex.query.expr.FLWR$1.next(FLWR.java:63) org.basex.query.expr.Constr.<init>(Constr.java:53) org.basex.query.expr.CElem.item(CElem.java:112) org.basex.query.expr.CElem.item(CElem.java:1) org.basex.query.expr.CFrag.item(CFrag.java:1) org.basex.query.expr.ParseExpr.iter(ParseExpr.java:49) org.basex.query.QueryContext.iter(QueryContext.java:306) org.basex.query.expr.FLWR$1.next(FLWR.java:67) org.basex.query.iter.Iter.finish(Iter.java:65) org.basex.query.expr.ParseExpr.value(ParseExpr.java:73) org.basex.query.expr.Func.iter(Func.java:80) org.basex.query.QueryContext.iter(QueryContext.java:306) org.basex.query.expr.FuncCall.iter(FuncCall.java:76) org.basex.query.QueryContext.iter(QueryContext.java:306) org.basex.query.expr.TypeCase.iter(TypeCase.java:95) org.basex.query.expr.TypeSwitch.iter(TypeSwitch.java:74) org.basex.query.QueryContext.iter(QueryContext.java:306) org.basex.query.expr.Constr.<init>(Constr.java:52) org.basex.query.up.Replace.item(Replace.java:50) org.basex.query.expr.ParseExpr.iter(ParseExpr.java:49) org.basex.query.QueryContext.iter(QueryContext.java:306) org.basex.query.expr.ParseExpr.value(ParseExpr.java:73) org.basex.query.expr.GFLWOR.iter(GFLWOR.java:298) org.basex.query.expr.GFLWOR.iter(GFLWOR.java:291) org.basex.query.expr.GFLWOR.iter(GFLWOR.java:266) org.basex.query.QueryContext.iter(QueryContext.java:306) org.basex.query.expr.ParseExpr.value(ParseExpr.java:73) org.basex.query.up.Transform.iter(Transform.java:86) org.basex.query.QueryContext.iter(QueryContext.java:306) org.basex.query.expr.FLWR$1.next(FLWR.java:67) org.basex.query.iter.Iter.finish(Iter.java:65) org.basex.query.expr.ParseExpr.value(ParseExpr.java:73) org.basex.query.expr.Func.iter(Func.java:80) org.basex.query.QueryContext.iter(QueryContext.java:306) org.basex.query.expr.FuncCall.iter(FuncCall.java:76) org.basex.query.QueryContext.iter(QueryContext.java:306)
I'm guessing that this is some sort of race condition?
What is the trick to using Base-X in embedded mode? Do I need to be doing some sort of threading here? (I have managed to avoid learning anything about threads for 15 years now. Hate to ruin that record.)
Suggestions? Advice? At this point I'm seriously thinking of just running Base-X as a server and connecting through a connection pool, but I have to figure that out tonight, so if there's an easier answer, I'd sure love to know it.
Thanks again for all your help!
Chas. _______________________________________________ BaseX-Talk mailing list BaseX-Talk@mailman.uni-konstanz.de https://mailman.uni-konstanz.de/mailman/listinfo/basex-talk