UNPKG

2q-cache

Version:

Imlementation of 2Q Cache Algorithm

167 lines (142 loc) 5.06 kB
import { CacheQueue } from "../utils/cache_queue"; import { CacheMapElem, CacheQueueElem, BucketsTransportObject } from "../utils/cache_objects"; export class CacheBuckets { private in : CacheQueue; private out : CacheQueue; private searcher : Map<any, CacheMapElem>; constructor(inSize, outSize) { this.in = new CacheQueue(inSize); this.out = new CacheQueue(outSize); this.searcher = new Map(); } public set(key : any, value : any, ttl : number = 0) : boolean { let oldMapElem = this.searcher.get(key); if (!oldMapElem) { let newQueueElem = new CacheQueueElem(); newQueueElem.key = key; let newMapElem = new CacheMapElem(); newMapElem.bucket = 0; newMapElem.linkToList = newQueueElem; newMapElem.data = value; clearTimeout(newMapElem.timeout); if (ttl > 0) { newMapElem.timeout = setTimeout(() => { if (this.has(key)) this.delete(key); },ttl) } let repressedElem = this.in.push(newQueueElem); this.pushToOut(repressedElem); this.searcher.set(key, newMapElem); } else { oldMapElem.data = value; clearTimeout(oldMapElem.timeout); if (ttl > 0) { oldMapElem.timeout = setTimeout(() => { if (this.has(key)) this.delete(key); },ttl) } this.searcher.set(key, oldMapElem); } return true; } updateTtl(key : any, ttl : any) { let mapElem = this.searcher.get(key); if (mapElem) { clearTimeout(mapElem.timeout); if (ttl > 0) { mapElem.timeout = setTimeout(() => { if (this.has(key)) this.delete(key); },ttl) } } } private pushToOut(elem : CacheQueueElem) : void { if (elem != null) { this.searcher.get(elem.key).bucket = 1; let repressedElem = this.out.push(elem); if (repressedElem != null) { this.searcher.delete(repressedElem.key); } } } public get(key : any) : BucketsTransportObject { let foundElem = this.searcher.get(key); if (foundElem) { let transport = new BucketsTransportObject(); transport.key = key; transport.value = foundElem.data; let bucket = foundElem.bucket; if (bucket === 1) { clearTimeout(foundElem.timeout); this.out.unlink(foundElem.linkToList); this.searcher.delete(key); transport.needMove = true; } return transport; } return null; } public has(key : any) : boolean { return this.searcher.has(key); } public clear() : void { this.searcher.forEach(value => { clearTimeout(value.timeout); }) this.searcher.clear(); this.in.clear(); this.out.clear(); } public delete(key : any) : boolean { let delObject = this.searcher.get(key); clearTimeout(delObject.timeout); if (delObject.bucket === 0) { this.in.unlink(delObject.linkToList); this.searcher.delete(key); } else { this.out.unlink(delObject.linkToList); this.searcher.delete(key); } return true; } public getSize() : Array<number> { return [ this.in.getSize(), this.out.getSize() ]; } public getMaxSize() : Array<number> { return [ this.in.getMaxSize(), this.out.getMaxSize() ]; } public getSizeObject() : object { return { in : { currentSize : this.in.getSize(), maxSize : this.in.getMaxSize() }, out : { currentSize : this.out.getSize(), maxSize : this.out.getMaxSize() } } } public setSize(inSize : number, outSize : number) { this.in.setSize(inSize); while (this.in.getSize() > this.in.getMaxSize()) { let deletedElem = this.in.pop(); let dElem = this.searcher.get(deletedElem.key); if (dElem) clearTimeout(dElem.timeout); this.searcher.delete(deletedElem.key); } this.out.setSize(outSize); while (this.out.getSize() > this.out.getMaxSize()) { let deletedElem = this.out.pop(); let dElem = this.searcher.get(deletedElem.key); if (dElem) clearTimeout(dElem.timeout); this.searcher.delete(deletedElem.key); } } }