Explorar o código

Работа над MegaStorage

Book Pauk %!s(int64=5) %!d(string=hai) anos
pai
achega
454a62dbb9
Modificáronse 1 ficheiros con 107 adicións e 15 borrados
  1. 107 15
      server/core/LibSharedStorage/MegaStorage.js

+ 107 - 15
server/core/LibSharedStorage/MegaStorage.js

@@ -1,12 +1,43 @@
+const _ = require('lodash');
 const fs = require('fs-extra');
 const path = require('path');
+
+const log = new (require('../AppLogger'))().log;//singleton
 const ZipStreamer = require('../ZipStreamer');
 
 const utils = require('../utils');
 
+const zeroStats = {
+    zipFilesCount: 0,
+    descFilesCount: 0,
+    zipFilesSize: 0,
+    descFilesSize: 0,
+};
+
+let instance = null;
+
+//singleton
 class MegaStorage {
     constructor() {
-        this.inited = false;
+        if (!instance) {
+            this.inited = false;
+
+            this.debouncedSaveStats = _.debounce(() => {
+                this.saveStats().catch((e) => {
+                    log(LM_ERR, `MegaStorage::saveStats ${e.message}`);
+                    //process.exit(1);
+                });
+            }, 5000, {'maxWait':6000});
+
+            process.on('exit', () => {
+                this.saveStatsSync();
+            });
+
+
+            instance = this;
+        }
+
+        return instance;
     }
 
     async init(config) {
@@ -17,12 +48,12 @@ class MegaStorage {
         await fs.ensureDir(this.megaStorageDir);
 
         this.readingFiles = false;
-        this.stats = {};
+        this.stats = _.cloneDeep(zeroStats);
 
         if (await fs.pathExists(this.statsPath)) {
             this.stats = Object.assign({},
-                JSON.parse(await fs.readFile(this.statsPath, 'utf8')),
-                this.stats
+                this.stats,
+                JSON.parse(await fs.readFile(this.statsPath, 'utf8'))
             );
         }
 
@@ -31,7 +62,7 @@ class MegaStorage {
 
     async nameHash(filename) {
         if (!this.inited)
-            throw new Error('MegaStorage::not inited');
+            throw new Error('not inited');
         const hash = utils.toBase36(await utils.getFileHash(filename, 'sha1'));
         const hashPath = `${hash.substr(0, 2)}/${hash.substr(2, 2)}/${hash}`;
         const fullHashPath = `${this.megaStorageDir}/${hashPath}`;
@@ -51,11 +82,18 @@ class MegaStorage {
 
     async addFile(nameHash, desc = null, force = false) {
         if (!this.inited)
-            throw new Error('MegaStorage::not inited');
+            throw new Error('not inited');
         if (await this.checkFileExists(nameHash) && !force)
             return false;
 
         await fs.ensureDir(path.dirname(nameHash.zipPath));
+        let oldZipSize = 0;
+        let newZipCount = 1;
+        if (await fs.pathExists(nameHash.zipPath)) {
+            oldZipSize = (await fs.stat(nameHash.zipPath)).size;
+            newZipCount = 0;
+        }
+
         const zip = new ZipStreamer();
         let entry = {};
         let resultFile = await zip.pack(nameHash.zipPath, [nameHash.filename], {zlib: {level: this.compressLevel}}, (ent) => {
@@ -64,22 +102,40 @@ class MegaStorage {
 
         if (desc) {
             desc = Object.assign({}, desc, {fileSize: entry.size, zipFileSize: resultFile.size});
-            this.updateDesc(nameHash, desc);
+            await this.updateDesc(nameHash, desc);
         }
+
+        this.stats.zipFilesSize += -oldZipSize + resultFile.size;
+        this.stats.zipFilesCount += newZipCount;
+        this.needSaveStats = true;
+
+        this.debouncedSaveStats();
         return desc;
     }
 
     async updateDesc(nameHash, desc) {
-        await fs.writeFile(nameHash.descPath, JSON.stringify(desc, null, 2));
+        let oldDescSize = 0;
+        let newDescCount = 1;
+        if (await fs.pathExists(nameHash.descPath)) {
+            oldDescSize = (await fs.stat(nameHash.descPath)).size;
+            newDescCount = 0;
+        }
+
+        const data = JSON.stringify(desc, null, 2);
+        await fs.writeFile(nameHash.descPath, data);
+
+        this.stats.descFilesSize += -oldDescSize + data.length;
+        this.stats.descFilesCount += newDescCount;
+        this.needSaveStats = true;
+
+        this.debouncedSaveStats();
     }
 
     async _findFiles(callback, dir) {
         if (!callback || !this.readingFiles)
             return;
-        if (!dir)
-            dir = this.megaStorageDir;
 
-        let result;
+        let result = true;
         const files = await fs.readdir(dir, { withFileTypes: true });
         for (const file of files) {
             if (!this.readingFiles)
@@ -88,17 +144,17 @@ class MegaStorage {
             if (file.isDirectory())
                 result = await this._findFiles(callback, found);
             else
-                callback(found);
+                await callback(found);
         }
         return result;
     }
 
-    async startFindFiles(callback, dir) {
+    async startFindFiles(callback) {
         if (!this.inited)
-            throw new Error('MegaStorage::not inited');
+            throw new Error('not inited');
         this.readingFiles = true;
         try {
-            return await this._findFiles(callback, dir);
+            return await this._findFiles(callback, this.megaStorageDir);
         } finally {
             this.readingFiles = false;
         }
@@ -108,9 +164,45 @@ class MegaStorage {
         this.readingFiles = false;
     }
 
+    async saveStats() {
+        if (this.needSaveStats) {
+            await fs.writeFile(this.statsPath, JSON.stringify(this.stats, null, 2));
+            this.needSaveStats = false;
+        }
+    }
+
+    saveStatsSync() {
+        if (this.needSaveStats) {
+            fs.writeFileSync(this.statsPath, JSON.stringify(this.stats, null, 2));
+            this.needSaveStats = false;
+        }
+    }
+
     async getStats(gather = false) {
         if (!this.inited)
             throw new Error('MegaStorage::not inited');
+        if (!gather || this.readingFiles)
+            return this.stats;
+
+        let stats = _.cloneDeep(zeroStats);
+        const result = await this.startFindFiles(async(entry) => {
+            if (path.extname(entry) == '.zip') {
+                stats.zipFilesSize += (await fs.stat(entry)).size;
+                stats.zipFilesCount++;
+            }
+
+            if (path.extname(entry) == '.desc') {
+                stats.descFilesSize += (await fs.stat(entry)).size;
+                stats.descFilesCount++;
+            }
+        });
+
+        if (result) {
+            this.stats = stats;
+            this.needSaveStats = true;
+            this.debouncedSaveStats();
+        }
+        return this.stats;
     }
 }