All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.duracloud.mill.manifest.jpa.JpaManifestStore Maven / Gradle / Ivy

There is a newer version: 8.0.0
Show newest version
/*
 * The contents of this file are subject to the license and copyright
 * detailed in the LICENSE and NOTICE files at the root of the source
 * tree and available online at
 *
 *     http://duracloud.org/license/
 */
package org.duracloud.mill.manifest.jpa;

import java.text.MessageFormat;
import java.util.Date;
import java.util.Iterator;

import org.duracloud.common.collection.StreamingIterator;
import org.duracloud.common.collection.jpa.JpaIteratorSource;
import org.duracloud.common.db.error.NotFoundException;
import org.duracloud.mill.db.model.ManifestItem;
import org.duracloud.mill.db.repo.JpaManifestItemRepo;
import org.duracloud.mill.db.repo.MillJpaRepoConfig;
import org.duracloud.mill.manifest.ManifestItemWriteException;
import org.duracloud.mill.manifest.ManifestStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author Daniel Bernstein
 */
public class JpaManifestStore implements ManifestStore {
    private static Logger log = LoggerFactory.getLogger(JpaManifestStore.class);
    private JpaManifestItemRepo manifestItemRepo;

    @Autowired
    public JpaManifestStore(JpaManifestItemRepo manifestItemRepo) {
        this.manifestItemRepo = manifestItemRepo;
    }

    @Override
    @Transactional(value = MillJpaRepoConfig.TRANSACTION_MANAGER_BEAN, propagation = Propagation.REQUIRES_NEW)
    public boolean addUpdate(String account,
                             String storeId,
                             String spaceId,
                             String contentId,
                             String contentChecksum,
                             String contentMimetype,
                             String contentSize,
                             Date eventTimestamp) throws ManifestItemWriteException {

        if (log.isDebugEnabled()) {
            log.debug("preparing to write account={}, " +
                      "storeId={}, " +
                      "spaceId={}, " +
                      "contentId={}, " +
                      "contentChecksum={}, " +
                      "contentMimetype={}, " +
                      "contentSize={}, " +
                      "eventTimestamp={}",
                      account,
                      storeId,
                      spaceId,
                      contentId,
                      contentChecksum,
                      contentMimetype,
                      contentSize,
                      eventTimestamp);
        }

        try {

            boolean save = false;

            ManifestItem item = this.manifestItemRepo
                .findByAccountAndStoreIdAndSpaceIdAndContentId(account, storeId, spaceId, contentId);
            String action = "added";

            if (item != null) {
                if (eventOutOfOrder(item, eventTimestamp)) {
                    return false;
                }

                //flip deleted flag if set to deleted
                if (item.isDeleted()) {
                    item.setDeleted(false);
                }
                String oldChecksum = item.getContentChecksum();
                if (!oldChecksum.equals(contentChecksum)) {
                    log.info("content checksum changed from {} to {}", oldChecksum, contentChecksum);
                }

                String oldMimetype = item.getContentMimetype();
                if (!oldMimetype.equals(contentMimetype)) {
                    log.info("content mimetype changed from {} to {}", oldMimetype, contentMimetype);
                }

                String oldSize = item.getContentSize();
                if (!oldSize.equals(contentSize)) {
                    log.info("content size changed from {} to {}", oldMimetype, contentSize);
                }

                action = "updated";

            } else {
                item = new ManifestItem();
                item.setAccount(account);
                item.setStoreId(storeId);
                item.setSpaceId(spaceId);
                item.setContentId(contentId);
            }

            item.setContentChecksum(contentChecksum);
            item.setContentMimetype(contentMimetype);
            item.setContentSize(contentSize);
            item.setModified(eventTimestamp);
            ManifestItem result = this.manifestItemRepo.saveAndFlush(item);
            log.info("successfully {} {} to the jpa repo.", action, result);
            return true;
        } catch (Exception ex) {
            String message = "failed to write item: " + ex.getMessage();
            log.error(message);
            throw new ManifestItemWriteException(message, ex);
        }
    }

    /* (non-Javadoc)
     * @see org.duracloud.mill.manifest.ManifestStore#flagAsDeleted(java.lang.String, java.lang.String, java.lang
     * .String, java.lang.String)
     */
    @Override
    @Transactional(value = MillJpaRepoConfig.TRANSACTION_MANAGER_BEAN, propagation = Propagation.REQUIRES_NEW)
    public boolean flagAsDeleted(String account,
                                 String storeId,
                                 String spaceId,
                                 String contentId,
                                 Date eventTimestamp) throws ManifestItemWriteException {
        try {

            ManifestItem item = this.manifestItemRepo
                .findByAccountAndStoreIdAndSpaceIdAndContentId(account,
                                                               storeId,
                                                               spaceId,
                                                               contentId);

            if (item != null) {
                if (eventOutOfOrder(item, eventTimestamp)) {
                    return false;
                }

                if (item.isDeleted()) {
                    log.warn("item {}/{}/{}/{} has already been deleted - " +
                             "there appears to have been a duplicate event " +
                             "or possibly a missed content add event - ignoring...",
                             account,
                             storeId,
                             spaceId,
                             contentId);

                }
            } else {
                log.warn("no manifest item {}/{}/{}/{} : nothing to delete - adding deleted manifest entry...",
                         account,
                         storeId,
                         spaceId,
                         contentId);

                item = new ManifestItem();
                item.setAccount(account);
                item.setStoreId(storeId);
                item.setSpaceId(spaceId);
                item.setContentId(contentId);
                item.setContentMimetype("unknown");
                item.setContentSize("0");
                item.setContentChecksum("unknown");
            }

            item.setDeleted(true);
            item.setModified(eventTimestamp);
            ManifestItem result = this.manifestItemRepo.saveAndFlush(item);
            log.info("successfully processed flag as deleted: {}", result);
            return true;
        } catch (Exception ex) {
            String message = "failed to flag item as deleted item: " + ex.getMessage();
            log.error(message);
            throw new ManifestItemWriteException(message, ex);
        }
    }

    /**
     * @param item
     * @param eventTimestamp
     * @return
     */
    private boolean eventOutOfOrder(ManifestItem item, Date eventTimestamp) {
        long itemTime = item.getModified().getTime();
        long eventTime = eventTimestamp.getTime();

        if (eventTime < itemTime) {
            log.warn("The current database item is more " +
                     "current that the event: item last modified: " +
                     "{}, event timestamp: {}. Likely cause: events " +
                     "were delivered out of order. Ignoring...",
                     itemTime,
                     eventTime);
            return true;
        } else {
            return false;
        }
    }

    @Override
    public Iterator getItems(final String account,
                                           final String storeId,
                                           final String spaceId) {
        return getItems(account, storeId, spaceId, false);
    }

    @Override
    public Iterator getItems(final String account,
                                           final String storeId,
                                           final String spaceId,
                                           final boolean ordered) {

        if (ordered) {
            return getItemsOrdered(account, storeId, spaceId);
        } else {
            return getItemsUnordered(account, storeId, spaceId);
        }

    }

    private Iterator getItemsOrdered(final String account, final String storeId, final String spaceId) {
        JpaIteratorSource source =
            new JpaIteratorSource(this.manifestItemRepo, 10000) {
                @Override
                protected Page getNextPage(Pageable pageable,
                                                         JpaManifestItemRepo repo) {
                    return manifestItemRepo
                        .findByAccountAndStoreIdAndSpaceIdAndDeletedFalseOrderByContentIdAsc(account,
                                                                                             storeId,
                                                                                             spaceId,
                                                                                             pageable);
                }
            };
        return (Iterator) new StreamingIterator(source);
    }

    /**
     * @param account
     * @param storeId
     * @param spaceId
     * @return
     */
    private Iterator getItemsUnordered(final String account,
                                                     final String storeId,
                                                     final String spaceId) {
        return new StreamingIterator(
            new ManifestItemIteratorSource(this.manifestItemRepo,
                                           account,
                                           storeId,
                                           spaceId,
                                           10000));
    }

    @Override
    public ManifestItem getItem(final String account,
                                final String storeId,
                                final String spaceId,
                                final String contentId) throws NotFoundException {
        ManifestItem item = this.manifestItemRepo
            .findByAccountAndStoreIdAndSpaceIdAndContentId(account,
                                                           storeId,
                                                           spaceId,
                                                           contentId);
        if (item == null) {
            throw new NotFoundException(
                MessageFormat.format("No ManifestItem could be found matching the specified params: " +
                                     "account={0}, storeId={1}, spaceId={2}, contentId={3}",
                                     account,
                                     storeId,
                                     spaceId,
                                     contentId));
        }

        return item;
    }

    /* (non-Javadoc)
     * @see org.duracloud.mill.manifest.ManifestStore#purgeDeletedItemsBefore(java.util.Date)
     */
    @Override
    @Transactional(value = MillJpaRepoConfig.TRANSACTION_MANAGER_BEAN, propagation = Propagation.REQUIRES_NEW)
    public int purgeDeletedItemsBefore(Date expiration) {
        return this.manifestItemRepo.deleteFirst50000ByDeletedTrueAndModifiedBefore(expiration);
    }

    @Override
    @Transactional(value = MillJpaRepoConfig.TRANSACTION_MANAGER_BEAN, propagation = Propagation.REQUIRES_NEW)
    public void updateMissingFromStorageProviderFlag(String account,
                                                     String storeId,
                                                     String spaceId,
                                                     String contentId,
                                                     boolean flag) throws ManifestItemWriteException {

        try {

            ManifestItem item = this.manifestItemRepo
                .findByAccountAndStoreIdAndSpaceIdAndContentId(account,
                                                               storeId,
                                                               spaceId,
                                                               contentId);

            if (item != null) {
                item.setMissingFromStorageProvider(flag);
                ManifestItem result = this.manifestItemRepo.saveAndFlush(item);
                log.info("successfully processed update MissingFromStorageProvider flag: {}", result);
            } else {
                String message = MessageFormat.format("no manifest item found:  {0}/{1}/{2}/{3}: something's amiss.",
                                                      account,
                                                      storeId,
                                                      spaceId,
                                                      contentId);
                throw new NotFoundException(message);
            }

        } catch (Exception ex) {
            String message = "failed to update manifest item with : " + ex.getMessage();
            log.error(message);
            throw new ManifestItemWriteException(message, ex);
        }
    }

    @Override
    @Transactional(value = MillJpaRepoConfig.TRANSACTION_MANAGER_BEAN, propagation = Propagation.REQUIRES_NEW)
    public void delete(String account, String storeId, String spaceId)
        throws ManifestItemWriteException {
        this.manifestItemRepo.deleteByAccountAndStoreIdAndSpaceId(account, storeId, spaceId);
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy