azurite
Version:
An open source Azure Storage API compatible server
194 lines • 6.06 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
const tslib_1 = require("tslib");
const fs_1 = require("fs");
const lokijs_1 = tslib_1.__importDefault(require("lokijs"));
const utils_1 = require("../utils/utils");
const AllExtentsAsyncIterator_1 = tslib_1.__importDefault(require("./AllExtentsAsyncIterator"));
/**
* This is a metadata source implementation for extent management based on loki DB.
*
* It contains following collection and documents:
*
* -- EXTENTS_COLLECTION // Collections maintain extents information, including extentID, mapped local file path
* // Unique document properties: id, path
*
* @export
* @class LokiExtentMetadata
* @implements {IExtentMetadata}
*/
class LokiExtentMetadata {
constructor(lokiDBPath, inMemory) {
this.lokiDBPath = lokiDBPath;
this.initialized = false;
this.closed = true;
this.EXTENTS_COLLECTION = "$EXTENTS_COLLECTION$";
this.db = new lokijs_1.default(lokiDBPath, inMemory ? {
persistenceMethod: "memory"
} : {
persistenceMethod: "fs",
autosave: true,
autosaveInterval: 5000
});
}
isInitialized() {
return this.initialized;
}
isClosed() {
return this.closed;
}
async init() {
await new Promise((resolve, reject) => {
(0, fs_1.stat)(this.lokiDBPath, (statError, stats) => {
if (!statError) {
this.db.loadDatabase({}, (dbError) => {
if (dbError) {
reject(dbError);
}
else {
resolve();
}
});
}
else {
// when DB file doesn't exist, ignore the error because following will re-create the file
resolve();
}
});
});
// Create EXTENTS_COLLECTION if not exists
if (this.db.getCollection(this.EXTENTS_COLLECTION) === null) {
this.db.addCollection(this.EXTENTS_COLLECTION, {
indices: ["id"]
});
}
await new Promise((resolve, reject) => {
this.db.saveDatabase((err) => {
if (err) {
reject(err);
}
else {
resolve();
}
});
});
this.initialized = true;
this.closed = false;
}
/**
* Close loki DB.
*
* @returns {Promise<void>}
* @memberof LokiBlobDataStore
*/
async close() {
await new Promise((resolve, reject) => {
this.db.close((err) => {
if (err) {
reject(err);
}
else {
resolve();
}
});
});
this.closed = true;
}
/**
* Clean LokiExtentMetadata.
*
* @returns {Promise<void>}
* @memberof LokiExtentMetadata
*/
async clean() {
if (this.isClosed()) {
await (0, utils_1.rimrafAsync)(this.lokiDBPath);
return;
}
throw new Error(`Cannot clean LokiExtentMetadata, it's not closed.`);
}
/**
* Update the extent status in DB. A new item will be created if the extent does not exists.
*
* @param {IExtentModel} extent
* @returns {Promise<void>}
* @memberof LokiExtentMetadata
*/
async updateExtent(extent) {
const coll = this.db.getCollection(this.EXTENTS_COLLECTION);
const doc = coll.findOne({ id: extent.id });
if (!doc) {
coll.insert(extent);
return;
}
doc.size = extent.size;
doc.LastModifyInMS = extent.lastModifiedInMS;
coll.update(doc);
}
/**
* List extents.
*
* @param {string} [id]
* @param {number} [maxResults]
* @param {number} [marker]
* @param {Date} [queryTime]
* @param {number} [protectTimeInMs]
* @returns {(Promise<[IExtentModel[], number | undefined]>)}
* @memberof LokiExtentMetadata
*/
async listExtents(id, maxResults, marker, queryTime, protectTimeInMs) {
const query = {};
if (id !== undefined) {
query.id = id;
}
if (maxResults === undefined) {
maxResults = 5000;
}
if (protectTimeInMs === undefined) {
protectTimeInMs = 0;
}
if (queryTime !== undefined) {
query.LastModifyInMS = {
$lt: queryTime.getTime() - protectTimeInMs
};
}
query.$loki = { $gt: marker };
const coll = this.db.getCollection(this.EXTENTS_COLLECTION);
const docs = coll.chain().find(query).limit(maxResults).data();
if (docs.length < maxResults) {
return [docs, undefined];
}
else {
const nextMarker = docs[docs.length - 1].$loki;
return [docs, nextMarker];
}
}
/**
* Delete the extent metadata from DB with the extentId.
*
* @param {string} extentId
* @returns {Promise<void>}
* @memberof IExtentMetadata
*/
async deleteExtent(extentId) {
const coll = this.db.getCollection(this.EXTENTS_COLLECTION);
return coll.findAndRemove({ id: extentId });
}
iteratorExtents() {
return new AllExtentsAsyncIterator_1.default(this);
}
/**
* Get the persistencyId for a given extentId.
*
* @param {string} extentId
* @returns {Promise<string>}
* @memberof IExtentMetadata
*/
async getExtentLocationId(extentId) {
const coll = this.db.getCollection(this.EXTENTS_COLLECTION);
const doc = coll.findOne({ id: extentId });
return doc.locationId;
}
}
exports.default = LokiExtentMetadata;
//# sourceMappingURL=LokiExtentMetadataStore.js.map
;