Skip to content

Commit 1f70a05

Browse files
Merge pull request BaseXdb#834 from cfoster/next
[XQJ] Insert and further concurrency testing.
2 parents a2139c3 + 37e1f50 commit 1f70a05

File tree

4 files changed

+268
-17
lines changed

4 files changed

+268
-17
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
package net.xqj.basex.local;
2+
3+
import com.xqj2.XQConnection2;
4+
import static org.junit.Assert.*;
5+
import static net.xqj.basex.BaseXXQInsertOptions.*;
6+
7+
import org.junit.After;
8+
import org.junit.Before;
9+
import org.junit.Test;
10+
11+
import javax.xml.xquery.*;
12+
13+
/**
14+
* Testing XQJ insert
15+
*
16+
* @author Charles Foster
17+
*/
18+
public class InsertTest extends XQJBaseTest {
19+
20+
static final String DB = "xqj-test-database";
21+
static final String URI = "doc.xml";
22+
23+
@Before
24+
public void setUp() throws XQException {
25+
super.setUp();
26+
27+
XQExpression xqpe = xqc.createExpression();
28+
xqpe.executeCommand("CREATE DB "+DB);
29+
xqpe.executeCommand("SET DEFAULTDB true");
30+
xqpe.executeCommand("OPEN "+DB);
31+
xqpe.close();
32+
}
33+
34+
@After
35+
public void tearDown() throws XQException {
36+
XQExpression xqpe = xqc.createExpression();
37+
xqpe.executeCommand("DROP DB "+DB);
38+
super.tearDown();
39+
}
40+
41+
/**
42+
* Testing regular insert
43+
**/
44+
@Test
45+
public void testInsert() throws Throwable {
46+
XQConnection2 xqc2 = (XQConnection2)xqc;
47+
48+
xqc2.insertItem(URI, createDocument("<e>hello</e>"), null);
49+
assertTrue(docAvailable(URI));
50+
assertTrue(dbExists(DB, URI));
51+
}
52+
53+
/**
54+
* Testing insert via ADD strategy
55+
**/
56+
@Test
57+
public void testAdd() throws Throwable {
58+
XQConnection2 xqc2 = (XQConnection2)xqc;
59+
xqc2.insertItem(URI, createDocument("<e>a</e>"), options(ADD));
60+
61+
assertTrue(docAvailable(URI));
62+
assertTrue(dbExists(DB, URI));
63+
64+
xqc2.insertItem(URI, createDocument("<e>b</e>"), options(ADD));
65+
assertEquals(2, countUris(DB, URI));
66+
}
67+
68+
/**
69+
* Testing insert via REPLACE strategy
70+
**/
71+
@Test
72+
public void testReplace() throws Throwable {
73+
XQConnection2 xqc2 = (XQConnection2)xqc;
74+
xqc2.insertItem(URI, createDocument("<e>a</e>"), options(REPLACE));
75+
76+
assertTrue(docAvailable(URI));
77+
assertTrue(dbExists(DB, URI));
78+
79+
xqc2.insertItem(URI, createDocument("<e>b</e>"), options(REPLACE));
80+
assertEquals(1, countUris(DB, URI));
81+
}
82+
83+
/**
84+
* Testing insert via STORE strategy
85+
**/
86+
@Test
87+
public void testStore() throws Throwable {
88+
XQConnection2 xqc2 = (XQConnection2)xqc;
89+
xqc2.insertItem(URI, createDocument("<e>a</e>"), options(STORE));
90+
assertTrue(dbExists(DB, URI));
91+
92+
xqc2.insertItem(URI, createDocument("<e>b</e>"), options(STORE));
93+
assertEquals(1, countUris(DB, URI));
94+
}
95+
96+
// --------------------------------------------------------------------------
97+
// Helper methods
98+
// --------------------------------------------------------------------------
99+
100+
private boolean dbExists(String db, String uri) throws XQException {
101+
XQResultSequence rs =
102+
xqc.createExpression().executeQuery(
103+
"db:exists('"+db+"', '"+uri+"')"
104+
);
105+
rs.next();
106+
return rs.getBoolean();
107+
}
108+
109+
private int countUris(String db, String uri) throws XQException {
110+
XQResultSequence rs =
111+
xqc.createExpression().executeQuery(
112+
"xs:int(fn:count(db:list('"+db+"', '"+uri+"')))"
113+
);
114+
rs.next();
115+
return rs.getInt();
116+
}
117+
// --------------------------------------------------------------------------
118+
119+
}

