Search in sources :

Example 1 with CasHolder

use of de.tudarmstadt.ukp.clarin.webanno.api.dao.casstorage.CasHolder in project webanno by webanno.

the class CasStorageServiceImpl method deleteCas.

@Override
public boolean deleteCas(SourceDocument aDocument, String aUsername) throws IOException, CasSessionException {
    try (WithExclusiveAccess access = new WithExclusiveAccess(aDocument, aUsername)) {
        boolean fileWasDeleted = new File(getAnnotationFolder(aDocument), aUsername + ".ser").delete();
        // Drop the CAS from the shared CAS it doesn't ghost around. Also set the deleted flag
        // in the holder in case anybody might still be holding on to the holder and needs to
        // know that CAS was deleted.
        CasKey key = new CasKey(aDocument, aUsername);
        CasHolder sharedCasHolder = sharedAccessCache.getIfPresent(key);
        if (sharedCasHolder != null) {
            sharedCasHolder.setDeleted(true);
        }
        sharedAccessCache.invalidate(key);
        // Drop the CAS from the exclusive access pool. This is done my marking it as deleted
        // and then releasing it (returning it to the pool). Upon return, the deleted flag
        // causes the CAS to be invalidated and dropped from the pool.
        exclusiveAccessHolders.forEach(h -> {
            // Must use the forEach here because stream() is not synchronized!
            if (Objects.equals(h.getKey(), key)) {
                h.setDeleted(true);
            }
        });
        access.release();
        // Drop the CAS from the current session
        // This must happen after the call to access.release() because access.release() tries
        // to fetch the CAS from the session if WithExclusiveAccess did not borrow it itself
        CasStorageSession.get().remove(aDocument.getId(), aUsername);
        return fileWasDeleted;
    }
}
Also used : CasHolder(de.tudarmstadt.ukp.clarin.webanno.api.dao.casstorage.CasHolder) CasKey(de.tudarmstadt.ukp.clarin.webanno.api.dao.casstorage.CasKey) File(java.io.File)

Example 2 with CasHolder

use of de.tudarmstadt.ukp.clarin.webanno.api.dao.casstorage.CasHolder in project webanno by webanno.

the class CasStorageServiceImpl method readOrCreateCas.

