use of com.evolvedbinary.j8fu.tuple.Tuple2 in project exist by eXist-db.
the class BlobStoreImpl method add.
@Override
public Tuple2<BlobId, Long> add(final Txn transaction, final InputStream is) throws IOException {
if (state.get() != State.OPEN) {
throw new IOException("Blob Store is not open!");
}
// stage the BLOB file
final Tuple3<Path, Long, MessageDigest> staged = stage(is);
final BlobVacuum.RequestDeleteStagedBlobFile requestDeleteStagedBlobFile = new BlobVacuum.RequestDeleteStagedBlobFile(stagingDir, staged._1.getFileName().toString());
// register a callback to cleanup the staged BLOB file ONLY after commit+checkpoint
final JournalManager journalManager = database.getJournalManager().orElse(null);
if (journalManager != null) {
final DeleteStagedBlobFile cleanupStagedBlob = new DeleteStagedBlobFile(vacuumQueue, requestDeleteStagedBlobFile);
journalManager.listen(cleanupStagedBlob);
transaction.registerListener(cleanupStagedBlob);
}
final BlobId blobId = new BlobId(staged._3.getValue());
// if the blob entry does not exist, we exclusively compute it as STAGED.
BlobReference blobReference = references.computeIfAbsent(blobId, k -> new BlobReference(STAGED));
try {
while (true) {
if (blobReference.count.compareAndSet(STAGED, PROMOTING)) {
// write journal entries to the WAL
if (journalManager != null) {
try {
journalManager.journal(new StoreBlobFileLoggable(transaction.getId(), blobId, staged._1.getFileName().toString()));
journalManager.journal(new UpdateBlobRefCountLoggable(transaction.getId(), blobId, 0, 1));
// force WAL entries to disk!
journalManager.flush(true, true);
} catch (final JournalException e) {
references.remove(blobId);
throw new IOException(e);
}
}
// promote the staged blob
promote(staged);
if (journalManager == null) {
// no journal (or recovery)... so go ahead and schedule cleanup of the staged blob file
enqueueVacuum(vacuumQueue, requestDeleteStagedBlobFile);
}
// schedule disk persist of the new value
persistQueue.put(Tuple(blobId, blobReference, 1));
// update memory with the new value
blobReference.count.set(1);
// done!
return Tuple(blobId, staged._2);
}
final int count = blobReference.count.get();
// guard against a concurrent #add or #remove
if (count == PROMOTING || count == UPDATING_COUNT) {
// spin whilst another thread promotes the blob, or updates the reference count
// sleep a small time to save CPU
Thread.sleep(10);
continue;
}
// i.e. wait for the deletion of the blob to complete, and then we can add the blob again
if (count == DELETING) {
blobReference = references.computeIfAbsent(blobId, k -> new BlobReference(STAGED));
// loop again
continue;
}
// only increment the blob reference if the blob is active!
if (count >= 0 && blobReference.count.compareAndSet(count, UPDATING_COUNT)) {
// NOTE: we are the only thread that can be in this branch for the blobId
final int newCount = count + 1;
// write journal entries to the WAL
if (journalManager != null) {
try {
journalManager.journal(new UpdateBlobRefCountLoggable(transaction.getId(), blobId, count, newCount));
// force WAL entries to disk!
journalManager.flush(true, true);
} catch (final JournalException e) {
// restore the state of the blobReference first!
blobReference.count.set(count);
throw new IOException(e);
}
}
// persist the new value
persistQueue.put(Tuple(blobId, blobReference, newCount));
// update memory with the new value, and release other spinning threads
blobReference.count.set(newCount);
// done!
return Tuple(blobId, staged._2);
}
}
} catch (final InterruptedException e) {
// thrown by persistQueue.put or Thread.sleep
Thread.currentThread().interrupt();
throw new IOException(e);
}
}
use of com.evolvedbinary.j8fu.tuple.Tuple2 in project exist by eXist-db.
the class LocalCollectionManagementService method createCollection.
@Override
public Collection createCollection(final XmldbURI name, final Date created) throws XMLDBException {
final XmldbURI collName = resolve(name);
withDb((broker, transaction) -> {
try {
final org.exist.collections.Collection coll = broker.getOrCreateCollection(transaction, collName, Optional.ofNullable(created).map(c -> new Tuple2<>(null, c.getTime())));
try (final ManagedCollectionLock collectionLock = broker.getBrokerPool().getLockManager().acquireCollectionWriteLock(collName)) {
broker.saveCollection(transaction, coll);
}
return null;
} catch (final LockException | TriggerException e) {
throw new XMLDBException(ErrorCodes.VENDOR_ERROR, e.getMessage(), e);
}
});
return new LocalCollection(user, brokerPool, collection, collName);
}
use of com.evolvedbinary.j8fu.tuple.Tuple2 in project exist by eXist-db.
the class CollectionRemovalTest method initDB.
@Before
public void initDB() throws EXistException, PermissionDeniedException, IOException, SAXException, LockException {
final BrokerPool pool = existEmbeddedServer.getBrokerPool();
final TransactionManager transact = pool.getTransactionManager();
try (final DBBroker broker = pool.get(Optional.of(pool.getSecurityManager().getSystemSubject()));
final Txn transaction = transact.beginTransaction()) {
final int worldReadable = 0744;
final int worldForbidden = 0700;
/*
* Creates 3 collections: /db/test, /db/test/test2, /db/test/test2/test3 and /db/test/test2/test4,
* and stores one document into each.
* Collection /db/test/test2/test3 is only readable by the owner (i.e. admin user).
*/
final List<Tuple2<XmldbURI, Integer>> collectionUriAndModes = Arrays.asList(Tuple(TestConstants.TEST_COLLECTION_URI2, worldReadable), Tuple(TestConstants.TEST_COLLECTION_URI3, worldForbidden), Tuple(TestConstants.TEST_COLLECTION_URI2.append("test4"), worldReadable));
// creat collections
for (final Tuple2<XmldbURI, Integer> collectionUriAndMode : collectionUriAndModes) {
final XmldbURI collectionUri = collectionUriAndMode._1;
final int mode = collectionUriAndMode._2;
// create collection
final Collection collection = broker.getOrCreateCollection(transaction, collectionUri);
assertNotNull(collection);
final Permission perms = collection.getPermissions();
perms.setMode(mode);
broker.saveCollection(transaction, collection);
// store document
broker.storeDocument(transaction, XmldbURI.create("document.xml"), new StringInputSource(DATA), MimeType.XML_TYPE, collection);
}
transact.commit(transaction);
}
}
use of com.evolvedbinary.j8fu.tuple.Tuple2 in project exist by eXist-db.
the class AbstractXMLReaderSecurityTest method createTempSecretFile.
/**
* @return A tuple whose first item is the secret, and the second which is the path to a temporary file containing the secret
*/
protected Tuple2<String, Path> createTempSecretFile() throws IOException {
final Path file = Files.createTempFile("exist.XMLReaderSecurityTest", "topsecret");
final String randomSecret = generateRandomString(SECRET_LENGTH);
return new Tuple2<>(randomSecret, Files.write(file, randomSecret.getBytes(UTF_8)));
}
use of com.evolvedbinary.j8fu.tuple.Tuple2 in project exist by eXist-db.
the class AbstractTestRunner method executeQuery.
protected static Sequence executeQuery(final BrokerPool brokerPool, final Source query, final List<Function<XQueryContext, Tuple2<String, Object>>> externalVariableBindings) throws EXistException, PermissionDeniedException, XPathException, IOException, DatabaseConfigurationException {
final SecurityManager securityManager = requireNonNull(brokerPool.getSecurityManager(), "securityManager is null");
try (final DBBroker broker = brokerPool.get(Optional.of(securityManager.getSystemSubject()))) {
final XQueryPool queryPool = brokerPool.getXQueryPool();
CompiledXQuery compiledQuery = queryPool.borrowCompiledXQuery(broker, query);
try {
XQueryContext context;
if (compiledQuery == null) {
context = new XQueryContext(broker.getBrokerPool());
} else {
context = compiledQuery.getContext();
context.prepareForReuse();
}
// setup misc. context
context.setBaseURI(new AnyURIValue("/db"));
if (query instanceof FileSource) {
final Path queryPath = Paths.get(((FileSource) query).getPath().toAbsolutePath().toString());
if (Files.isDirectory(queryPath)) {
context.setModuleLoadPath(queryPath.toString());
} else {
context.setModuleLoadPath(queryPath.getParent().toString());
}
}
// declare variables for the query
for (final Function<XQueryContext, Tuple2<String, Object>> externalVariableBinding : externalVariableBindings) {
final Tuple2<String, Object> nameValue = externalVariableBinding.apply(context);
context.declareVariable(nameValue._1, nameValue._2);
}
final XQuery xqueryService = brokerPool.getXQueryService();
// compile or update the context
if (compiledQuery == null) {
compiledQuery = xqueryService.compile(context, query);
} else {
compiledQuery.getContext().updateContext(context);
context.getWatchDog().reset();
}
return xqueryService.execute(broker, compiledQuery, null);
} finally {
queryPool.returnCompiledXQuery(query, compiledQuery);
}
}
}
Aggregations