/** * Test concurrent reader and writer (GH-458). * * <p><b>Test case:</b> * * <ol> * <li/>start a long running reader; * <li/>try to start a writer: it should time out; * <li/>stop the reader; * <li/>start the writer again: it should succeed. * </ol> * * @throws Exception error during request execution */ @Test @Ignore("There is no way to stop a query on the server!") public void testReaderWriter() throws Exception { final String readerQuery = "?query=(1%20to%20100000000000000)%5b.=1%5d"; final String writerQuery = "/test.xml"; final byte[] content = Token.token("<a/>"); final Get readerAction = new Get(readerQuery); final Put writerAction = new Put(writerQuery, content); final ExecutorService exec = Executors.newFixedThreadPool(2); // start reader exec.submit(readerAction); Performance.sleep(TIMEOUT); // delay in order to be sure that the reader has started // start writer Future<HTTPResponse> writer = exec.submit(writerAction); try { final HTTPResponse result = writer.get(TIMEOUT, TimeUnit.MILLISECONDS); if (result.status.isSuccess()) fail("Database modified while a reader is running"); throw new Exception(result.toString()); } catch (final TimeoutException e) { // writer is blocked by the reader: stop it writerAction.stop = true; } // stop reader readerAction.stop = true; // start the writer again writer = exec.submit(writerAction); assertEquals(HTTPCode.CREATED, writer.get().status); }
@Override public void execute(final GUI gui) { final DialogExport dialog = new DialogExport(gui); if (!dialog.ok()) return; final IOFile root = new IOFile(dialog.path()); // check if existing files will be overwritten if (root.exists()) { IO file = null; boolean overwrite = false; final Data d = gui.context.data(); final IntList il = d.resources.docs(); final int is = il.size(); for (int i = 0; i < is; i++) { file = root.merge(Token.string(d.text(il.get(i), true))); if (file.exists()) { if (overwrite) { // more than one file will be overwritten; check remaining tests file = null; break; } overwrite = true; } } if (overwrite) { // show message for overwriting files or directories final String msg = file == null ? FILES_REPLACE_X : FILE_EXISTS_X; if (file == null) file = root; if (!BaseXDialog.confirm(gui, Util.info(msg, file))) return; } } DialogProgress.execute(gui, new Export(root.path())); }
@Override public void execute(final GUI gui) { final int pre = gui.context.marked.pres[0]; final byte[] txt = ViewData.path(gui.context.data(), pre); // copy path to clipboard final Clipboard clip = Toolkit.getDefaultToolkit().getSystemClipboard(); clip.setContents(new StringSelection(Token.string(txt)), null); }
/** * Calculates the text offset and writes the text value. * * @param value value to be inlined * @param text text/attribute flag * @return inline value or text position * @throws IOException I/O exception */ private long textOff(final byte[] value, final boolean text) throws IOException { // inline integer values... final long v = Token.toSimpleInt(value); if (v != Integer.MIN_VALUE) return v | IO.OFFNUM; // store text final DataOutput store = text ? xout : vout; final long off = store.size(); final byte[] val = COMP.get().pack(value); store.writeToken(val); return val == value ? off : off | IO.OFFCOMP; }
@Override public void execute(final GUI gui) { final Nodes n = gui.context.marked; final DialogInsert insert = new DialogInsert(gui); if (!insert.ok()) return; final StringList sl = insert.result; final NodeType type = ANode.type(insert.kind); String item = Token.string(type.string()) + " { " + quote(sl.get(0)) + " }"; if (type == NodeType.ATT || type == NodeType.PI) { item += " { " + quote(sl.get(1)) + " }"; } else if (type == NodeType.ELM) { item += " { () }"; } gui.context.copied = null; gui.execute(new XQuery("insert node " + item + " into " + openPre(n, 0))); }
/** * Test concurrent writers (GH-458). * * <p><b>Test case:</b> * * <ol> * <li/>start several writers one after another; * <li/>all writers should succeed. * </ol> * * @throws Exception error during request execution */ @Test public void testMultipleWriters() throws Exception { final int count = 10; final String template = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<command xmlns=\"http://basex.org/rest\"><text><![CDATA[" + "ADD TO %1$d <node id=\"%1$d\"/>" + "]]></text></command>"; @SuppressWarnings("unchecked") final Future<HTTPResponse>[] tasks = new Future[count]; final ExecutorService exec = Executors.newFixedThreadPool(count); // start all writers (not at the same time, but still in parallel) for (int i = 0; i < count; i++) { final String command = String.format(template, i); tasks[i] = exec.submit(new Post("", Token.token(command))); } // check if all have finished successfully for (final Future<HTTPResponse> task : tasks) { assertEquals(HTTPCode.OK, task.get(TIMEOUT, TimeUnit.MILLISECONDS).status); } }