Search in sources :

Example 1 with PreconditionFailedException

use of ca.nrc.cadc.net.PreconditionFailedException in project caom2db by opencadc.

the class AbstractObservationDAOTest method testConditionalUpdate.

@Test
public void testConditionalUpdate() {
    try {
        SimpleObservation orig = new SimpleObservation("FOO", "bar");
        dao.put(orig);
        Observation c = dao.get(orig.getURI());
        Assert.assertNotNull("found", c);
        testEqual(orig, c);
        URI cs1 = c.getAccMetaChecksum();
        c.sequenceNumber = 1;
        dao.put(c, cs1);
        Observation c2 = dao.get(c.getURI());
        Assert.assertNotNull("found", c2);
        URI cs2 = c.getAccMetaChecksum();
        // conditional update fails when expected checksum does not match
        c.type = "OBJECT";
        try {
            dao.put(c, cs1);
        } catch (PreconditionFailedException expected) {
            log.info("caught expected exception: " + expected);
        }
        // conditional update succeeds when expected checksum does match
        dao.put(c, cs2);
        Observation c3 = dao.get(c.getURI());
        Assert.assertNotNull("found", c3);
        URI cs3 = c.getAccMetaChecksum();
        dao.delete(orig.getID());
        // copnditional update fails when not found
        try {
            dao.put(c, cs3);
        } catch (PreconditionFailedException expected) {
            log.info("caught expected exception: " + expected);
        }
    } catch (Exception unexpected) {
        log.error("unexpected exception", unexpected);
        if (txnManager.isOpen())
            try {
                txnManager.rollbackTransaction();
            } catch (Throwable t) {
                log.error("failed to rollback transaction", t);
            }
        Assert.fail("unexpected exception: " + unexpected);
    }
}
Also used : SimpleObservation(ca.nrc.cadc.caom2.SimpleObservation) DerivedObservation(ca.nrc.cadc.caom2.DerivedObservation) Observation(ca.nrc.cadc.caom2.Observation) DeletedObservation(ca.nrc.cadc.caom2.DeletedObservation) SimpleObservation(ca.nrc.cadc.caom2.SimpleObservation) PreconditionFailedException(ca.nrc.cadc.net.PreconditionFailedException) PlaneURI(ca.nrc.cadc.caom2.PlaneURI) URI(java.net.URI) ObservationURI(ca.nrc.cadc.caom2.ObservationURI) SQLException(java.sql.SQLException) PreconditionFailedException(ca.nrc.cadc.net.PreconditionFailedException) Test(org.junit.Test)

Example 2 with PreconditionFailedException

use of ca.nrc.cadc.net.PreconditionFailedException in project caom2db by opencadc.

the class ObservationDAO method put.

/**
 * Store an observation. If the optional accMetaChecksum argument is not null and does not
 * match the accMetaChecksum of the currently observation, the update is rejected.
 *
 * @param obs the observation
 * @param expectedMetaChecksum optional metadata checksum
 * @throws PreconditionFailedException if the accMetaChecksum does not match
 */
