Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 52 additions & 9 deletions lib/routes/routeBackbeat.js
Original file line number Diff line number Diff line change
Expand Up @@ -491,24 +491,67 @@ function putMetadata(request, response, bucketInfo, objMd, log, callback) {
omVal[headerName] = objMd[headerName];
});
}
const versionId = decodeVersionId(request.query);
const options = {};
if (versionId || omVal.replicationInfo.isNFS) {
// specify both 'versioning' and 'versionId' to create a "new"
// version (updating master as well) but with specified
// versionId
options.versioning = bucketInfo.isVersioningEnabled();
options.versionId = versionId;

let versionId;
let versioning;
const decodedVidResult = decodeVersionId(request.query);

if (decodedVidResult || omVal.replicationInfo.isNFS) {
versionId = decodedVidResult;
versioning = bucketInfo.isVersioningEnabled();
}

if (versionId === 'null') {
// Retrieve the null version id from the object metadata.
versionId = objMd && objMd.versionId;
if (!versionId) {
if (versioning) {
// If the null version does not have a version id, it is a current null version.
// To update the metadata of a current version, versioning is set to false.

// This condition is to handle the case where a single null version looks like a master
// key and will not have a duplicate versioned key and no version ID.
// They are created when you have a non-versioned bucket with objects,
// and then convert bucket to versioned.
// If no new versioned objects are added for given object(s), they look like
// standalone master keys.
versioning = false;
} else {
const versioningConf = bucketInfo.getVersioningConfiguration();
// The purpose of this condition is to address situations in which
// - versioning is "suspended" and
// - no existing object or no null version.
// In such scenarios, we generate a new null version and designate it as the master version.
if (versioningConf && versioningConf.Status === 'Suspended') {
versionId = '';
omVal.isNull = true;
}
}
}
}

// If the object is from a source bucket without versioning (i.e. NFS),
// then we want to create a version for the replica object even though
// none was provided in the object metadata value.
if (omVal.replicationInfo.isNFS) {
const isReplica = omVal.replicationInfo.status === 'REPLICA';
options.versioning = isReplica;
versioning = isReplica;
omVal.replicationInfo.isNFS = !isReplica;
}

const options = {
versionId,
};

// NOTE: When 'versioning' is set to true and no 'versionId' is specified,
// it results in the creation of a "new" version, which also updates the master.
// NOTE: Since option fields are converted to strings when they're sent to Metadata via the query string,
// Metadata interprets the value "false" as if it were true.
// Therefore, to avoid this confusion, we don't pass the versioning parameter at all if its value is false.
if (versioning) {
options.versioning = true;
}

log.trace('putting object version', {
objectKey: request.objectKey, omVal, options });
return metadata.putObjectMD(bucketName, objectKey, omVal, options, log,
Expand Down
Loading