public boolean delete(Object key) { if (!isValidKeyType(key)) { return false; } EntityManager em = emf.createEntityManager(); try { long entityFindBegin = timeService.time(); Object entity = em.find(configuration.entityClass(), key); stats.addEntityFind(timeService.time() - entityFindBegin); if (entity == null) { return false; } MetadataEntity metadata = null; if (configuration.storeMetadata()) { byte[] keyBytes; try { keyBytes = marshaller.objectToByteBuffer(key); } catch (Exception e) { throw new JpaStoreException("Failed to marshall key", e); } long metadataFindBegin = timeService.time(); metadata = em.find(MetadataEntity.class, keyBytes); stats.addMetadataFind(timeService.time() - metadataFindBegin); } EntityTransaction txn = em.getTransaction(); if (trace) log.trace("Removing " + entity + "(" + toString(metadata) + ")"); long txnBegin = timeService.time(); txn.begin(); try { long entityRemoveBegin = timeService.time(); em.remove(entity); stats.addEntityRemove(timeService.time() - entityRemoveBegin); if (metadata != null) { long metadataRemoveBegin = timeService.time(); em.remove(metadata); stats.addMetadataRemove(timeService.time() - metadataRemoveBegin); } txn.commit(); stats.addRemoveTxCommitted(timeService.time() - txnBegin); return true; } catch (Exception e) { stats.addRemoveTxFailed(timeService.time() - txnBegin); throw new JpaStoreException("Exception caught in delete()", e); } finally { if (txn != null && txn.isActive()) txn.rollback(); } } finally { em.close(); } }
@Override public void purge(Executor threadPool, final PurgeListener listener) { ExecutorAllCompletionService eacs = new ExecutorAllCompletionService(threadPool); EntityManager em = emf.createEntityManager(); try { CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<MetadataEntity> cq = cb.createQuery(MetadataEntity.class); Root root = cq.from(MetadataEntity.class); long currentTime = timeService.wallClockTime(); cq.where(cb.le(root.get(MetadataEntity.EXPIRATION), currentTime)); for (MetadataEntity metadata : em.createQuery(cq).getResultList()) { EntityTransaction txn = em.getTransaction(); final Object key; try { key = marshaller.objectFromByteBuffer(metadata.name); } catch (Exception e) { throw new JpaStoreException("Cannot unmarshall key", e); } long txnBegin = timeService.time(); txn.begin(); try { long metadataFindBegin = timeService.time(); metadata = em.find(MetadataEntity.class, metadata.name); stats.addMetadataFind(timeService.time() - metadataFindBegin); // check for transaction - I hope write skew check is done here if (metadata.expiration > currentTime) { txn.rollback(); continue; } long entityFindBegin = timeService.time(); Object entity = em.find(configuration.entityClass(), key); stats.addEntityFind(timeService.time() - entityFindBegin); if (entity != null) { // the entry may have been removed long entityRemoveBegin = timeService.time(); em.remove(entity); stats.addEntityRemove(timeService.time() - entityRemoveBegin); } long metadataRemoveBegin = timeService.time(); em.remove(metadata); stats.addMetadataRemove(timeService.time() - metadataRemoveBegin); txn.commit(); stats.addRemoveTxCommitted(timeService.time() - txnBegin); if (trace) log.trace("Expired " + key + " -> " + entity + "(" + toString(metadata) + ")"); if (listener != null) { eacs.submit( new Runnable() { @Override public void run() { listener.entryPurged(key); } }, null); } } catch (RuntimeException e) { stats.addRemoveTxFailed(timeService.time() - txnBegin); throw e; } finally { if (txn != null && txn.isActive()) { txn.rollback(); } } } } finally { em.close(); } eacs.waitUntilAllCompleted(); if (eacs.isExceptionThrown()) { throw new JpaStoreException(eacs.getFirstException()); } }