Compare commits

..

No commits in common. "3da3727cb7a30c22b0b59789c2d4e5770c5a4e6a" and "9e66fda61039722bb7cbef89ca986127c5cdd019" have entirely different histories.

3 changed files with 221 additions and 239 deletions

View File

@ -850,10 +850,6 @@ class MongoClientInterface {
{ error: err.message }); { error: err.message });
return cb(errors.InternalError); return cb(errors.InternalError);
} }
if (isUserBucket(c.s.name) && result.value) {
const objVal = result.value;
this.dataCount.delObject(objVal.value, DEL_VER);
}
return cb(null); return cb(null);
}); });
} }
@ -890,7 +886,15 @@ class MongoClientInterface {
}); });
} }
return this.deleteObjectVerNotMaster(c, bucketName, objName, return this.deleteObjectVerNotMaster(c, bucketName, objName,
params, log, cb); params, log, err => {
if (err) {
return cb(err);
}
if (isUserBucket(c.s.name)) {
this.dataCount.delObject(mst.value, DEL_VER);
}
return cb();
});
}); });
} }
@ -1114,11 +1118,12 @@ class MongoClientInterface {
if (err) { if (err) {
return next(errors.InternalError); return next(errors.InternalError);
} }
if (results.bucketList && results.dataManaged) { if (results.bucketList && results.counter &&
results.counter.dataManaged) {
res.bucketList.push(results.bucketList); res.bucketList.push(results.bucketList);
res.objects += results.objects; res.objects += results.counter.objects;
res.versions += results.versions; res.versions += results.counter.versions;
consolidateData(results.dataManaged); consolidateData(results.counter.dataManaged);
} }
return next(); return next();
}); });
@ -1134,152 +1139,168 @@ class MongoClientInterface {
return undefined; return undefined;
} }
_handleResults(res, isVersioned) { getDataManaged(c, query, log, cb) {
const total = { curr: 0, prev: 0 }; const dataManaged = {
const locations = {}; total: 0,
locations: {},
Object.keys(res.nullData).forEach(loc => {
const bytes = res.nullData[loc];
const locName = loc === 'mem' || loc === 'file' ?
'us-east-1' : loc;
if (!locations[locName]) {
locations[locName] = { curr: 0, prev: 0 };
}
total.curr += bytes;
locations[locName].curr += bytes;
});
if (isVersioned) {
Object.keys(res.versionData).forEach(loc => {
const bytes = res.versionData[loc];
const locName = loc === 'mem' || loc === 'file' ?
'us-east-1' : loc;
if (!locations[locName]) {
locations[locName] = { curr: 0, prev: 0 };
}
total.prev += bytes;
locations[locName].prev += bytes;
});
}
Object.keys(res.masterData).forEach(loc => {
const bytes = res.masterData[loc];
const locName = loc === 'mem' || loc === 'file' ?
'us-east-1' : loc;
if (!locations[locName]) {
locations[locName] = { curr: 0, prev: 0 };
}
total.curr += bytes;
locations[locName].curr += bytes;
if (isVersioned) {
total.prev -= bytes;
locations[locName].prev -= bytes;
}
});
return {
versions: isVersioned ?
res.versionCount - res.masterCount : 0,
objects: res.masterCount + res.nullCount,
dataManaged: {
total,
locations,
},
};
}
_handleCount(entry) {
return entry && entry.count > 0 ? entry.count : 0;
}
_handleEntries(entries) {
const results = {};
if (entries) {
entries.forEach(entry => {
results[entry._id] = entry.bytes;
});
}
return results;
}
_handleMongo(c, filter, log, cb) {
const reducedFields = {
'_id': 1,
'value.versionId': 1,
'value.replicationInfo.backends': 1,
'value.content-length': 1,
'value.dataStoreName': 1,
}; };
const aggCount = [ const addLocation = (site, size) => {
{ $project: { _id: 1 } }, dataManaged.total += size;
{ $group: { _id: null, count: { $sum: 1 } } }, if (!dataManaged.locations[site]) {
]; dataManaged.locations[site] = 0;
}
dataManaged.locations[site] += size;
};
const aggData = [ c.find(query).toArray((err, entries) => {
{ $project: {
'value.dataStoreName': 1,
'value.content-length': 1,
} },
{ $group: {
_id: '$value.dataStoreName',
bytes: { $sum: '$value.content-length' },
} },
];
const aggRepData = [
{ $project: {
'value.replicationInfo.backends': 1,
'value.content-length': 1,
} },
{ $unwind: '$value.replicationInfo.backends' },
{ $match: {
'value.replicationInfo.backends.status': { $eq: 'COMPLETED' },
} },
{ $group: {
_id: '$value.replicationInfo.backends.site',
bytes: { $sum: '$value.content-length' },
} },
];
return c.aggregate([
{ $project: reducedFields },
{ $match: filter },
{ $facet: {
count: aggCount,
data: aggData,
repData: aggRepData,
} },
]).toArray((err, res) => {
if (err) { if (err) {
log.error('Error when processing mongo entries', { log.error('error occured in mongo client', {
method: '_handleMongo', method: 'getDataManaged',
error: err, error: err,
}); });
return cb(err); return cb(err);
} }
if (!res || res.length < 1) {
log.debug('aggregate returned empty results', { // change to use replicatio
method: '_handleMongo', entries.forEach(entry => {
}); const { backends } = entry.value.replicationInfo || {};
return cb(null, {}); const { dataStoreName, 'content-length': size } = entry.value;
addLocation(dataStoreName, size);
if (backends && Array.isArray(backends)) {
backends.forEach(loc => {
const { site, status } = loc;
if (status === 'COMPLETED') {
addLocation(site, size);
} }
const agg = res[0];
if (!agg || !agg.count || !agg.data || !agg.repData) {
log.debug('missing field in aggregate results', {
method: '_handleMongo',
}); });
return cb(null, {});
} }
const retResult = { });
count: this._handleCount(agg.count[0] || {}), return cb(null, {
data: this._handleEntries(agg.data), objCount: entries.length,
dataManaged,
});
});
}
getDataInfoNoVer(c, log, callback) {
return this.getDataManaged(c, {}, log, (err, res) => {
if (err) {
log.error('error occured in mongo client', {
method: 'getDataInfoNoVer',
error: err,
});
return callback(err);
}
const dataManaged = {
total: { curr: 0, prev: 0 },
locations: {},
}; };
const repDataEntries = this._handleEntries(agg.repData); const data = res.dataManaged.locations;
Object.keys(repDataEntries).forEach(site => { // add total
if (!retResult.data[site]) { dataManaged.total.curr += res.dataManaged.total;
retResult.data[site] = 0; Object.keys(data).forEach(loc => {
if (!dataManaged.locations[loc]) {
dataManaged.locations[loc] = { prev: 0, curr: 0 };
} }
retResult.data[site] += repDataEntries[site]; dataManaged.locations[loc].curr = data[loc];
});
return callback(null, {
objects: res.objCount,
versions: 0,
dataManaged,
});
});
}
getDataInfoVer(c, mstVerIds, log, callback) {
// query for removing placeholder entries
/* eslint-disable quote-props */
const queryFilter = {
'$or': [
{ '_id': { '$regex': /\0.*$/g } },
{ 'value.isNull': { '$exists': true } },
{
'value.nullVersionId': { '$exists': false },
'value.versionId': { '$exists': false },
},
],
};
/* eslint-enable quote-props */
return async.series({
master: done => {
// query for getting only master version entries
const mstFilter = [];
/* eslint-disable quote-props */
mstVerIds.forEach(id => {
if (id) {
mstFilter.push({ 'value.versionId': { '$eq': id } });
}
});
const query = {
'$and': [
queryFilter,
{ '$or': (mstFilter.length ? mstFilter : [{}]) },
],
};
/* eslint-enable quote-props */
return this.getDataManaged(c, query, log, done);
},
archived: done => {
// query for getting only versioned entries
const mstFilter = [];
/* eslint-disable quote-props */
mstVerIds.forEach(id => {
if (id) {
mstFilter.push({ 'value.versionId': { '$ne': id } });
}
});
const query = {
'$and': [
queryFilter,
{ '$and': (mstFilter.length ? mstFilter : [{}]) },
],
};
/* eslint-enable quote-props */
return this.getDataManaged(c, query, log, done);
},
}, (err, res) => {
if (err) {
log.error('error occured in mongo client', {
method: 'getDataInfoVer',
error: err,
});
return callback(err);
}
const dataManaged = {
total: { curr: 0, prev: 0 },
locations: {},
};
const mstData = res.master.dataManaged.locations;
const verData = res.archived.dataManaged.locations;
// add total
dataManaged.total.curr += res.master.dataManaged.total;
dataManaged.total.prev += res.archived.dataManaged.total;
Object.keys(mstData).forEach(loc => {
if (!dataManaged.locations[loc]) {
dataManaged.locations[loc] = { prev: 0, curr: 0 };
}
dataManaged.locations[loc].curr = mstData[loc];
});
Object.keys(verData).forEach(loc => {
if (!dataManaged.locations[loc]) {
dataManaged.locations[loc] = { prev: 0, curr: 0 };
}
dataManaged.locations[loc].prev = verData[loc];
});
return callback(null, {
objects: res.master.objCount,
versions: res.archived.objCount,
dataManaged,
}); });
return cb(null, retResult);
}); });
} }
@ -1289,40 +1310,60 @@ class MongoClientInterface {
name: bucketName, name: bucketName,
location: bucketInfo.getLocationConstraint(), location: bucketInfo.getLocationConstraint(),
}; };
if (bucketInfo && bucketInfo._versioningConfiguration &&
const mstFilter = { (bucketInfo._versioningConfiguration.Status === 'Suspended' ||
'_id': { $regex: /^[^\0]+$/ }, bucketInfo._versioningConfiguration.Status === 'Enabled')) {
'value.versionId': { $exists: true }, // if versioning is enabled
}; c.distinct('_id').then(keys => {
const verFilter = { _id: { $regex: /\0/ } }; const trimmedKeys = keys.map(key => key.replace(/\0.*$/g, ''));
const nullFilter = { const uniqKeys = trimmedKeys.filter(
'_id': { $regex: /^[^\0]+$/ }, (key, index, self) => self.indexOf(key) === index);
'value.versionId': { $exists: false }, // for each uniqKey get master version id
}; return async.map(uniqKeys, (key, done) => {
this.getLatestVersion(c, key, log, (err, mst) => {
async.parallel({ if (err) {
version: done => this._handleMongo(c, verFilter, log, done), if (err.NoSuchKey) {
null: done => this._handleMongo(c, nullFilter, log, done), log.debug('NoSuchKey master info', {
master: done => this._handleMongo(c, mstFilter, log, done), method: 'getObjectMDStats',
}, (err, res) => { error: err,
});
return done();
}
log.error('unable to retrieve master info', {
method: 'getObjectMDStats',
error: err,
});
return done(err);
}
return done(null, mst.versionId);
});
}, (err, mstVerIds) => {
if (err) { if (err) {
return callback(err); return callback(err);
} }
const resObj = { return this.getDataInfoVer(c, mstVerIds, log,
masterCount: res.master.count || 0, (err, res) => {
masterData: res.master.data || {}, if (err) {
nullCount: res.null.count || 0, return callback(err);
nullData: res.null.data || {}, }
versionCount: res.version.count || 0, return callback(null, {
versionData: res.version.data || {}, bucketList: retBucketInfo,
}; counter: res,
const bucketStatus = bucketInfo.getVersioningConfiguration();
const isVer = (bucketStatus && (bucketStatus.Status === 'Enabled' ||
bucketStatus.Status === 'Suspended'));
const retResult = this._handleResults(resObj, isVer);
retResult.bucketList = retBucketInfo;
return callback(null, retResult);
}); });
});
});
}).catch(callback);
} else {
this.getDataInfoNoVer(c, log, (err, res) => {
if (err) {
return callback(err);
}
return callback(null, {
bucketList: retBucketInfo,
counter: res,
});
});
}
} }
} }

