}
if(ctx.hasAdministrativePrivileges() || (bucket.canWrite(account.getAccountNumber()) && (bucket.isGlobalWrite() ||
Lookups.checkPrivilege(PolicySpec.S3_PUTOBJECT, PolicySpec.VENDOR_S3, PolicySpec.S3_RESOURCE_BUCKET, bucketName, null)))) {
<<<<<<< HEAD
AccessControlList accessControlList = request.getAccessControlList();
if (accessControlList == null) {
accessControlList = new AccessControlList();
}
EntityWrapper dbPart = db.recast(PartInfo.class);
// Create a manifest object entity
PartInfo manifest = PartInfo.create(bucketName, objectKey, account);
manifest.setStorageClass("STANDARD");
manifest.setContentEncoding(request.getContentEncoding());
manifest.setContentType(request.getContentType());
List grantInfos = new ArrayList();
manifest.addGrants(account.getAccountNumber(), bucket.getOwnerId(), grantInfos, accessControlList);
manifest.setGrants(grantInfos);
manifest.replaceMetaData(request.getMetaData());
manifest.setObjectName(null);
dbPart.add(manifest);
try {
dbPart.commit();
} catch (RollbackException ex) {
dbPart.rollback();
LOG.error("Error comitting new object entity to database", ex);
}
reply.setUploadId(manifest.getUploadId());
} else {
db.rollback();
throw new AccessDeniedException("Bucket", bucketName);
}
} else {
db.rollback();
throw new NoSuchBucketException(bucketName);
}
reply.setBucket(bucketName);
reply.setKey(objectKey);
return reply;
}
public UploadPartResponseType uploadPart(UploadPartType request) throws EucalyptusCloudException {
UploadPartResponseType reply = (UploadPartResponseType) request.getReply();
Context ctx = Contexts.lookup();
Account account = ctx.getAccount();
String bucketName = request.getBucket();
String objectKey = request.getKey();
String key = bucketName + "." + objectKey;
String randomKey = request.getRandomKey();
String uploadId = request.getUploadId();
Integer partNumber = Integer.parseInt(request.getPartNumber());
WalrusDataMessenger messenger = WalrusRESTBinding.getWriteMessenger();
Date lastModified = null;
String md5 = new String();
Long oldBucketSize = 0L; //TODO compute this correctly later
EntityWrapper db = EntityWrapper.get(BucketInfo.class);
BucketInfo bucketInfo = new BucketInfo(bucketName);
List bucketList = db.queryEscape(bucketInfo);
if(bucketList.size() > 0) {
BucketInfo bucket = bucketList.get(0);
BucketLogData logData = bucket.getLoggingEnabled() ? request.getLogData() : null;
long objSize = 0;
try {
objSize = Long.valueOf(request.getContentLength());
} catch (NumberFormatException e) {
LOG.error("Invalid content length " + request.getContentLength());
//TODO: FIXME This should be a MissingContentLengthException
throw new EucalyptusCloudException("Missing Content-Length");
}
if(ctx.hasAdministrativePrivileges() || (bucket.canWrite(account.getAccountNumber()) && (bucket.isGlobalWrite() ||
Lookups.checkPrivilege(PolicySpec.S3_PUTOBJECT, PolicySpec.VENDOR_S3, PolicySpec.S3_RESOURCE_BUCKET, bucketName, null)))) {
String objectName = null;
PartInfo partInfo = null;
try {
PartInfo searchManifest = new PartInfo(bucketName, objectKey);
searchManifest.setUploadId(uploadId);
searchManifest.setCleanup(Boolean.FALSE);
EntityWrapper dbPart = db.recast(PartInfo.class);
Criteria partCriteria = dbPart.createCriteria(PartInfo.class);
partCriteria.add(Example.create(searchManifest));
partCriteria.add(Restrictions.isNull("partNumber"));
List found = partCriteria.list();
if (found.size() == 0) {
db.rollback();
throw new EucalyptusCloudException("Multipart upload ID is invalid. Intitiate a multipart upload request before uploading the parts");
}
if (found.size() > 1) {
db.rollback();
throw new EucalyptusCloudException("Multiple manifests found for same uploadId");
}
PartInfo foundManifest = found.get(0);
partInfo = PartInfo.create(bucketName, objectKey, account);
partInfo.setUploadId(uploadId);
partInfo.setPartNumber(partNumber);
partInfo.setCleanup(Boolean.FALSE);
objectName = partInfo.getObjectName();
dbPart.add(partInfo);
dbPart.commit();
} catch (Exception ex) {
throw new EucalyptusCloudException(ex);
}
// writes are unconditional
WalrusDataQueue putQueue = messenger.getQueue(key, randomKey);
try {
WalrusDataMessage dataMessage;
String tempObjectName = objectName;
MessageDigest digest = null;
long size = 0;
FileIO fileIO = null;
while ((dataMessage = putQueue.take()) != null) {
if (putQueue.getInterrupted()) {
if (WalrusDataMessage.isEOF(dataMessage)) {
WalrusMonitor monitor = messenger.getMonitor(key);
if (monitor.getLastModified() == null) {
LOG.trace("Monitor wait: " + key
+ " random: " + randomKey);
synchronized (monitor) {
monitor.wait();
}
}
LOG.trace("Monitor resume: " + key + " random: " + randomKey);
lastModified = monitor.getLastModified();
md5 = monitor.getMd5();
// ok we are done here
if (fileIO != null) {
fileIO.finish();
}
ObjectDeleter objectDeleter = new ObjectDeleter(bucketName, tempObjectName, null, null, null,-1L,
ctx.getUser().getName(),
ctx.getUser().getUserId(),
ctx.getAccount().getName(),
ctx.getAccount().getAccountNumber());
Threads.lookup(Walrus.class, WalrusFSManager.ObjectDeleter.class).limitTo(10).submit(objectDeleter);
LOG.info("Transfer interrupted: " + key);
messenger.removeQueue(key, randomKey);
break;
}
continue;
}
if (WalrusDataMessage.isStart(dataMessage)) {
tempObjectName = UUID.randomUUID().toString();
digest = Digest.MD5.get();
try {
fileIO = storageManager.prepareForWrite(bucketName, tempObjectName);
} catch (Exception ex) {
messenger.removeQueue(key, randomKey);
throw new EucalyptusCloudException(ex);
}
} else if (WalrusDataMessage.isEOF(dataMessage)) {
if (digest != null) {
md5 = Hashes.bytesToHex(digest.digest());
} else {
WalrusMonitor monitor = messenger.getMonitor(key);
md5 = monitor.getMd5();
lastModified = monitor.getLastModified();
if (md5 == null) {
LOG.error("ETag did not match for: " + randomKey + " Computed MD5 is null");
throw new ContentMismatchException(bucketName + "/" + objectKey);
}
break;
}
String contentMD5 = request.getContentMD5();
if (contentMD5 != null) {
String contentMD5AsHex = Hashes.bytesToHex(Base64.decode(contentMD5));
if (!contentMD5AsHex.equals(md5)) {
if (fileIO != null) {
fileIO.finish();
}
cleanupTempObject(ctx, bucketName, tempObjectName);
messenger.removeQueue(key, randomKey);
LOG.error("ETag did not match for: " + randomKey + " Expected: " + contentMD5AsHex + " Computed: " + md5);
throw new ContentMismatchException(bucketName + "/" + objectKey);
}
}
// Fix for EUCA-2275:
// Moved up policy and bucket size checks on the temporary object. The temp object is committed (renamed) only after it clears the checks.
// If any of the checks fail, temp object is cleaned up and the process errors out. If the PUT request is overwriting an existing object, the object is left untouched.
// So the fix ensures proper clean up of temp files (no orphaned files) and does not overwrite existing data when policy or bucket size checks fail
if (!ctx.hasAdministrativePrivileges() &&
!Permissions.canAllocate(PolicySpec.VENDOR_S3, PolicySpec.S3_RESOURCE_OBJECT, bucketName, PolicySpec.S3_PUTOBJECT, ctx.getUser(), oldBucketSize + size)) {
// dbObject.rollback();
cleanupTempObject(ctx, bucketName, tempObjectName);
messenger.removeQueue(key, randomKey);
LOG.error("Quota exceeded for Walrus putObject");
throw new EntityTooLargeException("Key", objectKey);
}
// commit object
try {
if (fileIO != null) {
fileIO.finish();
}
storageManager.renameObject(bucketName, tempObjectName, objectName);
} catch (IOException ex) {
LOG.error(ex);
messenger.removeQueue(key, randomKey);
throw new EucalyptusCloudException(objectKey);
}
lastModified = new Date();
PartInfo searchPart = new PartInfo(bucketName, objectKey);
//objectName is guaranteed to be unique
searchPart.setObjectName(objectName);
searchPart.setPartNumber(partNumber);
searchPart.setUploadId(uploadId);
EntityWrapper dbPart = EntityWrapper.get(PartInfo.class);
PartInfo foundPart = null;
try {
foundPart = dbPart.getUniqueEscape(searchPart);
} catch (EucalyptusCloudException ex) {
dbPart.rollback();
throw new EucalyptusCloudException("Unable to update part: " + bucketName + "/" + objectKey + " uploadId: " + uploadId + " partNumber: " + partNumber);
}
foundPart.setEtag(md5);
foundPart.setSize(size);
foundPart.setLastModified(lastModified);
foundPart.setCleanup(false);
foundPart.setStorageClass("STANDARD");
reply.setSize(size);
try {
dbPart.commit();
} catch (RollbackException ex) {
dbPart.rollback();
LOG.error(ex, ex);
}
// restart all interrupted puts
WalrusMonitor monitor = messenger.getMonitor(key);
synchronized (monitor) {
monitor.setLastModified(lastModified);
monitor.setMd5(md5);
monitor.notifyAll();
}
// messenger.removeMonitor(key);
messenger.clearQueues(key);
messenger.removeQueue(key, randomKey);
LOG.info("Transfer complete: " + key + " uploadId: " + uploadId + " partNumber: " + partNumber);
/*try {
fireObjectCreationEvent(bucketName, objectKey, versionId, ctx.getUser().getUserId(), size, oldObjectSize);
} catch (Exception ex) {
LOG.debug("Failed to fire reporting event for walrus PUT object operation", ex);
}*/
break;
} else {
assert (WalrusDataMessage.isData(dataMessage));
byte[] data = dataMessage.getPayload();
// start writing object (but do not commit yet)
try {
if (fileIO != null)
fileIO.write(data);
} catch (IOException ex) {
LOG.error(ex);
}
// calculate md5 on the fly
size += data.length;
if (digest != null) {
digest.update(data);
}
}
}
} catch (Exception ex) {
LOG.error(ex, ex);
db.rollback();
messenger.removeQueue(key, randomKey);
throw new EucalyptusCloudException("Transfer interrupted: " + key + "." + randomKey);
}
} else {
db.rollback();
messenger.removeQueue(key, randomKey);
throw new AccessDeniedException("Bucket", bucketName, logData);
}
} else {
db.rollback();
messenger.removeQueue(key, randomKey);
throw new NoSuchBucketException(bucketName);
}
reply.setEtag(md5);
reply.setLastModified(DateUtils.format(lastModified.getTime(), DateUtils.RFC822_DATETIME_PATTERN));
return reply;
}
throw ex;
public CompleteMultipartUploadResponseType completeMultipartUpload(CompleteMultipartUploadType request) throws EucalyptusCloudException {
CompleteMultipartUploadResponseType reply = (CompleteMultipartUploadResponseType) request.getReply();
Context ctx = Contexts.lookup();
Account account = ctx.getAccount();
String bucketName = request.getBucket();
String objectKey = request.getKey();
List requestParts = request.getParts();
EntityWrapper db = EntityWrapper.get(BucketInfo.class);
BucketInfo bucketInfo = new BucketInfo(bucketName);
List bucketList = db.queryEscape(bucketInfo);
if (bucketList.size() > 0) {
BucketInfo bucket = bucketList.get(0);
if(ctx.hasAdministrativePrivileges() || (bucket.canWrite(account.getAccountNumber()) && (bucket.isGlobalWrite() ||
Lookups.checkPrivilege(PolicySpec.S3_PUTOBJECT, PolicySpec.VENDOR_S3, PolicySpec.S3_RESOURCE_BUCKET, bucketName, null)))) {
try {
// Find the manifest entity
PartInfo searchManifest = new PartInfo(bucketName, objectKey);
searchManifest.setUploadId(request.getUploadId());
searchManifest.setCleanup(Boolean.FALSE);
EntityWrapper dbPart = db.recast(PartInfo.class);
Criteria partCriteria = dbPart.createCriteria(PartInfo.class);
partCriteria.add(Example.create(searchManifest));
partCriteria.add(Restrictions.isNull("partNumber"));
List found = partCriteria.list();
if (found.size() == 0) {
db.rollback();
throw new EucalyptusCloudException("Multipart upload ID is invalid. Intitiate a multipart upload request before uploading the parts");
}
if (found.size() > 1) {
db.rollback();
throw new EucalyptusCloudException("Multiple manifests found for same uploadId");
}
PartInfo foundManifest = found.get(0);
if (foundManifest != null) {
long oldBucketSize = 0L;
long oldObjectSize = 0L;
//check if we can write to the object if it already exists
String versionId = null;
if (bucket.isVersioningEnabled()) {
versionId = foundManifest.getVersionId();
} else {
}
versionId = WalrusProperties.NULL_VERSION_ID;
ObjectInfo searchObject = new ObjectInfo(bucketName, objectKey);
searchObject.setVersionId(versionId);
EntityWrapper dbObject = db.recast(ObjectInfo.class);
try {
ObjectInfo foundObject = dbObject.getUniqueEscape(searchObject);
if (!foundObject.canWrite(account.getAccountNumber())) {
// Found existing object, but don't have write
// access
db.rollback();
throw new AccessDeniedException("Key", objectKey);
}
//check if we can write ACP
if(foundManifest.getGrants().size() > 0 && (!foundObject.canWriteACP(account.getAccountNumber()))) {
db.rollback();
throw new AccessDeniedException("Key", objectKey);
}
oldObjectSize = foundObject.getSize() == null ? 0L : foundObject.getSize();
// Fix for EUCA-2275:
// If an existing object is overwritten, the size
// difference must be taken into account. Size of the
// already existing object was ignored before
oldBucketSize = -oldObjectSize;
} catch (AccessDeniedException ex) {
} catch (EucalyptusCloudException ex) {
// No existing object found
}
}
// Look for the parts
PartInfo searchPart = new PartInfo(bucketName, objectKey);
searchPart.setUploadId(request.getUploadId());
partCriteria = dbPart.createCriteria(PartInfo.class);
partCriteria.add(Example.create(searchManifest));
partCriteria.add(Restrictions.isNotNull("partNumber"));
List foundParts = partCriteria.list();
String eTagString = "";
long size = 0;
if(foundParts != null && foundParts.size() > 0) {
if(requestParts != null && requestParts.size() > foundParts.size()) {
throw new EucalyptusCloudException("One or more parts has not been uploaded yet. Either upload the part or fix the manifest");
} else {
// Create a hashmap
Map partsMap = new HashMap(foundParts.size());
for(PartInfo foundPart : foundParts) {
partsMap.put(foundPart.getPartNumber(), foundPart);
}
PartInfo lookupPart = null;
for(Part requestPart : requestParts){
if((lookupPart = partsMap.get(requestPart.getPartNumber())) != null) {
lookupPart.setCleanup(Boolean.FALSE);
eTagString += lookupPart.getEtag();
size += lookupPart.getSize();
partsMap.remove(lookupPart.getPartNumber());
} else {
//TODO: This needs to be an InvalidPart exception
throw new EucalyptusCloudException("Part not found");
}
}
MessageDigest digest = Digest.MD5.get();
digest.update(eTagString.getBytes());
final String eTag = "uuid-" + Hashes.bytesToHex(digest.digest());
foundManifest.setEtag(eTag);
foundManifest.setCleanup(Boolean.FALSE);
if (!ctx.hasAdministrativePrivileges()
&& !Permissions.canAllocate(PolicySpec.VENDOR_S3, PolicySpec.S3_RESOURCE_OBJECT, bucketName, PolicySpec.S3_PUTOBJECT,
ctx.getUser(), oldBucketSize + size)) {
// dbObject.rollback();
LOG.error("Quota exceeded for Walrus putObject");
throw new EntityTooLargeException("Key", objectKey);
}
boolean success = false;
int retryCount = 0;
do {
try {
incrementBucketSize(bucketName, objectKey, oldBucketSize, size);
success = true;
} catch (EntityTooLargeException ex) {
// dbObject.rollback();
throw ex;
} catch (NoSuchBucketException ex) {
// dbObject.rollback();
throw ex;
} catch (RollbackException ex) {
retryCount++;
LOG.trace("retrying update: " + bucketName);
} catch (EucalyptusCloudException ex) {
// dbObject.rollback();
throw ex;
}
} while (!success && (retryCount < 5));
ObjectInfo objectInfo = new ObjectInfo(bucketName, objectKey);
objectInfo.setCleanup(false);
objectInfo.setEtag(eTag);
objectInfo.setUploadId(foundManifest.getUploadId());
objectInfo.setDeleted(false);
objectInfo.setSize(size);
objectInfo.setLastModified(new Date());
objectInfo.setVersionId(versionId);
objectInfo.setStorageClass(foundManifest.getStorageClass());
objectInfo.setContentDisposition(foundManifest.getContentDisposition());
objectInfo.setContentType(foundManifest.getContentType());
objectInfo.setLast(true);
objectInfo.setDeleted(false);
objectInfo.updateGrants(foundManifest);
EntityWrapper dbOject = db.recast(ObjectInfo.class);
dbOject.add(objectInfo);
//cleanup unused parts
Set keys = partsMap.keySet();
for (Integer key : keys) {
partsMap.get(key).markForCleanup();
}
db.commit();
reply.setEtag(foundManifest.getEtag()); // TODO figure out etag correctly
reply.setLocation("Walrus" + foundManifest.getBucketName() + "/" + foundManifest.getObjectKey());
reply.setBucket(foundManifest.getBucketName());
reply.setKey(foundManifest.getObjectKey());
//fire cleanup
firePartsCleanupTask(foundManifest.getBucketName(), request.getKey(), request.getUploadId());
}
} else {
throw new EucalyptusCloudException("No parts found in the database");
}
} else {
throw new EucalyptusCloudException("Multipart upload ID is invalid.");
}
} catch (Exception ex) {
db.rollback();
throw new EucalyptusCloudException(ex);
}
} else {
db.rollback();
throw new AccessDeniedException("Bucket", bucketName);
}
} else {
db.rollback();
throw new NoSuchBucketException(bucketName);
}
reply.setLocation(request.getBucket() + '/' + request.getKey());
reply.setBucket(request.getBucket());
reply.setKey(request.getKey());
return reply;
}
public AbortMultipartUploadResponseType abortMultipartUpload(AbortMultipartUploadType request) throws EucalyptusCloudException {
AbortMultipartUploadResponseType reply = (AbortMultipartUploadResponseType) request.getReply();
Context ctx = Contexts.lookup();
Account account = ctx.getAccount();
String bucketName = request.getBucket();
String objectKey = request.getKey();
EntityWrapper db = EntityWrapper.get(BucketInfo.class);
BucketInfo bucketInfo = new BucketInfo(bucketName);
List bucketList = db.queryEscape(bucketInfo);
if (bucketList.size() > 0) {
BucketInfo bucket = bucketList.get(0);
if(ctx.hasAdministrativePrivileges() || (bucket.canWrite(account.getAccountNumber()) && (bucket.isGlobalWrite() ||
Lookups.checkPrivilege(PolicySpec.S3_PUTOBJECT, PolicySpec.VENDOR_S3, PolicySpec.S3_RESOURCE_BUCKET, bucketName, null)))) {
try {
// Find the manifest entity
EntityWrapper dbPart = db.recast(PartInfo.class);
PartInfo searchManifest = new PartInfo(bucketName, objectKey);
searchManifest.setUploadId(request.getUploadId());
searchManifest.setCleanup(Boolean.FALSE);
Criteria partCriteria = dbPart.createCriteria(PartInfo.class);
partCriteria.add(Example.create(searchManifest));
partCriteria.add(Restrictions.isNull("partNumber"));
List found = partCriteria.list();
if (found.size() == 0) {
db.rollback();
throw new EucalyptusCloudException("Multipart upload ID is invalid. Intitiate a multipart upload request before uploading the parts");
}
if (found.size() > 1) {
db.rollback();
throw new EucalyptusCloudException("Multiple manifests found for same uploadId");
}
PartInfo foundManifest = found.get(0);
if (foundManifest != null) {
// Look for the parts
foundManifest.markForCleanup();
PartInfo searchPart = new PartInfo(bucketName, objectKey);
searchPart.setUploadId(request.getUploadId());
List foundParts = dbPart.queryEscape(searchPart);
if(foundParts != null && foundParts.size() > 0) {
for (PartInfo part : foundParts) {
part.markForCleanup();
}
} else {
throw new EucalyptusCloudException("No parts found for upload: " + request.getUploadId());
}
db.commit();
//fire cleanup
firePartsCleanupTask(foundManifest.getBucketName(), foundManifest.getObjectKey(), request.getUploadId());
} else {
throw new EucalyptusCloudException("Multipart upload ID is invalid.");
}
} catch (Exception ex) {
db.rollback();
throw new EucalyptusCloudException(ex);
}
} else {
db.rollback();
throw new AccessDeniedException("Bucket", bucketName);
}
} else {
db.rollback();
throw new NoSuchBucketException(bucketName);
}
return reply;
}
private void firePartsCleanupTask(final String bucketName, final String objectKey, final String uploadId) {
try {
MPU_EXECUTOR.submit(new Runnable() {
public void run() {
try {
doPartCleanup(bucketName, objectKey, uploadId);
} catch (final Throwable f) {
LOG.error("Error during part cleanup for " + bucketName + "/" + objectKey + " uploadId: " + uploadId, f);
}
}
});
} catch (final Throwable f) {
LOG.warn("Error cleaning parts for " + bucketName + "/" + objectKey + " uploadId: " + uploadId + " .", f);
}
}
private void doPartCleanup(String bucketName, String objectKey, String uploadId) {
//get all parts
PartInfo searchPart = new PartInfo(bucketName, objectKey);
searchPart.setCleanup(true);
searchPart.setUploadId(uploadId);
List parts;
EntityTransaction db = Entities.get(PartInfo.class);
try {
parts = Entities.query(searchPart);
if(parts.size() > 0) {
for (PartInfo part : parts) {
if (part.getObjectName() != null) {
try {
storageManager.deleteObject(bucketName, part.getObjectName());
} catch (IOException e) {
LOG.error("Unable to delete part on disk: " + e.getMessage());
}
}
LOG.info("Garbage collecting part: " + part.getBucketName() + "/" + part.getObjectName() + " partNumber: " + part.getPartNumber() + " uploadId: " + part.getUploadId());
if (part.getGrants() != null) {
for (GrantInfo grant : part.getGrants()) {
Entities.delete(grant);
}
}
Entities.delete(part);
}
}
} finally {
db.commit();
}
}
=======
/* the reporting is now done in the OSG
try {
fireObjectCreationEvent(bucketName, objectKey, versionId, ctx.getUser().getUserId(), size, oldObjectSize);
} catch (Exception ex) {
LOG.debug("Failed to fire reporting event for walrus PUT object operation", ex);
}
*/
break;
} else {
assert (WalrusDataMessage.isData(dataMessage));
byte[] data = dataMessage.getPayload();
// start writing object (but do not commit yet)
try {
if (fileIO != null)
fileIO.write(data);
} catch (IOException ex) {
LOG.error(ex);
}
// calculate md5 on the fly
size += data.length;
if (digest != null) {
digest.update(data);
}
}
}
} catch (Exception ex) {
LOG.error(ex, ex);
db.rollback();
messenger.removeQueue(key, randomKey);
throw new EucalyptusCloudException("Transfer interrupted: " + key + "." + randomKey);
}
} else {
db.rollback();
messenger.removeQueue(key, randomKey);
throw new AccessDeniedException("Bucket", bucketName, logData);
}
} else {
db.rollback();
messenger.removeQueue(key, randomKey);
throw new NoSuchBucketException(bucketName);
}
reply.setEtag(md5); // TODO figure out etag correctly
reply.setLastModified(DateUtils.format(lastModified.getTime(), DateUtils.RFC822_DATETIME_PATTERN));
return reply;
public CompleteMultipartUploadResponseType completeMultipartUpload(CompleteMultipartUploadType request) throws EucalyptusCloudException {
CompleteMultipartUploadResponseType reply = (CompleteMultipartUploadResponseType) request.getReply();
Context ctx = Contexts.lookup();
Account account = ctx.getAccount();
String bucketName = request.getBucket();
String objectKey = request.getKey();
List requestParts = request.getParts();
EntityWrapper db = EntityWrapper.get(BucketInfo.class);
BucketInfo bucketInfo = new BucketInfo(bucketName);
List bucketList = db.queryEscape(bucketInfo);
if (bucketList.size() > 0) {
BucketInfo bucket = bucketList.get(0);
if(ctx.hasAdministrativePrivileges() || (bucket.canWrite(account.getAccountNumber()) && (bucket.isGlobalWrite() ||
Lookups.checkPrivilege(PolicySpec.S3_PUTOBJECT, PolicySpec.VENDOR_S3, PolicySpec.S3_RESOURCE_BUCKET, bucketName, null)))) {
try {
// Find the manifest entity
ObjectInfo searchManifest = new ObjectInfo(bucketName, objectKey);
searchManifest.setUploadId(request.getUploadId());
searchManifest.setManifest(Boolean.TRUE);
EntityWrapper dbObject = db.recast(ObjectInfo.class);
ObjectInfo foundManifest = dbObject.uniqueResultEscape(searchManifest);
if (foundManifest != null) {
// Look for the parts
ObjectInfo searchPart = new ObjectInfo(bucketName, objectKey);
searchPart.setUploadId(request.getUploadId());
searchPart.setManifest(Boolean.FALSE);
List foundParts = dbObject.queryEscape(searchPart);
if(foundParts != null && foundParts.size() > 0) {
if(requestParts != null && requestParts.size() > foundParts.size()) {
throw new EucalyptusCloudException("One or more parts has not been uploaded yet. Either upload the part or fix the manifest");
} else {
// Create a hashmap
Map partsMap = new HashMap(foundParts.size());
for(ObjectInfo foundPart : foundParts) {
foundPart.setCleanup(Boolean.TRUE);
foundPart.setUploadComplete(Boolean.TRUE);
partsMap.put(foundPart.getPartNumber(), foundPart);
}
ObjectInfo lookupPart = null;
for(Part requestPart : requestParts){
if((lookupPart = partsMap.get(requestPart.getPartNumber())) != null) {
lookupPart.setCleanup(Boolean.FALSE);
} else {
throw new EucalyptusCloudException("Part not found");
}
}
foundManifest.setCleanup(Boolean.FALSE);
foundManifest.setUploadComplete(Boolean.TRUE);
db.commit();
}
} else {
throw new EucalyptusCloudException("No parts found in the database");
}
} else {
throw new EucalyptusCloudException("Multipart upload ID is invalid.");
}
} catch (Exception ex) {
db.rollback();
throw new EucalyptusCloudException(ex);
}
} else {
db.rollback();
throw new AccessDeniedException("Bucket", bucketName);
}
} else {
db.rollback();
throw new NoSuchBucketException(bucketName);
}
reply.setLocation(request.getBucket() + '/' + request.getKey());
reply.setBucket(request.getBucket());
reply.setKey(request.getKey());
reply.setEtag(Crypto.generateAlphanumericId(16, "")); // TODO figure out etag correctly
return reply;
}
public AbortMultipartUploadResponseType abortMultipartUpload(AbortMultipartUploadType request) {
AbortMultipartUploadResponseType reply = (AbortMultipartUploadResponseType) request.getReply();
return reply;
}
>>>>>>> 2b88afc1831d36dcdd53595f60c738380252791a
|