@Override
public CAS readOrCreateCas(SourceDocument aDocument, String aUsername, CasUpgradeMode aUpgradeMode, CasProvider aSupplier, CasAccessMode aAccessMode) throws IOException, CasSessionException {
    CasStorageSession session = CasStorageSession.get();
    // If the CAS is already present in the current session and the access mode is compatible
    // with the requested access mode, then we can return it immediately
    // THOUGHT: As it is written now - if the access more already recorded in the session
    // is insufficient, the access mode is upgraded because we simply continue after this
    // IF-clause. I am not entirely sure this is valid.
    // Case 1) CAS was added during the current session - the holder in the session is
    // replaced with an exclusive access CAS and when the session is closed, it is released.
    // Case 2) CAS was added during a parent session - the new exclusive access holder is added
    // to the current session and released as the current session is closed. The parent session
    // then still has the previously obtained read-only CAS - which at this point might be
    // stale if the CAS was changed during the exclusive access period
    Optional<SessionManagedCas> mCas = session.getManagedState(aDocument.getId(), aUsername);
    if (mCas.isPresent() && mCas.get().getMode().alsoPermits(aAccessMode)) {
        return mCas.get().getCas();
    }
    // If the CAS is not yet in the session, then we must get hold of it somehow...
    CasHolder casHolder;
    // If exclusive access is requested, then we check the CAS out of the exclusive access pool
    if (EXCLUSIVE_WRITE_ACCESS.equals(aAccessMode)) {
        CasKey key = null;
        CasHolder holder = null;
        try {
            log.trace("CAS storage session [{}]: trying to borrow CAS [{}]@[{}]({})", session.hashCode(), aUsername, aDocument.getName(), aDocument.getId());
            key = new CasKey(aDocument, aUsername);
            holder = borrowCas(key);
            // load it
            if (!holder.isCasSet()) {
                CasKey finalKey = key;
                CasHolder finalHolder = holder;
                CAS cas;
                // exclusive lock in CAS in readOrCreateUnmanagedCas
                try (CasStorageSession loaderSession = CasStorageSession.openNested(true)) {
                    SessionManagedCas mLoaderCas = loaderSession.add(aDocument.getId(), aUsername, EXCLUSIVE_WRITE_ACCESS, holder);
                    // Do not try to release the CAS when the loader session closes because in
                    // fact we won't even have set the CAS in the holder by then
                    mLoaderCas.setReleaseOnClose(false);
                    cas = readOrCreateUnmanagedCas(aDocument, aUsername, aSupplier, aUpgradeMode);
                }
                holder.setCas(cas);
                // Hook up releasing of the CAS when CAS.release() is called via the
                // CasStorageSession
                ((CASImpl) getRealCas(cas)).setOwner(_cas -> returnBorrowedCas(_cas, finalKey, finalHolder));
                log.trace("CAS storage session [{}]: borrowed CAS [{}] for [{}]@[{}]({}) loaded from storage", session.hashCode(), holder.getCasHashCode(), aUsername, aDocument.getName(), aDocument.getId());
            } else {
                log.trace("CAS storage session [{}]: borrowed CAS [{}] for [{}]@[{}]({}) was already in memory", session.hashCode(), holder.getCasHashCode(), aUsername, aDocument.getName(), aDocument.getId());
                transferCasOwnershipToCurrentThread(holder.getCas());
                repairAndUpgradeCasIfRequired(aDocument, aUsername, holder.getCas(), aUpgradeMode, ISOLATED_SESSION);
            }
            casHolder = holder;
        } catch (Exception e) {
            // If there was an exception, we need to return the CAS to the pool
            if (key != null && holder != null) {
                log.trace("CAS storage session [{}]: returning borrowed CAS [{}] for [{}]@[{}]({}) after failure to load CAS", session.hashCode(), holder.getCasHashCode(), aUsername, aDocument.getName(), aDocument.getId());
                try {
                    exclusiveAccessPool.returnObject(key, holder);
                    logExclusiveAccessHolders();
                } catch (Exception e1) {
                    log.error("Unable to return CAS to exclusive access pool", e1);
                }
            }
            casHolder = new CasHolder(key, e);
        }
    } else // else if shared read access is requested, then we try fetching it from the shared cache
    if (SHARED_READ_ONLY_ACCESS.equals(aAccessMode)) {
        if (!AUTO_CAS_UPGRADE.equals(aUpgradeMode)) {
            throw new IllegalArgumentException("When requsting a shared read-only CAS, the " + "access mode must be " + AUTO_CAS_UPGRADE);
        }
        // check for its existence
        try (WithExclusiveAccess access = new WithExclusiveAccess(aDocument, aUsername)) {
            // Since we promise to only read the CAS, we don't have to worry about it being
            // locked to a particular thread...
            casHolder = sharedAccessCache.get(new CasKey(aDocument, aUsername), (key) -> CasHolder.of(key, () -> getRealCas(readOrCreateUnmanagedCas(aDocument, aUsername, aSupplier, aUpgradeMode))));
        }
    } else // else if the special bypass mode is requested, then we fetch directly from disk
    if (UNMANAGED_ACCESS.equals(aAccessMode)) {
        // check for its existence
        try (WithExclusiveAccess access = new WithExclusiveAccess(aDocument, aUsername)) {
            casHolder = CasHolder.of(new CasKey(aDocument, aUsername), () -> readOrCreateUnmanagedCas(aDocument, aUsername, aSupplier, aUpgradeMode));
        }
    } else // else if the special bypass mode is requested, then we fetch directly from disk
    if (UNMANAGED_NON_INITIALIZING_ACCESS.equals(aAccessMode)) {
        // check for its existence
        try (WithExclusiveAccess access = new WithExclusiveAccess(aDocument, aUsername)) {
            casHolder = CasHolder.of(new CasKey(aDocument, aUsername), () -> readUnmanagedCas(aDocument, aUsername));
        }
    } else {
        throw new IllegalArgumentException("Unknown CAS access mode [" + aAccessMode + "]");
    }
    // If there was a problem retrieving the CAS, then we throw an exception
    if (casHolder.getException() != null) {
        if (casHolder.getException() instanceof IOException) {
            throw (IOException) casHolder.getException();
        }
        throw new IOException(casHolder.getException());
    }
    CAS cas = casHolder.getCas();
    if (aAccessMode.isSessionManaged()) {
        session.add(aDocument.getId(), aUsername, aAccessMode, cas).incrementReadCount();
    }
    return cas;
}
Also used : SessionManagedCas(de.tudarmstadt.ukp.clarin.webanno.api.dao.casstorage.SessionManagedCas) CasHolder(de.tudarmstadt.ukp.clarin.webanno.api.dao.casstorage.CasHolder) CAS(org.apache.uima.cas.CAS) CASImpl(org.apache.uima.cas.impl.CASImpl) CasKey(de.tudarmstadt.ukp.clarin.webanno.api.dao.casstorage.CasKey) IOException(java.io.IOException) CasStorageSession(de.tudarmstadt.ukp.clarin.webanno.api.dao.casstorage.CasStorageSession) CasDoctorException(de.tudarmstadt.ukp.clarin.webanno.diag.CasDoctorException) UIMAException(org.apache.uima.UIMAException) CasSessionException(de.tudarmstadt.ukp.clarin.webanno.api.casstorage.CasSessionException) FileNotFoundException(java.io.FileNotFoundException) DataRetrievalFailureException(org.springframework.dao.DataRetrievalFailureException) IOException(java.io.IOException)

Example 3 with CasHolder

use of de.tudarmstadt.ukp.clarin.webanno.api.dao.casstorage.CasHolder in project webanno by webanno.

the class CasStorageServiceImpl method borrowCas.

private CasHolder borrowCas(CasKey aKey) {
    try {
        CasHolder holder = exclusiveAccessPool.borrowObject(aKey);
        // Add the holder to the set of known holder. Because this set it using weak
        // references, and because we use the set only to inform holders when they become
        // invalid we do never have to explicitly remove the holder from the set
        exclusiveAccessHolders.add(holder);
        log.trace("Added to exclusiveAccessHolders: {}", holder);
        logExclusiveAccessHolders();
        return holder;
    } catch (Exception e) {
        throw new CasSessionException("Unable to borrow CAS", e);
    }
}
Also used : CasHolder(de.tudarmstadt.ukp.clarin.webanno.api.dao.casstorage.CasHolder) CasSessionException(de.tudarmstadt.ukp.clarin.webanno.api.casstorage.CasSessionException) CasDoctorException(de.tudarmstadt.ukp.clarin.webanno.diag.CasDoctorException) UIMAException(org.apache.uima.UIMAException) CasSessionException(de.tudarmstadt.ukp.clarin.webanno.api.casstorage.CasSessionException) FileNotFoundException(java.io.FileNotFoundException) DataRetrievalFailureException(org.springframework.dao.DataRetrievalFailureException) IOException(java.io.IOException)

Aggregations

CasHolder (de.tudarmstadt.ukp.clarin.webanno.api.dao.casstorage.CasHolder)3 CasSessionException (de.tudarmstadt.ukp.clarin.webanno.api.casstorage.CasSessionException)2 CasKey (de.tudarmstadt.ukp.clarin.webanno.api.dao.casstorage.CasKey)2 CasDoctorException (de.tudarmstadt.ukp.clarin.webanno.diag.CasDoctorException)2 FileNotFoundException (java.io.FileNotFoundException)2 IOException (java.io.IOException)2 UIMAException (org.apache.uima.UIMAException)2 DataRetrievalFailureException (org.springframework.dao.DataRetrievalFailureException)2 CasStorageSession (de.tudarmstadt.ukp.clarin.webanno.api.dao.casstorage.CasStorageSession)1 SessionManagedCas (de.tudarmstadt.ukp.clarin.webanno.api.dao.casstorage.SessionManagedCas)1 File (java.io.File)1 CAS (org.apache.uima.cas.CAS)1 CASImpl (org.apache.uima.cas.impl.CASImpl)1