basex-api/src/test/java/net/xqj/basex/local/XQItemAccessorTest.java

+7-8
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,15 @@
22

33
import static javax.xml.xquery.XQItemType.*;
44
import static org.junit.Assert.*;
5-
6-
import java.net.*;
7-
8-
import javax.xml.xquery.*;
9-
10-
import org.junit.*;
11-
import org.w3c.dom.*;
5+
import org.junit.Test;
6+
import java.net.URI;
7+
import javax.xml.xquery.XQException;
8+
import javax.xml.xquery.XQItemType;
9+
import javax.xml.xquery.XQResultSequence;
10+
import org.w3c.dom.Attr;
1211

1312
/**
14-
* Basic XQItemAccessor test.
13+
* Testing Basic XQItemAccessor functionality
1514
*
1615
* @author Charles Foster
1716
*/

basex-api/src/test/java/net/xqj/basex/local/XQJBaseTest.java

+42-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,14 @@
11
package net.xqj.basex.local;
22

3-
import javax.xml.xquery.*;
3+
import javax.xml.xquery.XQConnection;
4+
import javax.xml.xquery.XQException;
5+
import javax.xml.xquery.XQItem;
6+
import javax.xml.xquery.XQItemType;
7+
import javax.xml.xquery.XQResultSequence;
48

5-
import org.junit.*;
9+
import net.xqj.basex.BaseXXQInsertOptions;
10+
import org.junit.After;
11+
import org.junit.Before;
612

