# HG changeset patch # User Atul Varma # Date 1239808062 25200 # Node ID aa013581aecac9e670f12432468311c4eda359c1 # Parent 3607a684469139a6d5aebbad622ec56137b0ddb5 Directory restructuring. diff -r 3607a6844691 -r aa013581aeca big.html --- a/big.html Wed Apr 15 08:01:14 2009 -0700 +++ b/big.html Wed Apr 15 08:07:42 2009 -0700 @@ -6,7 +6,7 @@ + href="css/index.css" /> Browser Big Couch Test @@ -18,6 +18,6 @@
- - + + diff -r 3607a6844691 -r aa013581aeca big.js --- a/big.js Wed Apr 15 08:01:14 2009 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,156 +0,0 @@ -var MAX_WORD_LENGTH = 10; -var LEXICON_SIZE = 200; -var MIN_DOCUMENT_LENGTH = 250; -var MAX_DOCUMENT_LENGTH = 500; -var CORPUS_SIZE = 1000; -var UI_LOCK_LIMIT = 100; -var UI_BREATHE_TIME = 10; - -// Returns a random integer between min and max -// Using Math.round() will give you a non-uniform distribution! -function getRandomInt(min, max) -{ - return Math.floor(Math.random() * (max - min + 1)) + min; -} - -function makeRandomWord() { - var word = ""; - var len = getRandomInt(1, MAX_WORD_LENGTH); - for (var i = 0; i < len; i++) { - var charCode = getRandomInt("a".charCodeAt(0), - "z".charCodeAt(0)); - var letter = String.fromCharCode(charCode); - word += letter; - } - return word; -} - -function makeLexicon() { - var lexicon = []; - - for (var i = 0; i < LEXICON_SIZE; i++) - lexicon.push(makeRandomWord()); - - return lexicon; -} - -function makeDocument(lexicon) { - var len = getRandomInt(MIN_DOCUMENT_LENGTH, - MAX_DOCUMENT_LENGTH); - var doc = []; - - for (var i = 0; i < len; i++) { - var wordIndex = getRandomInt(0, lexicon.length); - doc.push(lexicon[wordIndex]); - } - - return doc.join(" "); -} - -function makeCorpus(db, progress, chunkSize, cb) { - var lexicon = makeLexicon(); - var docs = []; - var i = 0; - - function makeNextDocument() { - var iAtStart = i; - - do { - docs.push({id: i, - content: makeDocument(lexicon)}); - i += 1; - } while (i - iAtStart < chunkSize && - i < CORPUS_SIZE); - if (i == CORPUS_SIZE) - db.put(docs, cb); - else - progress("make-documents", i / CORPUS_SIZE, makeNextDocument); - } - - makeNextDocument(); -} - -var config = document.getElementById("config"); -var statusArea = document.getElementById("status"); -var result = document.getElementById("result"); - -statusArea.textContent = "Please wait..."; -config.textContent = ("Counting word occurrences in a lexicon of " + - LEXICON_SIZE + " words, using a corpus of " + - CORPUS_SIZE + " documents, each of which is " + - MIN_DOCUMENT_LENGTH + " to " + MAX_DOCUMENT_LENGTH + - " words long."); - -function makeProgress(func) { - var lastDate = new Date(); - function progress(phase, percent, resume) { - var currDate = new Date(); - if (currDate - lastDate > UI_LOCK_LIMIT) { - lastDate = currDate; - func.call(this, phase, percent); - window.setTimeout(resume, UI_BREATHE_TIME); - } else - window.setTimeout(resume, 0); - } - - return progress; -} - -function start() { - BrowserCouch.get( - "big", - function(db) { - if (db.getLength() == 0) { - db.wipe(function() { - makeCorpus( - db, - makeProgress( - function(phase, percent) { - statusArea.textContent = ("building new corpus (" + - Math.floor(percent * 100) + - "%)"); - }), - 25, - run - ); - }); - } else - run(); - - function run() { - db.view( - {map: function(doc, emit) { - var words = doc.content.split(" "); - for (var i = 0; i < words.length; i++) - emit(words[i], 1); - }, - reduce: function(keys, values) { - var sum = 0; - for (var i = 0; i < values.length; i++) - sum += values[i]; - return sum; - }, - chunkSize: 25, - progress: makeProgress( - function(phase, percent) { - percent = Math.floor(percent * 100); - var msg = phase + " (" + percent + "%)"; - statusArea.textContent = msg; - }), - finished: function(aResult) { - statusArea.textContent = "Done."; - - ModuleLoader.require( - "JSON", - function() { - result.textContent = JSON.stringify(aResult); - }); - }} - ); - } - }, - new FakeStorage() - ); -} - -window.addEventListener("load", start, false); diff -r 3607a6844691 -r aa013581aeca browser-couch.js --- a/browser-couch.js Wed Apr 15 08:01:14 2009 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,568 +0,0 @@ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is Ubiquity. - * - * The Initial Developer of the Original Code is Mozilla. - * Portions created by the Initial Developer are Copyright (C) 2007 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * Atul Varma - * - * Alternatively, the contents of this file may be used under the terms of - * either the GNU General Public License Version 2 or later (the "GPL"), or - * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -function isArray(value) { - // Taken from "Remedial Javascript" by Douglas Crockford: - // http://javascript.crockford.com/remedial.html - - return (typeof value.length === 'number' && - !(value.propertyIsEnumerable('length')) && - typeof value.splice === 'function'); -} - -var ModuleLoader = { - LIBS: {JSON: "json2.js"}, - - require: function ML_require(libs, cb) { - var self = this; - var i = 0; - var lastLib = ""; - - if (!isArray(libs)) - libs = [libs]; - - function loadNextLib() { - if (lastLib && !window[lastLib]) - throw new Error("Failed to load library: " + lastLib); - if (i == libs.length) - cb(); - else { - var libName = libs[i]; - i += 1; - if (window[libName]) - loadNextLib(); - else { - var libUrl = self.LIBS[libName]; - if (!libUrl) - throw new Error("Unknown lib: " + libName); - lastLib = libName; - self._loadScript(libUrl, window, loadNextLib); - } - } - } - - loadNextLib(); - }, - - _loadScript: function ML__loadScript(url, window, cb) { - var doc = window.document; - var script = doc.createElement("script"); - script.setAttribute("src", url); - script.addEventListener( - "load", - function onLoad() { - script.removeEventListener("load", onLoad, false); - cb(); - }, - false - ); - doc.body.appendChild(script); - } -}; - -function WebWorkerMapReducer(numWorkers, Worker) { - if (!Worker) - Worker = window.Worker; - - var pool = []; - - function MapWorker(id) { - var worker = new Worker('worker-map-reducer.js'); - var onDone; - - worker.onmessage = function(event) { - onDone(event.data); - }; - - this.id = id; - this.map = function MW_map(map, dict, cb) { - onDone = cb; - worker.postMessage({map: map.toString(), dict: dict}); - }; - } - - for (var i = 0; i < numWorkers; i++) - pool.push(new MapWorker(i)); - - this.map = function WWMR_map(map, dict, progress, chunkSize, finished) { - var keys = dict.getKeys(); - var size = keys.length; - var workersDone = 0; - var mapDict = {}; - - function getNextChunk() { - if (keys.length) { - var chunkKeys = keys.slice(0, chunkSize); - keys = keys.slice(chunkSize); - var chunk = {}; - for (var i = 0; i < chunkKeys.length; i++) - chunk[chunkKeys[i]] = dict.get(chunkKeys[i]); - return chunk; - } else - return null; - } - - function nextJob(mapWorker) { - var chunk = getNextChunk(); - if (chunk) { - mapWorker.map( - map, - chunk, - function jobDone(aMapDict) { - for (name in aMapDict) - if (name in mapDict) { - var item = mapDict[name]; - item.keys = item.keys.concat(aMapDict[name].keys); - item.values = item.values.concat(aMapDict[name].values); - } else - mapDict[name] = aMapDict[name]; - - if (keys.length) - progress("map", - (size - keys.length) / size, - function() { nextJob(mapWorker); }); - else - workerDone(); - }); - } else - workerDone(); - } - - function workerDone() { - workersDone += 1; - if (workersDone == numWorkers) - allWorkersDone(); - } - - function allWorkersDone() { - var mapKeys = []; - for (name in mapDict) - mapKeys.push(name); - mapKeys.sort(); - finished({dict: mapDict, keys: mapKeys}); - } - - for (var i = 0; i < numWorkers; i++) - nextJob(pool[i]); - }; - - this.reduce = SingleThreadedMapReducer.reduce; -}; - -var SingleThreadedMapReducer = { - map: function STMR_map(map, dict, progress, - chunkSize, finished) { - var mapDict = {}; - var keys = dict.getKeys(); - var currDoc; - - function emit(key, value) { - // TODO: This assumes that the key will always be - // an indexable value. We may have to hash the value, - // though, if it's e.g. an Object. - var item = mapDict[key]; - if (!item) - item = mapDict[key] = {keys: [], values: []}; - item.keys.push(currDoc.id); - item.values.push(value); - } - - var i = 0; - - function continueMap() { - var iAtStart = i; - - do { - currDoc = dict.get(keys[i]); - map(currDoc, emit); - i++; - } while (i - iAtStart < chunkSize && - i < keys.length) - - if (i == keys.length) { - var mapKeys = []; - for (name in mapDict) - mapKeys.push(name); - mapKeys.sort(); - finished({dict: mapDict, keys: mapKeys}); - } else - progress("map", i / keys.length, continueMap); - } - - continueMap(); - }, - - reduce: function STMR_reduce(reduce, mapResult, progress, - chunkSize, finished) { - var rows = []; - var mapDict = mapResult.dict; - var mapKeys = mapResult.keys; - - var i = 0; - - function continueReduce() { - var iAtStart = i; - - do { - var key = mapKeys[i]; - var item = mapDict[key]; - - var keys = []; - for (var j = 0; j < keys.length; j++) - newKeys.push([key, item.keys[j]]); - - rows.push({key: key, - value: reduce(keys, item.values)}); - i++; - } while (i - iAtStart < chunkSize && - i < mapKeys.length) - - if (i == mapKeys.length) - finished(rows); - else - progress("reduce", i / mapKeys.length, continueReduce); - } - - continueReduce(); - } -}; - -function FakeStorage() { - var db = {}; - - function deepCopy(obj) { - if (typeof(obj) == "object") { - var copy; - - if (isArray(obj)) - copy = new Array(); - else - copy = new Object(); - - for (name in obj) { - if (obj.hasOwnProperty(name)) { - var property = obj[name]; - if (typeof(property) == "object") - copy[name] = deepCopy(property); - else - copy[name] = property; - } - } - - return copy; - } else - return obj; - } - - this.get = function FS_get(name, cb) { - if (!(name in db)) - cb(null); - else - cb(db[name]); - }; - - this.put = function FS_put(name, obj, cb) { - db[name] = deepCopy(obj); - cb(); - }; -}; - -function LocalStorage(JSON) { - var storage; - - if (window.globalStorage) - storage = window.globalStorage[location.hostname]; - else { - if (window.localStorage) - storage = window.localStorage; - else - throw new Error("globalStorage/localStorage not available."); - } - - function ensureJSON(cb) { - if (!JSON) { - ModuleLoader.require( - "JSON", - function() { - JSON = window.JSON; - cb(); - }); - } else - cb(); - } - - this.get = function LS_get(name, cb) { - if (name in storage && storage[name].value) - ensureJSON( - function() { - var obj = JSON.parse(storage[name].value); - cb(obj); - }); - else - cb(null); - }; - - this.put = function LS_put(name, obj, cb) { - ensureJSON( - function() { - storage[name] = JSON.stringify(obj); - cb(); - }); - }; -} - -var BrowserCouch = { - get: function BC_get(name, cb, storage) { - if (!storage) - storage = new LocalStorage(); - - new this._DB(name, storage, new this._Dictionary(), cb); - }, - - _Dictionary: function BC__Dictionary() { - var dict = {}; - var keys = []; - - function regenerateKeys() { - keys = []; - for (key in dict) - keys.push(key); - } - - this.has = function Dictionary_has(key) { - return (key in dict); - }; - - this.getKeys = function Dictionary_getKeys() { - return keys; - }; - - this.get = function Dictionary_get(key) { - return dict[key]; - }; - - this.set = function Dictionary_set(key, value) { - if (!(key in dict)) - keys.push(key); - dict[key] = value; - }; - - this.remove = function Dictionary_delete(key) { - delete dict[key]; - - // TODO: If we're in JS 1.6 and have Array.indexOf(), we - // shouldn't have to rebuild the key index like this. - regenerateKeys(); - }; - - this.clear = function Dictionary_clear() { - dict = {}; - keys = []; - }; - - this.pickle = function Dictionary_pickle() { - return dict; - }; - - this.unpickle = function Dictionary_unpickle(obj) { - dict = obj; - regenerateKeys(); - }; - }, - - _DB: function BC__DB(name, storage, dict, cb) { - var self = this; - var dbName = 'BrowserCouch_DB_' + name; - - function commitToStorage(cb) { - if (!cb) - cb = function() {}; - storage.put(dbName, dict.pickle(), cb); - } - - this.wipe = function DB_wipe(cb) { - dict.clear(); - commitToStorage(cb); - }; - - this.get = function DB_get(id, cb) { - if (dict.has(id)) - cb(dict.get(id)); - else - cb(null); - }; - - this.put = function DB_put(document, cb) { - if (isArray(document)) { - for (var i = 0; i < document.length; i++) - dict.set(document[i].id, document[i]); - } else - dict.set(document.id, document); - - commitToStorage(cb); - }; - - this.getLength = function DB_getLength() { - return dict.getKeys().length; - }; - - this.view = function DB_view(options) { - if (!options.map) - throw new Error('map function not provided'); - if (!options.finished) - throw new Error('finished callback not provided'); - - // Maximum number of items to process before giving the UI a chance - // to breathe. - var DEFAULT_CHUNK_SIZE = 1000; - - // If no progress callback is given, we'll automatically give the - // UI a chance to breathe for this many milliseconds before continuing - // processing. - var DEFAULT_UI_BREATHE_TIME = 50; - - var chunkSize = options.chunkSize; - if (!chunkSize) - chunkSize = DEFAULT_CHUNK_SIZE; - - var progress = options.progress; - if (!progress) - progress = function defaultProgress(phase, percent, resume) { - window.setTimeout(resume, DEFAULT_UI_BREATHE_TIME); - }; - - var mapReducer = options.mapReducer; - if (!mapReducer) - mapReducer = SingleThreadedMapReducer; - - mapReducer.map( - options.map, - dict, - progress, - chunkSize, - function(mapResult) { - if (options.reduce) - mapReducer.reduce( - options.reduce, - mapResult, - progress, - chunkSize, - function(rows) { - options.finished(new BrowserCouch._View(rows)); - }); - else - options.finished(new BrowserCouch._MapView(mapResult)); - }); - }; - - storage.get( - dbName, - function(obj) { - if (obj) - dict.unpickle(obj); - cb(self); - }); - }, - - _View: function BC__View(rows) { - this.rows = rows; - - function findRow(key, rows) { - if (rows.length > 1) { - var midpoint = Math.floor(rows.length / 2); - var row = rows[midpoint]; - if (key < row.key) - return findRow(key, rows.slice(0, midpoint)); - if (key > row.key) - return midpoint + findRow(key, rows.slice(midpoint)); - return midpoint; - } else - return 0; - } - - this.findRow = function V_findRow(key) { - return findRow(key, rows); - }; - }, - - _MapView: function BC__MapView(mapResult) { - var rows = []; - var keyRows = []; - - var mapKeys = mapResult.keys; - var mapDict = mapResult.dict; - - for (var i = 0; i < mapKeys.length; i++) { - var key = mapKeys[i]; - var item = mapDict[key]; - keyRows.push({key: key, pos: rows.length}); - var newRows = []; - for (var j = 0; j < item.keys.length; j++) { - var id = item.keys[j]; - var value = item.values[j]; - newRows.push({id: id, - key: key, - value: value}); - } - newRows.sort(function(a, b) { - if (a.id < b.id) - return -1; - if (a.id > b.id) - return 1; - return 0; - }); - rows = rows.concat(newRows); - } - - function findRow(key, keyRows) { - if (keyRows.length > 1) { - var midpoint = Math.floor(keyRows.length / 2); - var keyRow = keyRows[midpoint]; - if (key < keyRow.key) - return findRow(key, keyRows.slice(0, midpoint)); - if (key > keyRow.key) - return findRow(key, keyRows.slice(midpoint)); - return keyRow.pos; - } else - return keyRows[0].pos; - } - - this.rows = rows; - this.findRow = function MV_findRow(key) { - return findRow(key, keyRows); - }; - } -}; diff -r 3607a6844691 -r aa013581aeca css/index.css --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/css/index.css Wed Apr 15 08:07:42 2009 -0700 @@ -0,0 +1,31 @@ +body { + width: 20em; + font-family: helvetica; +} + +h1 { + font-weight: normal; +} + +.test { + font-family: monospace; +} + +.in-progress { + background-color: yellow; +} + +.successful { + background-color: lawnGreen; +} + +.failed { + background-color: red; +} + +.pending { +} + +.skipped { + background-color: lightGrey; +} diff -r 3607a6844691 -r aa013581aeca index.css --- a/index.css Wed Apr 15 08:01:14 2009 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +0,0 @@ -body { - width: 20em; - font-family: helvetica; -} - -h1 { - font-weight: normal; -} - -.test { - font-family: monospace; -} - -.in-progress { - background-color: yellow; -} - -.successful { - background-color: lawnGreen; -} - -.failed { - background-color: red; -} - -.pending { -} - -.skipped { - background-color: lightGrey; -} diff -r 3607a6844691 -r aa013581aeca index.html --- a/index.html Wed Apr 15 08:01:14 2009 -0700 +++ b/index.html Wed Apr 15 08:07:42 2009 -0700 @@ -6,7 +6,7 @@ + href="css/index.css" /> Browser Couch Tests @@ -14,8 +14,8 @@
- - + +