DbObjectMetadataManagerImpl.java (eucalyptus-4.4.1) | : | DbObjectMetadataManagerImpl.java (eucalyptus-4.4.2) | ||
---|---|---|---|---|
skipping to change at line 36 | skipping to change at line 36 | |||
import java.util.HashSet; | import java.util.HashSet; | |||
import java.util.List; | import java.util.List; | |||
import java.util.NoSuchElementException; | import java.util.NoSuchElementException; | |||
import javax.annotation.Nonnull; | import javax.annotation.Nonnull; | |||
import javax.annotation.Nullable; | import javax.annotation.Nullable; | |||
import javax.persistence.EntityTransaction; | import javax.persistence.EntityTransaction; | |||
import org.apache.log4j.Logger; | import org.apache.log4j.Logger; | |||
import org.hibernate.Criteria; | import org.hibernate.Criteria; | |||
import org.hibernate.ScrollMode; | ||||
import org.hibernate.ScrollableResults; | ||||
import org.hibernate.criterion.Example; | import org.hibernate.criterion.Example; | |||
import org.hibernate.criterion.MatchMode; | import org.hibernate.criterion.MatchMode; | |||
import org.hibernate.criterion.Order; | import org.hibernate.criterion.Order; | |||
import org.hibernate.criterion.Projections; | import org.hibernate.criterion.Projections; | |||
import org.hibernate.criterion.Restrictions; | import org.hibernate.criterion.Restrictions; | |||
import com.eucalyptus.auth.Accounts; | ||||
import com.eucalyptus.auth.principal.User; | ||||
import com.eucalyptus.auth.principal.UserPrincipal; | import com.eucalyptus.auth.principal.UserPrincipal; | |||
import com.eucalyptus.entities.Entities; | import com.eucalyptus.entities.Entities; | |||
import com.eucalyptus.entities.TransactionException; | import com.eucalyptus.entities.TransactionException; | |||
import com.eucalyptus.entities.TransactionResource; | import com.eucalyptus.entities.TransactionResource; | |||
import com.eucalyptus.entities.Transactions; | import com.eucalyptus.entities.Transactions; | |||
import com.eucalyptus.objectstorage.ObjectMetadataManagers; | import com.eucalyptus.objectstorage.ObjectMetadataManagers; | |||
import com.eucalyptus.objectstorage.ObjectState; | import com.eucalyptus.objectstorage.ObjectState; | |||
import com.eucalyptus.objectstorage.PaginatedResult; | import com.eucalyptus.objectstorage.PaginatedResult; | |||
import com.eucalyptus.objectstorage.entities.Bucket; | import com.eucalyptus.objectstorage.entities.Bucket; | |||
import com.eucalyptus.objectstorage.entities.ObjectEntity; | import com.eucalyptus.objectstorage.entities.ObjectEntity; | |||
skipping to change at line 227 | skipping to change at line 227 | |||
} | } | |||
ObjectEntity latest = results.get(0); | ObjectEntity latest = results.get(0); | |||
latest.setIsLatest(Boolean.TRUE); | latest.setIsLatest(Boolean.TRUE); | |||
// Set all but the first element as not latest | // Set all but the first element as not latest | |||
for (ObjectEntity obj : results.subList(1, results.size())) { | for (ObjectEntity obj : results.subList(1, results.size())) { | |||
LOG.trace("Marking object " + obj.getObjectUuid() + " as no longer l atest version"); | LOG.trace("Marking object " + obj.getObjectUuid() + " as no longer l atest version"); | |||
obj.setIsLatest(Boolean.FALSE); | obj.setIsLatest(Boolean.FALSE); | |||
if (latest.getVersionId() != null && ObjectStorageProperties.NULL_VE RSION_ID.equals(latest.getVersionId()) && obj.getVersionId() != null | if (latest.getVersionId() != null && ObjectStorageProperties.NULL_VE RSION_ID.equals(latest.getVersionId()) && obj.getVersionId() != null | |||
&& ObjectStorageProperties.NULL_VERSION_ID.equals(obj.getVersion Id())) { | && ObjectStorageProperties.NULL_VERSION_ID.equals(obj.getVersion Id())) { | |||
LOG.trace("Transitioning to deleting"); | ||||
transitionObjectToState(obj, ObjectState.deleting); | transitionObjectToState(obj, ObjectState.deleting); | |||
} | } | |||
} | } | |||
} catch (NoSuchElementException e) { | } catch (NoSuchElementException e) { | |||
// Nothing to do. | // Nothing to do. | |||
} catch (Exception e) { | } catch (Exception e) { | |||
LOG.error("Error consolidationg Object records for " + example.getBuck et().getBucketName() + "/" + example.getObjectKey()); | LOG.error("Error consolidationg Object records for " + example.getBuck et().getBucketName() + "/" + example.getObjectKey()); | |||
return false; | return false; | |||
} | } | |||
return true; | return true; | |||
} | } | |||
}; | }; | |||
try { | try { | |||
LOG.trace("Starting cleanup for " + bucket.getBucketName() + "/" + objectK ey); | ||||
Entities.asTransaction(repairPredicate).apply(searchExample); | Entities.asTransaction(repairPredicate).apply(searchExample); | |||
} catch (final Throwable f) { | } catch (final Throwable f) { | |||
LOG.error("Error in version/null repair", f); | LOG.error("Error in version/null repair", f); | |||
} | } | |||
} | } | |||
@Override | @Override | |||
public void cleanupAllNullVersionedObjectRecords(final Bucket bucket, final St ring objectKey) throws Exception { | public void cleanupAllNullVersionedObjectRecords(final Bucket bucket, final St ring objectKey) throws Exception { | |||
ObjectEntity searchExample = new ObjectEntity(bucket, objectKey, null); | ObjectEntity searchExample = new ObjectEntity(bucket, objectKey, null); | |||
skipping to change at line 645 | skipping to change at line 647 | |||
retrieved.setIsLatest(Boolean.FALSE); | retrieved.setIsLatest(Boolean.FALSE); | |||
tran.commit(); | tran.commit(); | |||
return retrieved; | return retrieved; | |||
} catch (Exception ex) { | } catch (Exception ex) { | |||
LOG.warn("while attempting to set isLatest = true on the newest remaining object version, an exception was encountered: ", ex); | LOG.warn("while attempting to set isLatest = true on the newest remaining object version, an exception was encountered: ", ex); | |||
throw ex; | throw ex; | |||
} | } | |||
} | } | |||
@Override | @Override | |||
public PaginatedResult<ObjectEntity> listVersionsPaginated(final Bucket bucket | public PaginatedResult<ObjectEntity> listVersionsPaginated( | |||
, int maxEntries, String prefix, String delimiter, | final Bucket bucket, | |||
String fromKeyMarker, String fromVersionId, boolean latestOnly) throws Exc | final int maxEntries, | |||
eption { | String prefix, | |||
String delimiter, | ||||
EntityTransaction db = Entities.get(ObjectEntity.class); | final String fromKeyMarker, | |||
try { | final String fromVersionId, | |||
final boolean latestOnly | ||||
) throws Exception { | ||||
try ( final TransactionResource db = Entities.readOnlyDistinctTransactionFor | ||||
( ObjectEntity.class ) ) { | ||||
PaginatedResult<ObjectEntity> result = new PaginatedResult<ObjectEntity>() ; | PaginatedResult<ObjectEntity> result = new PaginatedResult<ObjectEntity>() ; | |||
HashSet<String> commonPrefixes = new HashSet<String>(); | HashSet<String> commonPrefixes = new HashSet<String>(); | |||
// Include zero since 'istruncated' is still valid | // Include zero since 'istruncated' is still valid | |||
if (maxEntries >= 0) { | if (maxEntries >= 0) { | |||
final int queryStrideSize = maxEntries + 1; | ||||
ObjectEntity searchObj = new ObjectEntity().withBucket(bucket).withState (ObjectState.extant); | ObjectEntity searchObj = new ObjectEntity().withBucket(bucket).withState (ObjectState.extant); | |||
// Return latest version, so exclude delete markers as well. | // Return latest version, so exclude delete markers as well. | |||
// This makes listVersion act like listObjects | // This makes listVersion act like listObjects | |||
if (latestOnly) { | if (latestOnly) { | |||
searchObj.setIsLatest(true); | searchObj.setIsLatest(true); | |||
searchObj.setIsDeleteMarker(false); | searchObj.setIsDeleteMarker(false); | |||
} | } | |||
Criteria objCriteria = Entities.createCriteria(ObjectEntity.class); | Criteria objCriteria = Entities.createCriteria(ObjectEntity.class); | |||
objCriteria.setReadOnly(true); | objCriteria.setReadOnly(true); | |||
objCriteria.setFetchSize(queryStrideSize); | objCriteria.setFetchSize(1_000); | |||
objCriteria.add(Example.create(searchObj)); | objCriteria.add(Example.create(searchObj)); | |||
objCriteria.addOrder(Order.asc("objectKey")); | objCriteria.addOrder(Order.asc("objectKey")); | |||
objCriteria.addOrder(Order.desc("objectModifiedTimestamp")); | objCriteria.addOrder(Order.desc("objectModifiedTimestamp")); | |||
objCriteria.setMaxResults(queryStrideSize); | ||||
if (!Strings.isNullOrEmpty(fromKeyMarker)) { | if (!Strings.isNullOrEmpty(fromKeyMarker)) { | |||
if (!Strings.isNullOrEmpty(fromVersionId)) { | if (!Strings.isNullOrEmpty(fromVersionId)) { | |||
// Look for the key that matches the key-marker and version-id-marke r | // Look for the key that matches the key-marker and version-id-marke r | |||
ObjectEntity searchObject = new ObjectEntity(bucket, fromKeyMarker, fromVersionId); | ObjectEntity searchObject = new ObjectEntity(bucket, fromKeyMarker, fromVersionId); | |||
ObjectEntity matchingObject = null; | ObjectEntity matchingObject = null; | |||
try { | try { | |||
matchingObject = Entities.uniqueResult(searchObject); | matchingObject = Entities.uniqueResult(searchObject); | |||
if (matchingObject == null || matchingObject.getObjectModifiedTime stamp() == null) { | if (matchingObject == null || matchingObject.getObjectModifiedTime stamp() == null) { | |||
throw new NoSuchKeyException(bucket.getBucketName() + "/" + from KeyMarker + "?versionId=" + fromVersionId); | throw new NoSuchKeyException(bucket.getBucketName() + "/" + from KeyMarker + "?versionId=" + fromVersionId); | |||
skipping to change at line 714 | skipping to change at line 719 | |||
prefix = ""; | prefix = ""; | |||
} | } | |||
objCriteria = getSearchByBucket(objCriteria, bucket); | objCriteria = getSearchByBucket(objCriteria, bucket); | |||
// Ensure not null. | // Ensure not null. | |||
if (Strings.isNullOrEmpty(delimiter)) { | if (Strings.isNullOrEmpty(delimiter)) { | |||
delimiter = ""; | delimiter = ""; | |||
} | } | |||
List<ObjectEntity> objectInfos = null; | ||||
int resultKeyCount = 0; | int resultKeyCount = 0; | |||
String[] parts = null; | String[] parts = null; | |||
String prefixString = null; | String prefixString = null; | |||
boolean useDelimiter = !Strings.isNullOrEmpty(delimiter); | boolean useDelimiter = !Strings.isNullOrEmpty(delimiter); | |||
int pages = 0; | ||||
// Iterate over result sets of size maxkeys + 1 since | // Iterate over results, since | |||
// commonPrefixes collapse the list, we may examine many more | // commonPrefixes collapse the list, we may examine many more | |||
// records than maxkeys + 1 | // records than maxkeys + 1 | |||
do { | final ScrollableResults objectResults = objCriteria.scroll( ScrollMode.F | |||
parts = null; | ORWARD_ONLY ); | |||
prefixString = null; | try { | |||
while ( objectResults.next( ) ) { | ||||
// Skip ahead the next page of 'queryStrideSize' results. | final ObjectEntity objectRecord = (ObjectEntity) objectResults.get( | |||
objCriteria.setFirstResult(pages++ * queryStrideSize); | 0 ); | |||
objectInfos = (List<ObjectEntity>) objCriteria.list(); | ||||
if (objectInfos == null) { | ||||
// nothing to do. | ||||
break; | ||||
} | ||||
for (ObjectEntity objectRecord : objectInfos) { | ||||
if (useDelimiter) { | if (useDelimiter) { | |||
// Check if it will get aggregated as a commonprefix | // Check if it will get aggregated as a commonprefix | |||
// Split the substring with at least 2 matches as we need a result containing trailing strings. For instance | // Split the substring with at least 2 matches as we need a result containing trailing strings. For instance | |||
// if "x" is delimiter and key string is also "x", then this key s hould be included in common prefixes. | // if "x" is delimiter and key string is also "x", then this key s hould be included in common prefixes. | |||
// "x".split("x") gives 0 strings which causes the subsequent logi c to skip the key where as | // "x".split("x") gives 0 strings which causes the subsequent logi c to skip the key where as | |||
// "x".split("x", 2) gives 2 empty strings which is what the logic expects | // "x".split("x", 2) gives 2 empty strings which is what the logic expects | |||
parts = objectRecord.getObjectKey().substring(prefix.length()).spl it(delimiter, 2); | parts = objectRecord.getObjectKey().substring(prefix.length()).spl it(delimiter, 2); | |||
if (parts.length > 1) { | if (parts.length > 1) { | |||
prefixString = prefix + parts[0] + delimiter; | prefixString = prefix + parts[0] + delimiter; | |||
if (!prefixString.equals(fromKeyMarker) && !commonPrefixes.conta ins(prefixString)) { | if (!prefixString.equals(fromKeyMarker) && !commonPrefixes.conta ins(prefixString)) { | |||
if (resultKeyCount == maxEntries) { | if (resultKeyCount == maxEntries) { | |||
// This is a new record, so we know | // This is a new record, so we know | |||
// we're truncating if this is true | // we're truncating if this is true | |||
result.setIsTruncated(true); | result.setIsTruncated(true); | |||
resultKeyCount++; | ||||
break; | break; | |||
} else { | } else { | |||
// Add it to the common prefix set | // Add it to the common prefix set | |||
commonPrefixes.add(prefixString); | commonPrefixes.add(prefixString); | |||
result.setLastEntry(prefixString); | result.setLastEntry(prefixString); | |||
// count the unique commonprefix as a | // count the unique commonprefix as a | |||
// single return entry | // single return entry | |||
resultKeyCount++; | resultKeyCount++; | |||
} | } | |||
} else { | } // else, already have this prefix, so skip | |||
// Already have this prefix, so skip | Entities.evict( objectRecord ); | |||
} | ||||
continue; | continue; | |||
} | } | |||
} | } | |||
if (resultKeyCount == maxEntries) { | if (resultKeyCount == maxEntries) { | |||
// This is a new (non-commonprefix) record, so | // This is a new (non-commonprefix) record, so | |||
// we know we're truncating | // we know we're truncating | |||
result.setIsTruncated(true); | result.setIsTruncated(true); | |||
resultKeyCount++; | ||||
break; | break; | |||
} | } | |||
result.getEntityList().add(objectRecord); | result.getEntityList().add(objectRecord); | |||
result.setLastEntry(objectRecord); | result.setLastEntry(objectRecord); | |||
resultKeyCount++; | resultKeyCount++; | |||
} | } | |||
} finally { | ||||
if (resultKeyCount <= maxEntries && objectInfos.size() <= maxEntries) | objectResults.close( ); | |||
{ | } | |||
break; | ||||
} | ||||
} while (resultKeyCount <= maxEntries); | ||||
// Sort the prefixes from the hashtable and add to the reply | // Sort the prefixes from the hashtable and add to the reply | |||
if (commonPrefixes != null) { | if (commonPrefixes != null) { | |||
result.getCommonPrefixes().addAll(commonPrefixes); | result.getCommonPrefixes().addAll(commonPrefixes); | |||
Collections.sort(result.getCommonPrefixes()); | Collections.sort(result.getCommonPrefixes()); | |||
} | } | |||
} else { | } else { | |||
throw new IllegalArgumentException("MaxKeys must be positive integer"); | throw new IllegalArgumentException("MaxKeys must be positive integer"); | |||
} | } | |||
return result; | return result; | |||
} catch (Exception e) { | } catch (Exception e) { | |||
LOG.error("Error generating paginated object list of bucket " + bucket.get BucketName(), e); | LOG.error("Error generating paginated object list of bucket " + bucket.get BucketName(), e); | |||
throw e; | throw e; | |||
} finally { | ||||
db.rollback(); | ||||
} | } | |||
} | } | |||
@Override | @Override | |||
public long countValid(Bucket bucket) throws Exception { | public long countValid(Bucket bucket) throws Exception { | |||
try (TransactionResource trans = Entities.transactionFor(ObjectEntity.class) ) { | try (TransactionResource trans = Entities.transactionFor(ObjectEntity.class) ) { | |||
/* | /* | |||
* Criteria queryCriteria = Entities.createCriteria(ObjectEntity.class); q ueryCriteria.add(Restrictions.eq("state", ObjectState.extant)) | * Criteria queryCriteria = Entities.createCriteria(ObjectEntity.class); q ueryCriteria.add(Restrictions.eq("state", ObjectState.extant)) | |||
* .createCriteria("bucket").add(Restrictions.eq("naturalId", bucket.getNa turalId())) | * .createCriteria("bucket").add(Restrictions.eq("naturalId", bucket.getNa turalId())) | |||
*/ | */ | |||
End of changes. 17 change blocks. | ||||
42 lines changed or deleted | 28 lines changed or added |