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

rapture.repo.NVersionedRepo Maven / Gradle / Ivy

There is a newer version: 3.0.4
Show newest version
/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2011-2016 Incapture Technologies LLC
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package rapture.repo;

import rapture.common.LockHandle;
import rapture.common.MessageFormat;
import rapture.common.exception.RaptureExceptionFactory;
import rapture.common.impl.jackson.JsonContent;
import rapture.common.model.DocumentMetadata;
import rapture.common.model.DocumentWithMeta;
import rapture.dsl.dparse.AbsoluteVersion;
import rapture.dsl.dparse.AsOfTimeDirective;
import rapture.dsl.dparse.BaseDirective;
import rapture.dsl.dparse.VersionDirective;
import rapture.lock.ILockingHandler;
import rapture.repo.meta.AbstractMetaBasedRepo;
import rapture.repo.meta.handler.VersionedMetaHandler;

import java.net.HttpURLConnection;
import java.util.Map;

import org.apache.log4j.Logger;

/**
 * A repo that manages a "latest" version and a history of versions
 * 

* Also stores meta data about the current and historical versions * * @author amkimian */ public class NVersionedRepo extends AbstractMetaBasedRepo { private static final Logger log = Logger.getLogger(NVersionedRepo.class); public NVersionedRepo(Map config, KeyStore store, KeyStore versionKeyStore, KeyStore metaKeyStore, KeyStore attributeStore, ILockingHandler lockHandler) { super(store, lockHandler); metaHandler = new VersionedMetaHandler(store, versionKeyStore, metaKeyStore, attributeStore); } @Override public DocumentWithMeta revertDoc(String disp, BaseDirective directive) { return metaHandler.revertDoc(disp, producer); } @Override public boolean isVersioned() { return true; } /** * Archive old versions of the entire repo, including all docs. * * @param authority * @param versionLimit * @param timeLimit * @param ensureVersionLimit * @param user * @return */ public boolean archiveRepoVersions(final String authority, final int versionLimit, final long timeLimit, final boolean ensureVersionLimit, final String user) { log.info("Archive repo " + authority); RepoVisitor visitor = new RepoVisitor() { @Override public boolean visit(String name, JsonContent content, boolean isFolder) { archiveDocumentVersions(name, versionLimit, timeLimit, ensureVersionLimit, user); return true; } }; visitAll("", null, visitor); return true; } /** * Archives old versions * * @param docPath doc path * @param versionLimit number of versions to retain * @param timeLimit commits older than timeLimit will be archived * @param ensureVersionLimit ensure number of versions to retain even if commit is older * than timeLimit * @param user * @return */ public boolean archiveDocumentVersions(String docPath, int versionLimit, long timeLimit, boolean ensureVersionLimit, String user) { if (versionLimit <= 0) { log.error("versionLimit should > 0"); return false; } if (metaHandler.supportsVersionLookupByTime()) { return archiveDocumentVersionsWithTimestampRepo(docPath, versionLimit, timeLimit, ensureVersionLimit, user); } else { return archiveDocumentVersionsWithStandardRepo(docPath, versionLimit, timeLimit, ensureVersionLimit, user); } } private boolean archiveDocumentVersionsWithStandardRepo(String docPath, int versionLimit, long timeLimit, boolean ensureVersionLimit, String user) { try { int latestVersion = metaHandler.getLatestMeta(docPath).getVersion(); int cutoffVersion = getCutoffVersion(docPath, versionLimit, timeLimit, ensureVersionLimit); log.info(String.format("Archive doc %s: latestVersion=%d, cutoffVersion=%d", docPath, latestVersion, cutoffVersion)); // no version to archive if (cutoffVersion < 1) { return true; } // cutoff version is the latest version, delete the document if (cutoffVersion == latestVersion) { return removeDocument(docPath, user, "Archive old versions"); } return metaHandler.deleteOldVersions(docPath, cutoffVersion); } catch (Exception e) { log.error("Failed to archive " + docPath, e); return false; } } private int getCutoffVersion(String docPath, int versionLimit, long timeLimit, boolean ensureVersionLimit) { int versionsRemaining = versionLimit; int cutoffVersion = -1; DocumentMetadata metadata = metaHandler.getLatestMeta(docPath); while (metadata != null) { Long time = metadata.getModifiedTimestamp(); if (time == null && metadata.getWriteTime() != null) { time = metadata.getWriteTime().getTime(); } if (time == null || (time < timeLimit && !ensureVersionLimit)) { // reached the cut off version cutoffVersion = metadata.getVersion(); break; } else { versionsRemaining--; if (versionsRemaining <= 0) { cutoffVersion = metadata.getVersion() - 1; break; } else { // move on to previous version metadata = metaHandler.getVersionMeta(docPath, metadata.getVersion() - 1); } } } return cutoffVersion; } private boolean archiveDocumentVersionsWithTimestampRepo(String docPath, int versionLimit, long timeLimit, boolean ensureVersionLimit, String user) { try { DocumentMetadata latestMeta = metaHandler.getLatestMeta(docPath); long latestTimestamp = latestMeta.getModifiedTimestamp(); long cutoffTimestamp = getCutoffTimestamp(docPath, versionLimit, timeLimit, ensureVersionLimit, latestMeta); log.info(String.format("Archive doc %s: latestTimestamp=%d, cutoffTimestamp=%d", docPath, latestTimestamp, cutoffTimestamp)); // no version to archive if (cutoffTimestamp < 1) { return true; } // cutoff version is the latest version, delete the document if (cutoffTimestamp == latestTimestamp) { return removeDocument(docPath, user, "Archive old versions"); } return metaHandler.deleteOldVersions(docPath, cutoffTimestamp); } catch (Exception e) { log.error("Failed to archive " + docPath, e); return false; } } private long getCutoffTimestamp(String docPath, int versionLimit, long timeLimit, boolean ensureVersionLimit, DocumentMetadata latestMeta) { Long cutoffTimestamp = -1L; int cutoffVersion = latestMeta.getVersion() - versionLimit; DocumentMetadata metadata = latestMeta; if (timeLimit > 0) { // Jump right to the timestamp we're looking for, then iterate if we need to to keep versionLimit versions. metadata = metaHandler.getMetaAtTimestamp(docPath, timeLimit); } while (metadata != null) { cutoffTimestamp = metadata.getModifiedTimestamp(); if (cutoffTimestamp == null && metadata.getWriteTime() != null) { cutoffTimestamp = metadata.getWriteTime().getTime(); } if (cutoffTimestamp == null || (cutoffTimestamp < timeLimit && !ensureVersionLimit)) { // reached the cut off version break; } else { if (metadata.getVersion() <= cutoffVersion) { break; } else { // move on to previous version metadata = metaHandler.getMetaAtTimestamp(docPath, cutoffTimestamp - 1); } } } if (cutoffTimestamp == null) { cutoffTimestamp = -1L; } return cutoffTimestamp.longValue(); } @Override protected DocumentWithMeta getVersionedDocumentWithMeta(String docPath, VersionDirective directive) { if (directive instanceof AsOfTimeDirective) { return getVersionedDocumentWithMetaByAsOfTime(docPath, (AsOfTimeDirective) directive); } else { return metaHandler.getDocumentWithMeta(docPath, ((AbsoluteVersion) directive).getVersion()); } } private DocumentWithMeta getVersionedDocumentWithMetaByAsOfTime(String docPath, AsOfTimeDirective directive) { if (metaHandler.supportsVersionLookupByTime()) { DocumentWithMeta documentWithMeta = metaHandler.getDocumentWithMeta(docPath, directive.getAsOfTimeMillis()); if (documentWithMeta == null) { // Document didn't exist at that time. String[] parameters = {docPath, directive.getAsOfTime()}; throw RaptureExceptionFactory.create(HttpURLConnection.HTTP_NOT_FOUND, new MessageFormat(Messages.getString("InvalidAsOfTime"), parameters)); } return documentWithMeta; } else { String[] parameters = {directive.getClass().getName()}; throw RaptureExceptionFactory.create(HttpURLConnection.HTTP_INTERNAL_ERROR, new MessageFormat(Messages.getString("NVersionedRepository.InvalidDirective"), parameters)); } } @Override public boolean addDocumentWithVersion(String docPath, String content, String user, String comment, boolean mustBeNew, int expectedVersion) { String lockHolder = repoLockHandler.generateLockHolder(); boolean ret = false; LockHandle lockHandle = repoLockHandler.acquireLock(lockHolder); if (lockHandle != null) { try { ret = metaHandler.addDocumentWithExpectedVersion(docPath, content, user, comment, expectedVersion, producer); } finally { repoLockHandler.releaseLock(lockHolder, lockHandle); } } else { throw RaptureExceptionFactory.create(HttpURLConnection.HTTP_INTERNAL_ERROR, Messages.getString("NVersionedRepo.nolockWrite")); //$NON-NLS-1$ } return ret; } protected BaseDirective getAppropriateDirectiveFromAsOfTimeDirective(String docPath, AsOfTimeDirective directive) { if (metaHandler.supportsVersionLookupByTime()) { return directive; } Integer version = metaHandler.getVersionNumberAsOfTime(docPath, directive.getAsOfTime()); if (version == null) { // Document didn't exist at that time. String[] parameters = {docPath, directive.getAsOfTime()}; throw RaptureExceptionFactory.create(HttpURLConnection.HTTP_NOT_FOUND, new MessageFormat(Messages.getString("InvalidAsOfTime"), parameters)); } AbsoluteVersion newDirective = new AbsoluteVersion(); newDirective.setVersion(version); return newDirective; } @Override public DocumentWithMeta getDocAndMeta(String docPath, BaseDirective directive) { if (directive instanceof AsOfTimeDirective) { directive = getAppropriateDirectiveFromAsOfTimeDirective(docPath, (AsOfTimeDirective) directive); } return super.getDocAndMeta(docPath, directive); } @Override public DocumentMetadata getMeta(String docPath, BaseDirective directive) { if (directive instanceof AsOfTimeDirective) { directive = getAppropriateDirectiveFromAsOfTimeDirective(docPath, (AsOfTimeDirective) directive); } return super.getMeta(docPath, directive); } @Override public String getDocument(String docPath, BaseDirective directive) { if (directive instanceof AsOfTimeDirective) { directive = getAppropriateDirectiveFromAsOfTimeDirective(docPath, (AsOfTimeDirective) directive); } return super.getDocument(docPath, directive); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy