int-cli
Version:
INT is the new generation of bottom-up created system of IoT and blockchain
178 lines (177 loc) • 6.35 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const fs = require("fs-extra");
const util_1 = require("util");
const error_code_1 = require("../error_code");
const storage_1 = require("./storage");
const log_snapshot_manager_1 = require("./log_snapshot_manager");
class StorageManager {
constructor(options) {
this.m_views = new Map();
this.m_path = options.path;
this.m_storageType = options.storageType;
this.m_logger = options.logger;
if (options.snapshotManager) {
this.m_snapshotManager = options.snapshotManager;
}
else {
this.m_snapshotManager = new log_snapshot_manager_1.StorageLogSnapshotManager(options);
}
this.m_readonly = !!options.readonly;
this.m_tmpManager = options.tmpManager;
}
async init() {
let err = await this.m_snapshotManager.init();
if (err) {
return err;
}
return error_code_1.ErrorCode.RESULT_OK;
}
get path() {
return this.m_path;
}
uninit() {
this.m_snapshotManager.uninit();
}
async createSnapshot(from, blockHash, remove) {
if (this.m_readonly) {
return { err: error_code_1.ErrorCode.RESULT_NOT_SUPPORT };
}
let csr = await this.m_snapshotManager.createSnapshot(from, blockHash);
if (csr.err) {
return csr;
}
// assert((await csr.snapshot!.messageDigest()).value !== (await from.messageDigest()).value);
if (remove) {
await from.remove();
}
return csr;
}
async getSnapshot(blockHash) {
return await this.m_snapshotManager.getSnapshot(blockHash);
}
releaseSnapshot(blockHash) {
return this.m_snapshotManager.releaseSnapshot(blockHash);
}
async createStorage(name, from) {
if (this.m_readonly) {
return { err: error_code_1.ErrorCode.RESULT_NOT_SUPPORT };
}
let storage = new this.m_storageType({
filePath: this.m_tmpManager.getPath(`${name}.storage`),
logger: this.m_logger
});
await storage.remove();
let err;
if (!from) {
this.m_logger.info(`create storage ${name}`);
err = await storage.init();
}
else if (util_1.isString(from)) {
this.m_logger.info(`create storage ${name} from snapshot ${from}`);
let ssr = await this._getSnapshotStorage(from);
if (ssr.err) {
this.m_logger.error(`get snapshot failed for ${from}`);
err = ssr.err;
}
else {
fs.copyFileSync(ssr.storage.filePath, storage.filePath);
this.releaseSnapshotView(from);
err = await storage.init();
}
}
else if (from instanceof storage_1.Storage) {
this.m_logger.info(`create storage ${name} from snapshot ${storage.filePath}`);
fs.copyFileSync(from.filePath, storage.filePath);
err = await storage.init();
}
else {
this.m_logger.error(`create storage ${name} with invalid from ${from}`);
return { err: error_code_1.ErrorCode.RESULT_INVALID_PARAM };
}
if (err) {
this.m_logger.error(`create storage ${name} failed for ${err}`);
return { err };
}
return { err: error_code_1.ErrorCode.RESULT_OK, storage };
}
async _getSnapshotStorage(blockHash) {
let stub = this.m_views.get(blockHash);
if (stub) {
++stub.ref;
if (stub.storage.isInit) {
return { err: error_code_1.ErrorCode.RESULT_OK, storage: stub.storage };
}
else {
return new Promise((resolve) => {
stub.storage.once('init', (err) => {
if (err) {
resolve({ err });
}
else {
resolve({ err, storage: stub.storage });
}
});
});
}
}
stub = {
storage: new this.m_storageType({
filePath: this.m_snapshotManager.getSnapshotFilePath(blockHash),
logger: this.m_logger
}),
ref: 1
};
this.m_views.set(blockHash, stub);
let sr = await this.m_snapshotManager.getSnapshot(blockHash);
if (sr.err) {
this.m_logger.error(`get snapshot failed for ${sr.err}`);
this.m_views.delete(blockHash);
return { err: sr.err };
}
let ret = new Promise((resolve) => {
stub.storage.once('init', (err) => {
if (err) {
this.m_snapshotManager.releaseSnapshot(blockHash);
this.m_views.delete(blockHash);
resolve({ err });
}
else {
resolve({ err, storage: stub.storage });
}
});
});
stub.storage.init(true);
return ret;
}
async getSnapshotView(blockHash) {
return await this._getSnapshotStorage(blockHash);
}
// 根据block hash 获取redo log内容
// 提供给chain_node层引用
getRedoLog(blockHash) {
return this.m_snapshotManager.getRedoLog(blockHash);
}
hasRedoLog(blockHash) {
return this.m_snapshotManager.hasRedoLog(blockHash);
}
addRedoLog(blockHash, log) {
return this.m_snapshotManager.writeRedoLog(blockHash, log);
}
async releaseSnapshotView(blockHash) {
let stub = this.m_views.get(blockHash);
if (stub) {
--stub.ref;
if (!stub.ref) {
this.m_views.delete(blockHash);
// 这里await也不能保证互斥, 可能在uninit过程中再次创建,只能靠readonly保证在一个path上创建多个storage 实例
await stub.storage.uninit();
this.m_snapshotManager.releaseSnapshot(blockHash);
}
}
}
recycleSnapshot() {
return this.m_snapshotManager.recycle();
}
}
exports.StorageManager = StorageManager;