713
/**
814
* Base class for all XQJ local tests.
@@ -19,7 +25,7 @@ public abstract class XQJBaseTest {
1925
* Initializes a test.
2026
*/
2127
@Before
22-
public void setUp() {
28+
public void setUp() throws XQException {
2329
xqds = new BaseXXQDataSource();
2430
xqc = xqds.getConnection();
2531
}
@@ -32,4 +38,37 @@ public void setUp() {
3238
public void tearDown() throws XQException {
3339
xqc.close();
3440
}
41+
42+
/**
43+
* Creates a document-node(element()) with some text content
44+
* @param content the text() content the element() will contain
45+
* @return a XQItem representing a document-node(element()) item
46+
* @throws XQException
47+
*/
48+
public final XQItem createDocument(String content) throws XQException {
49+
return
50+
xqc.createItemFromDocument(
51+
content,
52+
null,
53+
xqc.createDocumentElementType(
54+
xqc.createElementType(null, XQItemType.XQBASETYPE_ANYTYPE)
55+
)
56+
);
57+
}
58+
59+
public boolean docAvailable(String uri) throws XQException {
60+
XQResultSequence rs =
61+
xqc.createExpression().executeQuery(
62+
"fn:doc-available('"+uri+"')"
63+
);
64+
rs.next();
65+
return rs.getBoolean();
66+
}
67+
68+
public final static BaseXXQInsertOptions options(int strategy) {
69+
BaseXXQInsertOptions options = new BaseXXQInsertOptions();
70+
options.setInsertStrategy(strategy);
71+
return options;
72+
}
73+
3574
}

basex-api/src/test/java/net/xqj/basex/local/XQJConcurrencyTest.java

+100-6
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,108 @@
11
package net.xqj.basex.local;
22

3+
import com.xqj2.XQConnection2;
4+
import static net.xqj.basex.BaseXXQInsertOptions.*;
5+
6+
import net.xqj.basex.BaseXXQInsertOptions;
37
import org.junit.Test;
8+
import static org.junit.Assert.*;
49

510
import javax.xml.xquery.XQConnection;
611
import javax.xml.xquery.XQException;
712
import javax.xml.xquery.XQExpression;
13+
import javax.xml.xquery.XQItem;
814
import javax.xml.xquery.XQResultSequence;
915
import java.util.ArrayList;
16+
import java.util.HashMap;
17+
import java.util.UUID;
18+
import java.util.concurrent.ArrayBlockingQueue;
19+
import java.util.concurrent.Future;
20+
import java.util.concurrent.ThreadPoolExecutor;
21+
import java.util.concurrent.TimeUnit;
1022

1123
/**
12-
* XQJ concurrency test.
24+
* Test XQJ concurrency, both reads and writes
1325
*
1426
* @author Charles Foster
1527
*/
1628
public class XQJConcurrencyTest extends XQJBaseTest {
17-
/** Thread count. */
18-
private static final int THREAD_COUNT = 256;
19-
/** Numbers of iterations. */
29+
30+
/** Number of threads used when executing read only queries */
31+
private static final int CONCURRENT_READ_THREADS = 256;
32+
33+
/** Numbers of iterations, when perform a ready query */
2034
private static final int ITERATE_TO = 1024;
2135

36+
/** Number of threads used when writing documents **/
37+
private static final int CONCURRENT_WRITE_THREADS = 12;
38+
39+
/** Total number of documents to insert when writing **/
40+
private static final int DOCS_TO_INSERT = CONCURRENT_WRITE_THREADS * 30;
41+
42+
/** BaseX insert strategy for inserting documents **/
43+
private static final BaseXXQInsertOptions INSERT_STRATEGY = options(REPLACE);
44+
2245
/**
23-
* Runs concurrency test.
46+
* Runs read concurrency test.
2447
* @throws Throwable any exception or error
2548
*/
2649
@Test
2750
public void testConcurrentXQuery1to1024() throws Throwable {
2851
final ArrayList<SimpleQueryThread> sqtList = new ArrayList<SimpleQueryThread>();
2952

30-
for(int i = 0; i < THREAD_COUNT; i++)
53+
for(int i = 0; i < CONCURRENT_READ_THREADS; i++)
3154
sqtList.add(new SimpleQueryThread());
3255

3356
for(final SimpleQueryThread s : sqtList) s.start();
3457
for(final SimpleQueryThread s : sqtList) s.join();
3558
for(final SimpleQueryThread s : sqtList) if(s.thrown != null) throw s.thrown;
3659
}
3760

61+
/**
62+
* Runs insert concurrency test.
63+
*/
64+
@Test
65+
public void testConcurrentInsert() throws Exception {
66+
67+
XQExpression xqpe = xqc.createExpression();
68+
69+
try
70+
{
71+
xqpe.executeCommand("CREATE DB xqj-concurrent-insert-test");
72+
xqpe.executeCommand("OPEN xqj-concurrent-insert-test");
73+
xqpe.executeCommand("SET DEFAULTDB true");
74+
75+
HashMap<String, XQItem> docs = new HashMap<String, XQItem>();
76+
77+
ThreadPoolExecutor tpe =
78+
new ThreadPoolExecutor(
79+
CONCURRENT_WRITE_THREADS, CONCURRENT_WRITE_THREADS, 4l,
80+
TimeUnit.SECONDS,
81+
new ArrayBlockingQueue<Runnable>(CONCURRENT_READ_THREADS),
82+
new ThreadPoolExecutor.CallerRunsPolicy());
83+
84+
ArrayList<Future> futures = new ArrayList<Future>();
85+
86+
for(int i=0;i<DOCS_TO_INSERT;i++) {
87+
String uri = i + "-" + UUID.randomUUID().toString() + ".xml";
88+
XQItem item = createDocument("<e>" + uri + "</e>");
89+
docs.put(uri, item);
90+
}
91+
92+
for(String uri : docs.keySet())
93+
futures.add(tpe.submit(new InsertItemThread(uri, docs.get(uri))));
94+
95+
for(Future future : futures)
96+
future.get();
97+
98+
for(String uri : docs.keySet())
99+
assertTrue(docAvailable(uri));
100+
}
101+
finally {
102+
xqpe.executeCommand("DROP DB xqj-concurrent-insert-test");
103+
}
104+
}
105+
38106
/**
39107
* Query Thread.
40108
*/
@@ -44,6 +112,7 @@ private class SimpleQueryThread extends Thread {
44112

45113
@Override
46114
public void run() {
115+
47116
XQConnection newConnection = null;
48117

49118
try {
@@ -76,6 +145,31 @@ public void run() {
76145
}
77146
}
78147

148+
private class InsertItemThread extends Thread {
149+
150+
/** uri of document being inserted **/
151+
private final String uri;
152+
153+
/** content of document being inserted **/
154+
private final XQItem item;
155+
156+
public InsertItemThread(String uri, XQItem item) {
157+
this.uri = uri;
158+
this.item = item;
159+
}
160+
161+
@Override
162+
public void run() {
163+
try {
164+
XQConnection2 xqc2 = (XQConnection2)xqc;
165+
xqc2.insertItem(uri, item, INSERT_STRATEGY);
166+
} catch(final Throwable th) {
167+
// a JUnit assertion WILL fail later because of this happening.
168+
th.printStackTrace();
169+
}
170+
}
171+
}
172+
79173
/**
80174
* Closes a connection.
81175
* @param conn connection to be closed

0 commit comments

Comments
 (0)