use of org.exist.dom.persistent.MutableDocumentSet in project exist by eXist-db.
the class FunIdRef method eval.
/**
* @see org.exist.xquery.Expression#eval(Sequence, Item)
*/
public Sequence eval(Sequence contextSequence, Item contextItem) throws XPathException {
if (context.getProfiler().isEnabled()) {
context.getProfiler().start(this);
context.getProfiler().message(this, Profiler.DEPENDENCIES, "DEPENDENCIES", Dependency.getDependenciesName(this.getDependencies()));
if (contextSequence != null) {
context.getProfiler().message(this, Profiler.START_SEQUENCES, "CONTEXT SEQUENCE", contextSequence);
}
if (contextItem != null) {
context.getProfiler().message(this, Profiler.START_SEQUENCES, "CONTEXT ITEM", contextItem.toSequence());
}
}
if (getArgumentCount() < 1) {
throw new XPathException(this, ErrorCodes.XPST0017, "function id requires one argument");
}
if (contextItem != null) {
contextSequence = contextItem.toSequence();
}
Sequence result;
boolean processInMem = false;
final Expression arg = getArgument(0);
final Sequence idrefval = arg.eval(contextSequence);
if (idrefval.isEmpty()) {
result = Sequence.EMPTY_SEQUENCE;
} else {
String nextId;
DocumentSet docs = null;
if (getArgumentCount() == 2) {
// second argument should be a node, whose owner document will be
// searched for the id
final Sequence nodes = getArgument(1).eval(contextSequence);
if (nodes.isEmpty()) {
throw new XPathException(this, ErrorCodes.XPDY0002, "no node or context item for fn:idref");
}
if (!Type.subTypeOf(nodes.itemAt(0).getType(), Type.NODE)) {
throw new XPathException(this, ErrorCodes.XPTY0004, "fn:idref() argument is not a node");
}
NodeValue node = (NodeValue) nodes.itemAt(0);
if (node.getImplementationType() == NodeValue.IN_MEMORY_NODE) // TODO : how to enforce this ?
// If $node, or the context item if the second argument is omitted,
// is a node in a tree whose root is not a document node [err:FODC0001] is raised processInMem = true;
{
processInMem = true;
} else {
MutableDocumentSet ndocs = new DefaultDocumentSet();
ndocs.add(((NodeProxy) node).getOwnerDocument());
docs = ndocs;
}
contextSequence = node;
} else if (contextSequence == null) {
throw new XPathException(this, ErrorCodes.XPDY0002, "no context item specified");
} else if (!Type.subTypeOf(contextSequence.getItemType(), Type.NODE)) {
throw new XPathException(this, ErrorCodes.XPTY0004, "context item is not a node");
} else {
if (contextSequence.isPersistentSet()) {
docs = contextSequence.toNodeSet().getDocumentSet();
} else {
processInMem = true;
}
}
if (processInMem) {
result = new ValueSequence();
} else {
result = new ExtArrayNodeSet();
}
for (final SequenceIterator i = idrefval.iterate(); i.hasNext(); ) {
nextId = i.nextItem().getStringValue();
if (nextId.isEmpty()) {
continue;
}
if (XMLNames.isNCName(nextId)) {
if (processInMem) {
getIdRef(result, contextSequence, nextId);
} else {
getIdRef((NodeSet) result, docs, nextId);
}
}
}
}
result.removeDuplicates();
if (context.getProfiler().isEnabled()) {
context.getProfiler().end(this, "", result);
}
return result;
}
use of org.exist.dom.persistent.MutableDocumentSet in project exist by eXist-db.
the class AbstractUpdateTest method update.
@Test
public final void update() throws EXistException, DatabaseConfigurationException, LockException, SAXException, PermissionDeniedException, IOException, ParserConfigurationException, XPathException {
BrokerPool.FORCE_CORRUPTION = true;
BrokerPool pool = startDb();
try {
final TransactionManager transact = pool.getTransactionManager();
try (final DBBroker broker = pool.get(Optional.of(pool.getSecurityManager().getSystemSubject()))) {
final DocumentImpl doc = init(broker, transact);
final MutableDocumentSet docs = new DefaultDocumentSet();
docs.add(doc);
doUpdate(broker, transact, docs);
pool.getJournalManager().get().flush(true, false);
}
BrokerPool.FORCE_CORRUPTION = false;
existEmbeddedServer.restart(false);
pool = existEmbeddedServer.getBrokerPool();
read(pool);
} finally {
existEmbeddedServer.stopDb(true);
}
}
use of org.exist.dom.persistent.MutableDocumentSet in project exist by eXist-db.
the class LocalXPathQueryService method beginProtected.
/**
* Execute all following queries in a protected environment.
* Protected means: it is guaranteed that documents referenced by the
* query or the result set are not modified by other threads
* until {@link #endProtected} is called.
*/
@Override
public void beginProtected() throws XMLDBException {
try {
int retries = BEGIN_PROTECTED_MAX_LOCKING_RETRIES == -1 ? -1 : BEGIN_PROTECTED_MAX_LOCKING_RETRIES - 2;
boolean deadlockCaught;
do {
reservedBroker = brokerPool.get(Optional.of(user));
deadlockCaught = false;
MutableDocumentSet docs = null;
try {
final org.exist.collections.Collection coll = reservedBroker.getCollection(collection.getPathURI());
lockedDocuments = new LockedDocumentMap();
docs = new DefaultDocumentSet();
coll.allDocs(reservedBroker, docs, true, lockedDocuments, LockMode.WRITE_LOCK);
return;
} catch (final LockException e) {
LOG.warn("Deadlock detected. Starting over again. Docs: {}; locked: {}. Cause: {}", docs.getDocumentCount(), lockedDocuments.size(), e.getMessage());
lockedDocuments.unlock();
reservedBroker.close();
deadlockCaught = true;
} catch (final PermissionDeniedException e) {
throw new XMLDBException(ErrorCodes.PERMISSION_DENIED, "Permission denied on document");
}
retries--;
} while (deadlockCaught && retries >= -1);
} catch (final EXistException e) {
if (reservedBroker != null) {
reservedBroker.close();
}
throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage());
}
throw new XMLDBException(ErrorCodes.VENDOR_ERROR, "Unable to beginProtected after " + BEGIN_PROTECTED_MAX_LOCKING_RETRIES + " retries");
}
use of org.exist.dom.persistent.MutableDocumentSet in project exist by eXist-db.
the class LocalXUpdateQueryService method updateResource.
@Override
public long updateResource(final String id, final String commands) throws XMLDBException {
return this.<Long>withDb((broker, transaction) -> {
final long start = System.currentTimeMillis();
final MutableDocumentSet docs = this.<MutableDocumentSet>read(broker, transaction, collection.getPathURI()).apply((collection, broker1, transaction1) -> {
MutableDocumentSet d = new DefaultDocumentSet();
if (id == null) {
d = collection.allDocs(broker1, d, true);
} else {
try {
final XmldbURI resourceURI = XmldbURI.xmldbUriFor(id);
try (final LockedDocument lockedDocument = collection.getDocumentWithLock(broker1, resourceURI, Lock.LockMode.READ_LOCK)) {
// NOTE: early release of Collection lock inline with Asymmetrical Locking scheme
collection.close();
final DocumentImpl doc = lockedDocument == null ? null : lockedDocument.getDocument();
if (doc == null) {
throw new XMLDBException(ErrorCodes.INVALID_RESOURCE, "Resource not found: " + id);
}
d.add(doc);
}
} catch (final URISyntaxException e) {
throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e);
}
}
return d;
});
try (final Reader reader = new StringReader(commands)) {
if (processor == null) {
processor = new XUpdateProcessor(broker, docs);
} else {
processor.setBroker(broker);
processor.setDocumentSet(docs);
}
final Modification[] modifications = processor.parse(new InputSource(reader));
long mods = 0;
for (Modification modification : modifications) {
mods += modification.process(transaction);
broker.flush();
}
if (LOG.isDebugEnabled()) {
LOG.debug("xupdate took {}ms.", System.currentTimeMillis() - start);
}
return mods;
} catch (final ParserConfigurationException | SAXException | LockException e) {
throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e);
} finally {
if (processor != null) {
processor.reset();
}
}
});
}
use of org.exist.dom.persistent.MutableDocumentSet in project exist by eXist-db.
the class UpdateRecoverTest method store.
private void store(final BrokerPool pool) throws EXistException, PermissionDeniedException, IOException, SAXException, LockException, ParserConfigurationException, XPathException {
final TransactionManager transact = pool.getTransactionManager();
try (final DBBroker broker = pool.get(Optional.of(pool.getSecurityManager().getSystemSubject()))) {
DocumentImpl doc;
try (final Txn transaction = transact.beginTransaction()) {
final Collection root = broker.getOrCreateCollection(transaction, TestConstants.TEST_COLLECTION_URI);
assertNotNull(root);
broker.saveCollection(transaction, root);
final Collection test2 = broker.getOrCreateCollection(transaction, TestConstants.TEST_COLLECTION_URI2);
assertNotNull(test2);
broker.saveCollection(transaction, test2);
broker.storeDocument(transaction, TestConstants.TEST_XML_URI, new StringInputSource(TEST_XML), MimeType.XML_TYPE, test2);
doc = test2.getDocument(broker, TestConstants.TEST_XML_URI);
// TODO : unlock the collection here ?
transact.commit(transaction);
}
try (final Txn transaction = transact.beginTransaction()) {
final MutableDocumentSet docs = new DefaultDocumentSet();
docs.add(doc);
final XUpdateProcessor proc = new XUpdateProcessor(broker, docs);
assertNotNull(proc);
// insert some nodes
for (int i = 1; i <= 200; i++) {
final String xupdate = "<xu:modifications version=\"1.0\" xmlns:xu=\"http://www.xmldb.org/xupdate\">" + " <xu:insert-before select=\"/products/product[1]\">" + " <product>" + " <description>Product " + i + "</description>" + " <price>" + (i * 2.5) + "</price>" + " <stock>" + (i * 10) + "</stock>" + " </product>" + " </xu:insert-before>" + "</xu:modifications>";
proc.setBroker(broker);
proc.setDocumentSet(docs);
final Modification[] modifications = proc.parse(new InputSource(new StringReader(xupdate)));
assertNotNull(modifications);
modifications[0].process(transaction);
proc.reset();
}
// add attribute
for (int i = 1; i <= 200; i++) {
final String xupdate = "<xu:modifications version=\"1.0\" xmlns:xu=\"http://www.xmldb.org/xupdate\">" + " <xu:append select=\"/products/product[" + i + "]\">" + " <xu:attribute name=\"id\">" + i + "</xu:attribute>" + " </xu:append>" + "</xu:modifications>";
proc.setBroker(broker);
proc.setDocumentSet(docs);
final Modification[] modifications = proc.parse(new InputSource(new StringReader(xupdate)));
assertNotNull(modifications);
modifications[0].process(transaction);
proc.reset();
}
// replace some
for (int i = 1; i <= 100; i++) {
final String xupdate = "<xu:modifications version=\"1.0\" xmlns:xu=\"http://www.xmldb.org/xupdate\">" + " <xu:replace select=\"/products/product[" + i + "]\">" + " <product id=\"" + i + "\">" + " <description>Replaced product</description>" + " <price>" + (i * 0.75) + "</price>" + " </product>" + " </xu:replace>" + "</xu:modifications>";
proc.setBroker(broker);
proc.setDocumentSet(docs);
final Modification[] modifications = proc.parse(new InputSource(new StringReader(xupdate)));
assertNotNull(modifications);
long mods = modifications[0].process(transaction);
proc.reset();
}
// remove some
for (int i = 1; i <= 100; i++) {
final String xupdate = "<xu:modifications version=\"1.0\" xmlns:xu=\"http://www.xmldb.org/xupdate\">" + " <xu:remove select=\"/products/product[last()]\"/>" + "</xu:modifications>";
proc.setBroker(broker);
proc.setDocumentSet(docs);
final Modification[] modifications = proc.parse(new InputSource(new StringReader(xupdate)));
assertNotNull(modifications);
modifications[0].process(transaction);
proc.reset();
}
for (int i = 1; i <= 100; i++) {
final String xupdate = "<xu:modifications version=\"1.0\" xmlns:xu=\"http://www.xmldb.org/xupdate\">" + " <xu:append select=\"/products\">" + " <product>" + " <xu:attribute name=\"id\"><xu:value-of select=\"count(/products/product) + 1\"/></xu:attribute>" + " <description>Product " + i + "</description>" + " <price>" + (i * 2.5) + "</price>" + " <stock>" + (i * 10) + "</stock>" + " </product>" + " </xu:append>" + "</xu:modifications>";
proc.setBroker(broker);
proc.setDocumentSet(docs);
final Modification[] modifications = proc.parse(new InputSource(new StringReader(xupdate)));
assertNotNull(modifications);
modifications[0].process(transaction);
proc.reset();
}
// rename element "description" to "descript"
String xupdate = "<xu:modifications version=\"1.0\" xmlns:xu=\"http://www.xmldb.org/xupdate\">" + " <xu:rename select=\"/products/product/description\">descript</xu:rename>" + "</xu:modifications>";
proc.setBroker(broker);
proc.setDocumentSet(docs);
Modification[] modifications = proc.parse(new InputSource(new StringReader(xupdate)));
assertNotNull(modifications);
modifications[0].process(transaction);
proc.reset();
// update attribute values
for (int i = 1; i <= 200; i++) {
xupdate = "<xu:modifications version=\"1.0\" xmlns:xu=\"http://www.xmldb.org/xupdate\">" + " <xu:update select=\"/products/product[" + i + "]/@id\">" + i + "u</xu:update>" + "</xu:modifications>";
proc.setBroker(broker);
proc.setDocumentSet(docs);
modifications = proc.parse(new InputSource(new StringReader(xupdate)));
assertNotNull(modifications);
long mods = modifications[0].process(transaction);
proc.reset();
}
// append new element to records
for (int i = 1; i <= 200; i++) {
xupdate = "<xu:modifications version=\"1.0\" xmlns:xu=\"http://www.xmldb.org/xupdate\">" + " <xu:append select=\"/products/product[" + i + "]\">" + " <date><xu:value-of select=\"current-dateTime()\"/></date>" + " </xu:append>" + "</xu:modifications>";
proc.setBroker(broker);
proc.setDocumentSet(docs);
modifications = proc.parse(new InputSource(new StringReader(xupdate)));
assertNotNull(modifications);
modifications[0].process(transaction);
proc.reset();
}
// update element content
for (int i = 1; i <= 200; i++) {
xupdate = "<xu:modifications version=\"1.0\" xmlns:xu=\"http://www.xmldb.org/xupdate\">" + " <xu:update select=\"/products/product[" + i + "]/price\">19.99</xu:update>" + "</xu:modifications>";
proc.setBroker(broker);
proc.setDocumentSet(docs);
modifications = proc.parse(new InputSource(new StringReader(xupdate)));
assertNotNull(modifications);
long mods = modifications[0].process(transaction);
proc.reset();
}
transact.commit(transaction);
}
}
}
Aggregations