public void put(Observation obs, URI expectedMetaChecksum) throws PreconditionFailedException {
    if (readOnly) {
        throw new UnsupportedOperationException("put in readOnly mode");
    }
    checkInit();
    if (obs == null) {
        throw new IllegalArgumentException("arg cannot be null");
    }
    log.debug("PUT: " + obs.getURI() + ", planes: " + obs.getPlanes().size());
    long t = System.currentTimeMillis();
    boolean txnOpen = false;
    try {
        JdbcTemplate jdbc = new JdbcTemplate(dataSource);
        // get current timestamp from server so that lastModified is closer to
        // monatonically increasing than if we use client machine clock
        Date now = getCurrentTime(jdbc);
        DateFormat df = DateUtil.getDateFormat(DateUtil.IVOA_DATE_FORMAT, DateUtil.UTC);
        log.debug("current time: " + df.format(now));
        // NOTE: this is by ID which means to update the caller must get(uri) then put(o)
        // and if they do not get(uri) they can get a duplicate observation error
        // if they violate unique keys
        String sql = gen.getSelectSQL(obs.getID(), SQLGenerator.MAX_DEPTH, true);
        log.debug("PUT: " + sql);
        final ObservationSkeleton dirtyRead = (ObservationSkeleton) jdbc.query(sql, new ObservationSkeletonExtractor());
        log.debug("starting transaction");
        getTransactionManager().startTransaction();
        txnOpen = true;
        // obtain row lock on observation update
        ObservationSkeleton cur = null;
        if (dirtyRead != null) {
            String lock = gen.getUpdateLockSQL(obs.getID());
            log.debug("LOCK SQL: " + lock);
            jdbc.update(lock);
            // req-acquire current state after obtaining lock
            cur = (ObservationSkeleton) jdbc.query(sql, new ObservationSkeletonExtractor());
            // check conditional update
            if (expectedMetaChecksum != null) {
                if (cur == null) {
                    // deleted by another actor since dirtyRead
                    throw new PreconditionFailedException("update blocked: current entity does not exist");
                } else if (!expectedMetaChecksum.equals(cur.accMetaChecksum)) {
                    throw new PreconditionFailedException("update blocked: current entity is : " + cur.accMetaChecksum);
                }
            }
        } else if (expectedMetaChecksum != null) {
            throw new PreconditionFailedException("update blocked: current entity does not exist");
        }
        // update metadata checksums, maybe modified timestamps
        updateEntity(obs, cur, now);
        // delete obsolete children
        List<Pair<Plane>> pairs = new ArrayList<Pair<Plane>>();
        if (cur != null) {
            // delete the skeletons that are not in obs.getPlanes()
            for (PlaneSkeleton ps : cur.planes) {
                Plane p = Util.findPlane(obs.getPlanes(), ps.id);
                if (p == null) {
                    log.debug("PUT: caused delete: " + ps.id);
                    planeDAO.delete(ps, jdbc);
                }
            }
            // pair up planes and skeletons for insert/update
            for (Plane p : obs.getPlanes()) {
                PlaneSkeleton ps = Util.findPlaneSkel(cur.planes, p.getID());
                // null ok
                pairs.add(new Pair<Plane>(ps, p));
            }
        } else {
            for (Plane p : obs.getPlanes()) {
                pairs.add(new Pair<Plane>(null, p));
            }
        }
        super.put(cur, obs, null, jdbc);
        // insert/update children
        LinkedList<CaomEntity> parents = new LinkedList<CaomEntity>();
        parents.push(obs);
        for (Pair<Plane> p : pairs) {
            planeDAO.put(p.cur, p.val, parents, jdbc);
        }
        log.debug("committing transaction");
        getTransactionManager().commitTransaction();
        log.debug("commit: OK");
        txnOpen = false;
    } catch (DataIntegrityViolationException e) {
        log.debug("failed to insert " + obs + ": ", e);
        getTransactionManager().rollbackTransaction();
        log.debug("rollback: OK");
        txnOpen = false;
        throw e;
    } catch (PreconditionFailedException ex) {
        log.debug("failed to update " + obs + ": ", ex);
        getTransactionManager().rollbackTransaction();
        log.debug("rollback: OK");
        txnOpen = false;
        throw ex;
    } catch (Exception e) {
        log.error("failed to insert " + obs + ": ", e);
        getTransactionManager().rollbackTransaction();
        log.debug("rollback: OK");
        txnOpen = false;
        throw e;
    } finally {
        if (txnOpen) {
            log.error("BUG - open transaction in finally");
            getTransactionManager().rollbackTransaction();
            log.error("rollback: OK");
        }
        long dt = System.currentTimeMillis() - t;
        log.debug("PUT: " + obs.getURI() + " " + dt + "ms");
    }
}
Also used : Plane(ca.nrc.cadc.caom2.Plane) ArrayList(java.util.ArrayList) JdbcTemplate(org.springframework.jdbc.core.JdbcTemplate) CaomEntity(ca.nrc.cadc.caom2.CaomEntity) Date(java.util.Date) LinkedList(java.util.LinkedList) DataAccessException(org.springframework.dao.DataAccessException) SQLException(java.sql.SQLException) DataIntegrityViolationException(org.springframework.dao.DataIntegrityViolationException) PreconditionFailedException(ca.nrc.cadc.net.PreconditionFailedException) DataIntegrityViolationException(org.springframework.dao.DataIntegrityViolationException) DateFormat(java.text.DateFormat) ObservationSkeleton(ca.nrc.cadc.caom2.persistence.skel.ObservationSkeleton) PlaneSkeleton(ca.nrc.cadc.caom2.persistence.skel.PlaneSkeleton) PreconditionFailedException(ca.nrc.cadc.net.PreconditionFailedException)

Aggregations

PreconditionFailedException (ca.nrc.cadc.net.PreconditionFailedException)2 SQLException (java.sql.SQLException)2 CaomEntity (ca.nrc.cadc.caom2.CaomEntity)1 DeletedObservation (ca.nrc.cadc.caom2.DeletedObservation)1 DerivedObservation (ca.nrc.cadc.caom2.DerivedObservation)1 Observation (ca.nrc.cadc.caom2.Observation)1 ObservationURI (ca.nrc.cadc.caom2.ObservationURI)1 Plane (ca.nrc.cadc.caom2.Plane)1 PlaneURI (ca.nrc.cadc.caom2.PlaneURI)1 SimpleObservation (ca.nrc.cadc.caom2.SimpleObservation)1 ObservationSkeleton (ca.nrc.cadc.caom2.persistence.skel.ObservationSkeleton)1 PlaneSkeleton (ca.nrc.cadc.caom2.persistence.skel.PlaneSkeleton)1 URI (java.net.URI)1 DateFormat (java.text.DateFormat)1 ArrayList (java.util.ArrayList)1 Date (java.util.Date)1 LinkedList (java.util.LinkedList)1 Test (org.junit.Test)1 DataAccessException (org.springframework.dao.DataAccessException)1 DataIntegrityViolationException (org.springframework.dao.DataIntegrityViolationException)1