michael@0: var DEBUG = true; michael@0: michael@0: var clientID = "javascript"; michael@0: var nsICache = Components.interfaces.nsICache; michael@0: michael@0: function getEventQueue() michael@0: { michael@0: var nsIEventQueueService = Components.interfaces.nsIEventQueueService; michael@0: var CID = Components.classes["@mozilla.org/event-queue-service;1"]; michael@0: var service = CID.getService(nsIEventQueueService); michael@0: return service.getSpecialEventQueue(nsIEventQueueService.CURRENT_THREAD_EVENT_QUEUE); michael@0: } michael@0: michael@0: var eventQueue = getEventQueue(); michael@0: michael@0: function getCacheService() michael@0: { michael@0: var nsCacheService = Components.classes["@mozilla.org/network/cache-service;1"]; michael@0: var service = nsCacheService.getService(Components.interfaces.nsICacheService); michael@0: return service; michael@0: } michael@0: michael@0: function createCacheSession(clientID, storagePolicy, streamable) michael@0: { michael@0: var service = getCacheService(); michael@0: var session = service.createSession(clientID, storagePolicy, streamable); michael@0: return session; michael@0: } michael@0: michael@0: function openCacheEntry(url, mode) michael@0: { michael@0: var session = createCacheSession(clientID, nsICache.STORE_ON_DISK, true); michael@0: var entry = session.openCacheEntry(url, mode); michael@0: return entry; michael@0: } michael@0: michael@0: function wrapInputStream(input) michael@0: { michael@0: var nsIScriptableInputStream = Components.interfaces.nsIScriptableInputStream; michael@0: var factory = Components.classes["@mozilla.org/scriptableinputstream;1"]; michael@0: var wrapper = factory.createInstance(nsIScriptableInputStream); michael@0: wrapper.init(input); michael@0: return wrapper; michael@0: } michael@0: michael@0: function download(url) michael@0: { michael@0: var data = ""; michael@0: var buffer = java.lang.reflect.Array.newInstance(java.lang.Byte.TYPE, 65536); michael@0: var stream = url.getContent(); michael@0: while (true) { michael@0: var count = stream.read(buffer); michael@0: if (count <= 0) michael@0: break; michael@0: var str = new java.lang.String(buffer, 0, count); michael@0: data += str; michael@0: } michael@0: stream.close(); michael@0: return data; michael@0: } michael@0: michael@0: function write(url, data) michael@0: { michael@0: var key = url.toString(); michael@0: var outputEntry = openCacheEntry(key, nsICache.ACCESS_WRITE); michael@0: var output = outputEntry.transport.openOutputStream(0, -1, 0); michael@0: var count = output.write(data, data.length); michael@0: michael@0: // store some metadata. michael@0: outputEntry.setMetaDataElement("size", data.length); michael@0: michael@0: output.close(); michael@0: outputEntry.markValid(); michael@0: outputEntry.close(); michael@0: michael@0: return count; michael@0: } michael@0: michael@0: function CacheListener() michael@0: { michael@0: this.done = false; michael@0: } michael@0: michael@0: CacheListener.prototype = { michael@0: QueryInterface : function(iid) michael@0: { michael@0: if (iid.equals(Components.interfaces.nsICacheListener)) michael@0: return this; michael@0: throw Components.results.NS_NOINTERFACE; michael@0: }, michael@0: michael@0: onCacheEntryAvailable : function(/* in nsICacheEntryDescriptor */ descriptor, michael@0: /* in nsCacheAccessMode */ accessGranted, michael@0: /* in nsresult */ status) michael@0: { michael@0: this.descriptor = descriptor; michael@0: this.status = status; michael@0: this.done = true; michael@0: } michael@0: }; michael@0: michael@0: function asyncOpenCacheEntry(url, mode) michael@0: { michael@0: var session = createCacheSession(clientID, nsICache.STORE_ON_DISK, true); michael@0: var listener = new CacheListener(); michael@0: session.asyncOpenCacheEntry(url, mode, listener); michael@0: while (!listener.done) michael@0: eventQueue.processPendingEvents(); michael@0: return listener.descriptor; michael@0: } michael@0: michael@0: function asyncWrite(key, data) michael@0: { michael@0: var outputEntry = asyncOpenCacheEntry(key, nsICache.ACCESS_WRITE); michael@0: michael@0: var output = outputEntry.transport.openOutputStream(0, -1, 0); michael@0: var count = output.write(data, data.length); michael@0: michael@0: // store some metadata. michael@0: outputEntry.setMetaDataElement("size", data.length); michael@0: michael@0: output.close(); michael@0: outputEntry.markValid(); michael@0: outputEntry.close(); michael@0: michael@0: return count; michael@0: } michael@0: michael@0: function StreamListener() michael@0: { michael@0: this.done = false; michael@0: this.data = ""; michael@0: this.wrapper = null; michael@0: } michael@0: michael@0: StreamListener.prototype = { michael@0: QueryInterface : function(iid) michael@0: { michael@0: if (iid.equals(Components.interfaces.nsIStreamListener) || michael@0: iid.equals(Components.interfaces.nsIStreamObserver)) michael@0: return this; michael@0: throw Components.results.NS_NOINTERFACE; michael@0: }, michael@0: michael@0: onStartRequest : function(request, context) michael@0: { michael@0: }, michael@0: michael@0: onStopRequest : function(request, context, statusCode, statusText) michael@0: { michael@0: this.statusCode = statusCode; michael@0: this.done = true; michael@0: }, michael@0: michael@0: onDataAvailable : function(request, context, input, offset, count) michael@0: { michael@0: if (this.wrapper == null) michael@0: this.wrapper = wrapInputStream(input); michael@0: input = this.wrapper; michael@0: this.data += input.read(count); michael@0: } michael@0: }; michael@0: michael@0: function asyncRead(key) michael@0: { michael@0: var inputEntry = asyncOpenCacheEntry(key, nsICache.ACCESS_READ); michael@0: var listener = new StreamListener(); michael@0: inputEntry.transport.asyncRead(listener, null, 0, inputEntry.dataSize, 0); michael@0: while (!listener.done) michael@0: eventQueue.processPendingEvents(); michael@0: inputEntry.close(); michael@0: return listener.data; michael@0: } michael@0: michael@0: function read(key) michael@0: { michael@0: var inputEntry = openCacheEntry(key, nsICache.ACCESS_READ); michael@0: var input = wrapInputStream(inputEntry.transport.openInputStream(0, -1, 0)); michael@0: var data = input.read(input.available()); michael@0: input.close(); michael@0: inputEntry.close(); michael@0: return data; michael@0: } michael@0: michael@0: function readMetaData(key, element) michael@0: { michael@0: var inputEntry = openCacheEntry(key, nsICache.ACCESS_READ); michael@0: var metadata = inputEntry.getMetaDataElement(element); michael@0: inputEntry.close(); michael@0: return metadata; michael@0: } michael@0: michael@0: function doom(url) michael@0: { michael@0: var key = url.toString(); michael@0: var doomedEntry = openCacheEntry(key, nsICache.ACCESS_READ_WRITE); michael@0: doomedEntry.doom(); michael@0: doomedEntry.close(); michael@0: } michael@0: michael@0: function test() michael@0: { michael@0: // download some real content from the network. michael@0: var url = new java.net.URL("http://www.mozilla.org"); michael@0: var key = url.toString(); michael@0: var data = download(url); michael@0: michael@0: if (asyncWrite(key, data) == data.length) michael@0: print("disk cache write works!"); michael@0: else michael@0: print("disk cache write broken!"); michael@0: michael@0: if (asyncRead(key) == data) michael@0: print("disk cache read works!"); michael@0: else michael@0: print("disk cache read broken!"); michael@0: michael@0: if (readMetaData(key, "size") == data.length) michael@0: print("disk cache metadata works!"); michael@0: else michael@0: print("disk cache metadata broken!"); michael@0: } michael@0: michael@0: function median(array) michael@0: { michael@0: var cmp = function(x, y) { return x - y; } michael@0: array.sort(cmp); michael@0: var middle = Math.floor(array.length / 2); michael@0: return array[middle]; michael@0: } michael@0: michael@0: function sum(array) michael@0: { michael@0: var s = 0; michael@0: var len = array.length; michael@0: for (var i = 0; i < len; ++i) michael@0: s += array[i]; michael@0: return s; michael@0: } michael@0: michael@0: function time() michael@0: { michael@0: var N = 50; michael@0: var System = java.lang.System; michael@0: var url = new java.net.URL("http://www.mozilla.org"); michael@0: var key = url.toString(); michael@0: var downloadTimes = new Array(); michael@0: for (var i = 0; i < N; ++i) { michael@0: var begin = System.currentTimeMillis(); michael@0: download(url); michael@0: var end = System.currentTimeMillis(); michael@0: downloadTimes.push(end - begin); michael@0: } michael@0: var downloadTotal = sum(downloadTimes); michael@0: var downloadMean = downloadTotal / N; michael@0: var downloadMedian = median(downloadTimes); michael@0: print("" + N + " downloads took " + downloadTotal + " milliseconds."); michael@0: print("mean = " + downloadMean + " milliseconds."); michael@0: print("median = " + downloadMedian + " milliseconds."); michael@0: michael@0: var readTimes = new Array(); michael@0: for (var i = 0; i < N; ++i) { michael@0: var begin = System.currentTimeMillis(); michael@0: asyncRead(key); michael@0: var end = System.currentTimeMillis(); michael@0: readTimes.push(end - begin); michael@0: } michael@0: var readTotal = sum(readTimes); michael@0: var readMean = readTotal / N; michael@0: var readMedian = median(readTimes); michael@0: print("" + N + " reads took " + readTotal + " milliseconds."); michael@0: print("mean = " + readMean + " milliseconds."); michael@0: print("median = " + readMedian + " milliseconds."); michael@0: } michael@0: michael@0: // load the cache service before doing anything with Java... michael@0: getCacheService(); michael@0: michael@0: if (DEBUG) { michael@0: print("cache service loaded."); michael@0: } else { michael@0: print("running disk cache test."); michael@0: test(); michael@0: print("disk cache test complete."); michael@0: }