Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / tools / perf / page_sets / endure / indexeddb_app_worker.js
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // This file simulates a typical background process of an offline-capable
6 // authoring application. When in an "online" state it receives chunks of
7 // data updates from a simulated server and stores them in a temporary IDB
8 // data store. On a different timer, the chunks are drained from the
9 // temporary store and combined into larger records in a permanent store.
10 // When in an "offline" state, nothing else happens.
11
12 function unexpectedErrorCallback(e) {
13   self.postMessage({type: 'ERROR', error: {
14     name: e.target.error.name,
15     message: e.target.error.message
16   }});
17 }
18
19 function unexpectedAbortCallback(e) {
20   self.postMessage({type: 'ABORT', error: {
21     name: e.target.error.name,
22     message: e.target.error.message
23   }});
24 }
25
26 function log(message) {
27   self.postMessage({type: 'LOG', message: message});
28 }
29
30 function error(message) {
31   self.postMessage({type: 'ERROR', message: message});
32 }
33
34 var DBNAME = 'endurance-db';
35 var DBVERSION = 1;
36
37 var MAX_DOC_ID = 25;
38 var MAX_CHUNK_ID = 10;
39 var MAX_CHUNK_SIZE = 5 * 1024;
40 var SYNC_TIMEOUT = 100;
41 var COMBINE_TIMEOUT = 234; // relatively prime with SYNC_TIMEOUT
42
43 function randomString(len)
44 {
45   var s = '';
46   while (len--)
47     s += Math.floor((Math.random() * 36)).toString(36);
48   return s;
49 }
50
51 var getNextChunk = (
52   function () {
53     var nextDocID = 0;
54     var nextChunkID = 0;
55
56     return function () {
57       var doc_id = nextDocID;
58       var chunk_id = nextChunkID;
59
60       nextDocID += 1;
61       if (nextDocID >= MAX_DOC_ID) {
62         nextDocID = 0;
63         nextChunkID += 1;
64         if (nextChunkID >= MAX_CHUNK_ID)
65           nextChunkID = 0;
66       }
67
68       return {
69         docid: doc_id,
70         chunkid: chunk_id,
71         timestamp: new Date(),
72         data: randomString(MAX_CHUNK_SIZE)
73       };
74     };
75   }()
76 );
77
78
79 self.onmessage = function (event) {
80   switch (event.data.type) {
81     case 'offline':
82       goOffline();
83       break;
84     case 'online':
85       goOnline();
86       break;
87     default:
88       throw new Error("Unexpected message: " + event.data.type);
89   }
90 };
91
92
93 var offline = true;
94 var syncTimeoutId = 0;
95 var combineTimeoutId = 0;
96
97 function goOffline() {
98   if (offline)
99     return;
100   log('offline');
101   offline = true;
102   clearTimeout(syncTimeoutId);
103   syncTimeoutId = 0;
104   clearTimeout(combineTimeoutId);
105   combineTimeoutId = 0;
106 }
107
108 function goOnline() {
109   if (!offline)
110     return;
111   offline = false;
112   log('online');
113   syncTimeoutId = setTimeout(sync, SYNC_TIMEOUT);
114   combineTimeoutId = setTimeout(combine, COMBINE_TIMEOUT);
115   // NOTE: Not using setInterval as we need to be sure they complete.
116 }
117
118 var sync_count = 0;
119 function sync() {
120   if (offline)
121     return;
122
123   var sync_id = ++sync_count;
124   log('sync ' + sync_id +  ' started');
125
126   var chunk = getNextChunk();
127   log('sync ' + sync_id +
128       ' adding chunk: ' + chunk.chunkid +
129       ' to doc: ' + chunk.docid);
130
131   var request = indexedDB.open(DBNAME);
132   request.onerror = unexpectedErrorCallback;
133   request.onsuccess = function () {
134     var db = request.result;
135     if (db.version !== DBVERSION) {
136       error('DB version incorrect');
137       return;
138     }
139
140     var transaction = db.transaction('sync-chunks', 'readwrite');
141     var store = transaction.objectStore('sync-chunks');
142     request = store.put(chunk);
143     transaction.onabort = unexpectedAbortCallback;
144     transaction.oncomplete = function () {
145       log('sync ' + sync_id +  ' finished');
146       db.close();
147       syncTimeoutId = setTimeout(sync, SYNC_TIMEOUT);
148     };
149   };
150 }
151
152 var combine_count = 0;
153 function combine() {
154   if (offline)
155     return;
156
157   var combine_id = ++combine_count;
158   log('combine ' + combine_id + ' started');
159
160   var combine_chunk_count = 0;
161
162   var request = indexedDB.open(DBNAME);
163   request.onerror = unexpectedErrorCallback;
164   request.onsuccess = function () {
165     var db = request.result;
166     if (db.version !== DBVERSION) {
167       error('DB version incorrect');
168       return;
169     }
170
171     var transaction = db.transaction(['sync-chunks', 'docs'], 'readwrite');
172     var syncStore = transaction.objectStore('sync-chunks');
173     var docStore = transaction.objectStore('docs');
174
175     var cursorRequest = syncStore.openCursor();
176     cursorRequest.onerror = unexpectedErrorCallback;
177     cursorRequest.onsuccess = function () {
178       var cursor = cursorRequest.result;
179       if (cursor) {
180         combine_chunk_count += 1;
181         log('combine ' + combine_id +
182             ' processing chunk # ' + combine_chunk_count);
183
184         var key = cursor.key;
185         var chunk = cursor.value;
186         var docRequest = docStore.get(chunk.docid);
187         docRequest.onerror = unexpectedErrorCallback;
188         docRequest.onsuccess = function () {
189           var doc = docRequest.result;
190           if (!doc) {
191             doc = {
192               docid: chunk.docid,
193               chunks: []
194             };
195             log('combine # ' + combine_id +
196                 ' created doc: ' + doc.docid);
197           }
198
199           log('combine # ' + combine_id +
200               ' updating doc: ' + doc.docid +
201               ' chunk: ' + chunk.chunkid);
202
203           doc.chunks[chunk.chunkid] = chunk;
204           doc.timestamp = new Date();
205           request = docStore.put(doc);
206           request.onerror = unexpectedErrorCallback;
207           cursor.delete(key);
208           cursor.continue();
209         };
210       } else {
211         // let transaction complete
212         log('combine ' + combine_id +
213             ' done, processed ' + combine_chunk_count + ' chunks');
214       }
215     };
216     transaction.onabort = unexpectedAbortCallback;
217     transaction.oncomplete = function () {
218       log('combine ' + combine_id +
219           ' finished, processed ' + combine_chunk_count + ' chunks');
220       db.close();
221       combineTimeoutId = setTimeout(combine, COMBINE_TIMEOUT);
222     };
223   };
224 }