From b59f03b94952f049c31eda9bb0a1adfb7cc186c7 Mon Sep 17 00:00:00 2001 From: ansuz Date: Fri, 30 Aug 2019 14:30:17 +0200 Subject: [PATCH] consider changes to metadata logs as channel activity --- storage/file.js | 98 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 75 insertions(+), 23 deletions(-) diff --git a/storage/file.js b/storage/file.js index 739f079ec..904e07e38 100644 --- a/storage/file.js +++ b/storage/file.js @@ -408,7 +408,6 @@ var removeArchivedChannel = function (env, channelName, cb) { }); }; -// TODO implement a method of removing metadata that doesn't have a corresponding channel var listChannels = function (root, handler, cb) { // do twenty things at a time var sema = Semaphore.create(20); @@ -442,38 +441,91 @@ var listChannels = function (root, handler, cb) { // ignore hidden files if (/^\./.test(item)) { return; } // ignore anything that isn't channel or metadata - if (!/^[0-9a-fA-F]{32}(\.metadata?)*\.ndjson$/.test(item)) { - return; - } + if (!/^[0-9a-fA-F]{32}(\.metadata?)*\.ndjson$/.test(item)) { return; } + + var isLonelyMetadata = false; + var channelName; + var metadataName; + + // if the current file is not the channel data, then it must be metadata if (!/^[0-9a-fA-F]{32}\.ndjson$/.test(item)) { - // this will catch metadata, which we want to ignore if - // the corresponding channel is present - if (list.indexOf(item.replace(/\.metadata/, '')) !== -1) { return; } - // otherwise fall through + metadataName = item; + + channelName = item.replace(/\.metadata/, ''); + + // if there is a corresponding channel present in the list, + // then we should stop here and handle everything when we get to the channel + if (list.indexOf(channelName) !== -1) { return; } + // otherwise set a flag indicating that we should + // handle the metadata on its own + isLonelyMetadata = true; + } else { + channelName = item; + metadataName = channelName.replace(/\.ndjson$/, '.metadata.ndjson'); } - var filepath = Path.join(nestedDirPath, item); - var channel = filepath - .replace(/\.ndjson$/, '') - .replace(/\.metadata/, '') - .replace(/.*\//, ''); + + var filePath = Path.join(nestedDirPath, channelName); + var metadataPath = Path.join(nestedDirPath, metadataName); + var channel = metadataName.replace(/\.metadata.ndjson$/, ''); if ([32, 34].indexOf(channel.length) === -1) { return; } // otherwise throw it on the pile sema.take(function (give) { var next = w(give()); - Fs.stat(filepath, w(function (err, stats) { - if (err) { - return void handler(err); + + var metaStat, channelStat; + var metaErr, channelErr; + nThen(function (ww) { + // get the stats for the metadata + Fs.stat(metadataPath, ww(function (err, stats) { + if (err) { + metaErr = err; + return; + } + metaStat = stats; + })); + + if (isLonelyMetadata) { return; } + + Fs.stat(filePath, ww(function (err, stats) { + if (err) { + channelErr = err; + return; + } + channelStat = stats; + })); + }).nThen(function () { + if (channelErr && metaErr) { + return void handler(channelErr, void 0, next); } - handler(void 0, { + var data = { channel: channel, - atime: stats.atime, - mtime: stats.mtime, - ctime: stats.ctime, - size: stats.size, - }, next); - })); + }; + + if (metaStat && channelStat) { + // take max of times returned by either stat + data.atime = Math.max(channelStat.atime, metaStat.atime); + data.mtime = Math.max(channelStat.mtime, metaStat.mtime); + data.ctime = Math.max(channelStat.ctime, metaStat.ctime); + // return the sum of the size of the two files + data.size = channelStat.size + metaStat.size; + } else if (metaStat) { + data.atime = metaStat.atime; + data.mtime = metaStat.mtime; + data.ctime = metaStat.ctime; + data.size = metaStat.size; + } else if (channelStat) { + data.atime = channelStat.atime; + data.mtime = channelStat.mtime; + data.ctime = channelStat.ctime; + data.size = channelStat.size; + } else { + return void handler('NO_DATA', void 0, next); + } + + handler(void 0, data, next); + }); }); }); })));