diff options
author | Alexander Sulfrian <alexander@sulfrian.net> | 2010-06-08 08:22:05 +0200 |
---|---|---|
committer | Alexander Sulfrian <alexander@sulfrian.net> | 2010-06-08 08:22:05 +0200 |
commit | d7c5ad7d6263fd1baf9bfdbaa4c50b70ef2fbdb2 (patch) | |
tree | ae0b65da6432f4c26c8d5a7319efbda5d172846c /trunk/etherpad/src/etherpad/pad/pad_migrations.js | |
parent | fa61221dcd89fcd72cba2c97971626f456c86e5d (diff) | |
download | etherpad-d7c5ad7d6263fd1baf9bfdbaa4c50b70ef2fbdb2.tar.gz etherpad-d7c5ad7d6263fd1baf9bfdbaa4c50b70ef2fbdb2.tar.xz etherpad-d7c5ad7d6263fd1baf9bfdbaa4c50b70ef2fbdb2.zip |
reverted folder structure change for better mergeing with upstream
Diffstat (limited to 'trunk/etherpad/src/etherpad/pad/pad_migrations.js')
-rw-r--r-- | trunk/etherpad/src/etherpad/pad/pad_migrations.js | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/trunk/etherpad/src/etherpad/pad/pad_migrations.js b/trunk/etherpad/src/etherpad/pad/pad_migrations.js new file mode 100644 index 0000000..e81cf63 --- /dev/null +++ b/trunk/etherpad/src/etherpad/pad/pad_migrations.js @@ -0,0 +1,206 @@ +/** + * Copyright 2009 Google Inc. + * + * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS-IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import("sqlbase.sqlobj"); +import("etherpad.pad.model"); +import("etherpad.pad.easysync2migration"); +import("sqlbase.sqlcommon"); +import("sqlbase.sqlobj"); +import("etherpad.log"); +import("etherpad.pne.pne_utils"); +jimport("java.util.concurrent.ConcurrentHashMap"); +jimport("java.lang.System"); +jimport("java.util.ArrayList"); +jimport("java.util.Collections"); + +function onStartup() { + if (! appjet.cache.pad_migrations) { + appjet.cache.pad_migrations = {}; + } + + // this part can be removed when all pads are migrated on pad.spline.inf.fu-berlin.de + //if (! pne_utils.isPNE()) { + // System.out.println("Building cache for live migrations..."); + // initLiveMigration(); + //} +} + +function initLiveMigration() { + + if (! appjet.cache.pad_migrations) { + appjet.cache.pad_migrations = {}; + } + appjet.cache.pad_migrations.doingAnyLiveMigrations = true; + appjet.cache.pad_migrations.doingBackgroundLiveMigrations = true; + appjet.cache.pad_migrations.padMap = new ConcurrentHashMap(); + + // presence of a pad in padMap indicates migration is needed + var padMap = _padMap(); + var migrationsNeeded = sqlobj.selectMulti("PAD_SQLMETA", {version: 1}); + migrationsNeeded.forEach(function(obj) { + padMap.put(String(obj.id), {from: obj.version}); + }); +} + +function _padMap() { + return appjet.cache.pad_migrations.padMap; +} + +function _doingItLive() { + return !! appjet.cache.pad_migrations.doingAnyLiveMigrations; +} + +function checkPadStatus(padId) { + if (! _doingItLive()) { + return "ready"; + } + var info = _padMap().get(padId); + if (! info) { + return "ready"; + } + else if (info.migrating) { + return "migrating"; + } + else { + return "oldversion"; + } +} + +function ensureMigrated(padId, async) { + if (! _doingItLive()) { + return false; + } + + var info = _padMap().get(padId); + if (! info) { + // pad is up-to-date + return false; + } + else if (async && info.migrating) { + // pad is already being migrated, don't wait on the lock + return false; + } + + return model.doWithPadLock(padId, function() { + // inside pad lock... + var info = _padMap().get(padId); + if (!info) { + return false; + } + // migrate from version 1 to version 2 in a transaction + var migrateSucceeded = false; + try { + info.migrating = true; + log.info("Migrating pad "+padId+" from version 1 to version 2..."); + + var success = false; + var whichTry = 1; + while ((! success) && whichTry <= 3) { + success = sqlcommon.inTransaction(function() { + try { + easysync2migration.migratePad(padId); + sqlobj.update("PAD_SQLMETA", {id: padId}, {version: 2}); + return true; + } + catch (e if (e.toString().indexOf("try restarting transaction") >= 0)) { + whichTry++; + return false; + } + }); + if (! success) { + java.lang.Thread.sleep(Math.floor(Math.random()*200)); + } + } + if (! success) { + throw new Error("too many retries"); + } + + migrateSucceeded = true; + log.info("Migrated pad "+padId+"."); + _padMap().remove(padId); + } + finally { + info.migrating = false; + if (! migrateSucceeded) { + log.info("Migration failed for pad "+padId+"."); + throw new Error("Migration failed for pad "+padId+"."); + } + } + return true; + }); +} + +function numUnmigratedPads() { + if (! _doingItLive()) { + return 0; + } + + return _padMap().size(); +} + +////////// BACKGROUND MIGRATIONS + +function _logPadMigration(runnerId, padNumber, padTotal, timeMs, fourCharResult, padId) { + log.custom("pad_migrations", { + runnerId: runnerId, + padNumber: Math.round(padNumber+1), + padTotal: Math.round(padTotal), + timeMs: Math.round(timeMs), + fourCharResult: fourCharResult, + padId: padId}); +} + +function _getNeededMigrationsArrayList(filter) { + var L = new ArrayList(_padMap().keySet()); + for(var i=L.size()-1; i>=0; i--) { + if (! filter(String(L.get(i)))) { + L.remove(i); + } + } + return L; +} + +function runBackgroundMigration(residue, modulus, runnerId) { + var L = _getNeededMigrationsArrayList(function(padId) { + return (padId.charCodeAt(0) % modulus) == residue; + }); + Collections.shuffle(L); + + var totalPads = L.size(); + for(var i=0;i<totalPads;i++) { + if (! appjet.cache.pad_migrations.doingBackgroundLiveMigrations) { + break; + } + var padId = L.get(i); + var result = "FAIL"; + var t1 = System.currentTimeMillis(); + try { + if (ensureMigrated(padId, true)) { + result = " OK "; // migrated successfully + } + else { + result = " -- "; // no migration needed after all + } + } + catch (e) { + // e just says "migration failed", but presumably + // inTransaction() printed a stack trace. + // result == "FAIL", do nothing. + } + var t2 = System.currentTimeMillis(); + _logPadMigration(runnerId, i, totalPads, t2 - t1, result, padId); + } +} |