Skip to content

Custom Storage Manager [v2]

Adrien Castex edited this page Apr 22, 2018 · 1 revision

A Storage Manager is an object which will manage the storage allocation of the resources.

If none is provided in the options of the server, a NoStorageManager instance will be used.

Interface

interface IStorageManager
{
    reserve(ctx : RequestContext, fs : FileSystem, size : number, callback : (reserved : boolean) => void) : void

    evaluateCreate(ctx : RequestContext, fs : FileSystem, path : Path, type : ResourceType, callback : IStorageManagerEvaluateCallback) : void
    evaluateContent(ctx : RequestContext, fs : FileSystem, expectedSize : number, callback : IStorageManagerEvaluateCallback) : void
    evaluateProperty(ctx : RequestContext, fs : FileSystem, name : string, value : ResourcePropertyValue, attributes : PropertyAttributes, callback : IStorageManagerEvaluateCallback) : void

    available(ctx : RequestContext, fs : FileSystem, callback : (available : number) => void) : void
    reserved(ctx : RequestContext, fs : FileSystem, callback : (reserved : number) => void) : void
}

type IStorageManagerEvaluateCallback = (size : number) => void;

Methods

reserve

Allocate a chunk of size size bytes. If it is not possible to allocate the requested chunk, the callback must be called with the value false, otherwise it must be called with the value true.

reserve(ctx : RequestContext, fs : FileSystem, size : number, callback : (reserved : boolean) => void) : void

available

Get how many bytes are still available for use for the current request context.

Returning -1 means infinity.

available(ctx : RequestContext, fs : FileSystem, callback : (available : number) => void) : void

reserved

Get how many bytes are already used for the current request context.

reserved(ctx : RequestContext, fs : FileSystem, callback : (reserved : number) => void) : void

evaluateCreate

Evaluates the size of the creation of a new empty resource.

evaluateCreate(ctx : RequestContext, fs : FileSystem, path : Path, type : ResourceType, callback : IStorageManagerEvaluateCallback) : void

evaluateContent

Evaluates the size of the content of a resource based on the actual size of it.

evaluateContent(ctx : RequestContext, fs : FileSystem, expectedSize : number, callback : IStorageManagerEvaluateCallback) : void

evaluateProperty

Evaluates the size of a property.

evaluateProperty(ctx : RequestContext, fs : FileSystem, name : string, value : ResourcePropertyValue, attributes : PropertyAttributes, callback : IStorageManagerEvaluateCallback) : void

Examples

NoStorageManager

class NoStorageManager implements IStorageManager
{
    reserve(ctx : RequestContext, fs : FileSystem, size : number, callback : (reserved : boolean) => void) : void
    {
        callback(true);
    }

    evaluateCreate(ctx : RequestContext, fs : FileSystem, path : Path, type : ResourceType, callback : IStorageManagerEvaluateCallback) : void
    {
        callback(0);
    }
    evaluateContent(ctx : RequestContext, fs : FileSystem, expectedSize : number, callback : IStorageManagerEvaluateCallback) : void
    {
        callback(0);
    }
    evaluateProperty(ctx : RequestContext, fs : FileSystem, name : string, value : ResourcePropertyValue, attributes : PropertyAttributes, callback : IStorageManagerEvaluateCallback) : void
    {
        callback(0);
    }

    available(ctx : RequestContext, fs : FileSystem, callback : (available : number) => void) : void
    {
        callback(-1);
    }
    reserved(ctx : RequestContext, fs : FileSystem, callback : (reserved : number) => void) : void
    {
        callback(0);
    }
}

PerUserStorageManager

class PerUserStorageManager implements IStorageManager
{
    storage : {
        [UUID : string] : number
    }

    constructor(public limitPerUser : number)
    {
        this.storage = {};
    }

    reserve(ctx : RequestContext, fs : FileSystem, size : number, callback : (reserved : boolean) => void) : void
    {
        let nb = this.storage[ctx.user.uid];
        if(nb === undefined)
            nb = 0;
        nb += size;

        if(nb > this.limitPerUser)
            return callback(false);

        this.storage[ctx.user.uid] = Math.max(0, nb);
        callback(true);
    }

    evaluateCreate(ctx : RequestContext, fs : FileSystem, path : Path, type : ResourceType, callback : IStorageManagerEvaluateCallback) : void
    {
        fs.getFullPath(ctx, path, (e, fullPath) => {
            callback(fullPath.toString().length);
        })
    }
    evaluateContent(ctx : RequestContext, fs : FileSystem, expectedSize : number, callback : IStorageManagerEvaluateCallback) : void
    {
        callback(expectedSize);
    }

    evalPropValue(value : ResourcePropertyValue) : number
    {
        if(!value)
            return 0;
        if(value.constructor === String)
            return (value as String).length;
        if(Array.isArray(value))
            return (value as XMLElement[]).map((el) => this.evalPropValue(el)).reduce((p, n) => p + n, 0);

        const xml = value as XMLElement;
        const attributesLength = Object.keys(xml.attributes).map((at) => at.length + (xml.attributes[at].length as number)).reduce((p, n) => p + n, 0);
        return xml.name.length + attributesLength + (xml.elements && xml.elements.length > 0 ? this.evalPropValue(xml.elements) : 0);
    }
    evaluateProperty(ctx : RequestContext, fs : FileSystem, name : string, value : ResourcePropertyValue, attributes : PropertyAttributes, callback : IStorageManagerEvaluateCallback) : void
    {
        callback(name.length + Object.keys(attributes).map((ak) => attributes[ak].length + ak.length).reduce((p, n) => p + n, 0) + this.evalPropValue(value));
    }

    available(ctx : RequestContext, fs : FileSystem, callback : (available : number) => void) : void
    {
        const nb = this.storage[ctx.user.uid];
        callback(nb === undefined ? this.limitPerUser : this.limitPerUser - nb);
    }
    reserved(ctx : RequestContext, fs : FileSystem, callback : (reserved : number) => void) : void
    {
        const nb = this.storage[ctx.user.uid];
        callback(nb === undefined ? 0 : nb);
    }
}
Clone this wiki locally