View File

@ -3,7 +3,7 @@
"engines": { "engines": {
"node": ">=6.9.5" "node": ">=6.9.5"
}, },
"version": "8.0.0-603.6", "version": "8.0.0",
"description": "Common utilities for the S3 project components", "description": "Common utilities for the S3 project components",
"main": "index.js", "main": "index.js",
"repository": { "repository": {

View File

@ -328,62 +328,3 @@ describe('MongoClientInterface::dataCount', () => {
}); });
}); });
}); });
describe('MongoClientInterface::_handleResults', () => {
it('should return zero-result', () => {
const testInput = {
masterCount: 0, masterData: {},
nullCount: 0, nullData: {},
versionCount: 0, versionData: {},
};
const testResults = mongoTestClient._handleResults(testInput, true);
const expectedRes = {
versions: 0, objects: 0,
dataManaged: {
total: { curr: 0, prev: 0 },
locations: {},
},
};
assert.deepStrictEqual(testResults, expectedRes);
});
it('should return correct value if isVer is false', () => {
const testInput = {
masterCount: 2, masterData: { test1: 10, test2: 10 },
nullCount: 2, nullData: { test1: 10, test2: 10 },
versionCount: 2, versionData: { test1: 20, test2: 20 },
};
const testResults = mongoTestClient._handleResults(testInput, false);
const expectedRes = {
versions: 0, objects: 4,
dataManaged: {
total: { curr: 40, prev: 0 },
locations: {
test1: { curr: 20, prev: 0 },
test2: { curr: 20, prev: 0 },
},
},
};
assert.deepStrictEqual(testResults, expectedRes);
});
it('should return correct value if isVer is true', () => {
const testInput = {
masterCount: 2, masterData: { test1: 10, test2: 10 },
nullCount: 2, nullData: { test1: 10, test2: 10 },
versionCount: 4, versionData: { test1: 20, test2: 20 },
};
const testResults = mongoTestClient._handleResults(testInput, true);
const expectedRes = {
versions: 2, objects: 4,
dataManaged: {
total: { curr: 40, prev: 20 },
locations: {
test1: { curr: 20, prev: 10 },
test2: { curr: 20, prev: 10 },
},
},
};
assert.deepStrictEqual(testResults, expectedRes);
});
});