[gnome-ostree/wip/delayed-zdisks] wip



commit 9ec30314a084dce3fa8ad9997e5090a9ace77690
Author: Colin Walters <walters verbum org>
Date:   Wed Apr 3 10:40:23 2013 -0400

    wip

 Makefile-ostbuild.am               |    2 +
 src/js/task.js                     |   52 ++++++++++++++++++++--
 src/js/tasks/task-builddisks.js    |   13 +++++-
 src/js/tasks/task-dummy-delayed.js |   46 +++++++++++++++++++
 src/js/tasks/task-dummy-resolve.js |   64 ++++++++++++++++++++++++++
 src/js/tasks/task-zdisks.js        |   87 +++++++----------------------------
 6 files changed, 189 insertions(+), 75 deletions(-)
---
diff --git a/Makefile-ostbuild.am b/Makefile-ostbuild.am
index 948b099..3913579 100644
--- a/Makefile-ostbuild.am
+++ b/Makefile-ostbuild.am
@@ -76,6 +76,8 @@ jsosttasks_DATA= \
        src/js/tasks/task-builddisks.js \
        src/js/tasks/task-smoketest.js \
        src/js/tasks/task-zdisks.js \
+       src/js/tasks/task-dummy-resolve.js \
+       src/js/tasks/task-dummy-delayed.js \
        $(NULL)
 
 endif
diff --git a/src/js/task.js b/src/js/task.js
index 54d1ad2..7677428 100644
--- a/src/js/task.js
+++ b/src/js/task.js
@@ -119,17 +119,60 @@ const TaskMaster = new Lang.Class({
        this._taskset = TaskSet.prototype.getInstance();
 
        this._taskVersions = {};
+
+       // string -> [ lastExecutedSecs, [timeoutId, parameters]]
+       this._scheduledTaskTimeouts = {};
+    },
+
+    _pushTaskDefImmediate: function(taskDef, parameters) {
+       let name = taskDef.prototype.TaskName;
+       let instance = new taskDef(this, name, [], parameters);
+       instance.onComplete = Lang.bind(this, this._onComplete, instance);
+       this._pendingTasksList.push(instance);
+       this._queueRecalculate();
     },
 
     _pushTaskDef: function(taskDef, parameters) {
        let name = taskDef.prototype.TaskName;
        if (!this._isTaskPending(name)) {
-           let instance = new taskDef(this, name, [], parameters);
-           instance.onComplete = Lang.bind(this, this._onComplete, instance);
-           this._pendingTasksList.push(instance);
-           this._queueRecalculate();
+           let scheduleMinSecs = taskDef.prototype.TaskScheduleMinSecs;
+           if (scheduleMinSecs > 0) {
+               let info = this._scheduledTaskTimeouts[name];
+               if (!info) {
+                   info = [ 0, [] ];
+                   this._scheduledTaskTimeouts[name] = info;
+               }
+               let lastExecutedSecs = info[0];
+               let pendingExecData = info[1];
+               let currentTime = GLib.get_monotonic_time();
+               if (lastExecutedSecs == 0) {
+                   print("Scheduled task " + name + " executing immediately");
+                   this._pushTaskDefImmediate(taskDef, parameters);
+                   info[0] = currentTime;
+               } else if (pendingExecData != null) {
+                   // Nothing, already scheduled
+               } else {
+                   let delta = (lastExecutedSecs + scheduleMinSecs) - currentTime;
+                   print("Scheduled task " + name + " delta=" + delta);
+                   let timeoutId = GLib.timeout_add_seconds(Math.max(delta, 0),
+                                                            Lang.bind(this, this._executeScheduledTask, 
taskDef));
+                   info[0] = currentTime;
+                   info[1] = [ timeoutId, parameters ];
+               }
+           } else {
+               this._pushTaskDefImmediate(taskDef, parameters);
+           }
        }
     },
+    
+    _executeScheduledTask: function(taskDef) {
+       let name = taskDef.prototype.TaskName;
+       print("Executing scheduled task " + name);
+       let info = this._scheduledTaskTimeouts[name];
+       let params = info[1][1];
+       info[1] = null;
+       this._pushTaskDefImmediate(name);
+    },
 
     pushTask: function(taskName, parameters) {
        let taskDef = this._taskset.getTask(taskName);
@@ -259,6 +302,7 @@ const TaskDef = new Lang.Class({
 
     TaskPattern: null,
     TaskAfter: [],
+    TaskScheduleMinSecs: 0,
 
     PreserveStdout: true,
     RetainFailed: 1,
diff --git a/src/js/tasks/task-builddisks.js b/src/js/tasks/task-builddisks.js
index 690f9da..616988e 100644
--- a/src/js/tasks/task-builddisks.js
+++ b/src/js/tasks/task-builddisks.js
@@ -46,10 +46,13 @@ const TaskBuildDisks = new Lang.Class({
     // Legacy
     _VERSION_RE: /^(\d+)\.(\d+)$/,
 
+    _imageSubdir = 'images',
+    _inheritPreviousDisk = true,
+
     execute: function(cancellable) {
         let subworkdir = Gio.File.new_for_path('.');
 
-             let baseImageDir = this.workdir.get_child('images');
+             let baseImageDir = this.workdir.resolve_relative_path(this._imageSubdir);
         GSystem.file_ensure_directory(baseImageDir, true, cancellable);
              let currentImageLink = baseImageDir.get_child('current');
              let previousImageLink = baseImageDir.get_child('previous');
@@ -84,7 +87,7 @@ const TaskBuildDisks = new Lang.Class({
             let diskPath = workImageDir.get_child(diskName);
             let prevPath = currentImageLink.get_child(diskName);
             GSystem.shutil_rm_rf(diskPath, cancellable);
-            if (prevPath.query_exists(null)) {
+            if (this._inheritPreviousDisk && prevPath.query_exists(null)) {
                 LibQA.copyDisk(prevPath, diskPath, cancellable);
             } else {
                 LibQA.createDisk(diskPath, cancellable);
@@ -105,6 +108,8 @@ const TaskBuildDisks = new Lang.Class({
                 gfmnt.umount(cancellable);
             }
             LibQA.grubInstall(diskPath, cancellable);
+
+            this._postDiskCreation(diskPath, cancellable);
              }
 
         GSystem.file_rename(workImageDir, targetImageDir, cancellable);
@@ -128,6 +133,10 @@ const TaskBuildDisks = new Lang.Class({
         this._cleanOldVersions(baseImageDir, IMAGE_RETAIN_COUNT, cancellable);
     },
 
+    _postDiskCreation: function(diskPath, cancellable) {
+        // Nothing, this is used by zdisks
+    },
+
     _loadVersionsFrom: function(dir, cancellable) {
              let e = dir.enumerate_children('standard::*', Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, 
cancellable);
              let info;
diff --git a/src/js/tasks/task-dummy-delayed.js b/src/js/tasks/task-dummy-delayed.js
new file mode 100644
index 0000000..81c5eb2
--- /dev/null
+++ b/src/js/tasks/task-dummy-delayed.js
@@ -0,0 +1,46 @@
+// Copyright (C) 2011 Colin Walters <walters verbum org>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+const GLib = imports.gi.GLib;
+const Gio = imports.gi.Gio;
+const Lang = imports.lang;
+const Format = imports.format;
+
+const GSystem = imports.gi.GSystem;
+
+const JsonDB = imports.jsondb;
+const Builtin = imports.builtin;
+const Task = imports.task;
+const ProcUtil = imports.procutil;
+const JsonUtil = imports.jsonutil;
+const Snapshot = imports.snapshot;
+const BuildUtil = imports.buildutil;
+const Vcs = imports.vcs;
+const ArgParse = imports.argparse;
+
+const TaskDummyDelayed = new Lang.Class({
+    Name: "TaskDummyDelayed",
+    Extends: Task.TaskDef,
+
+    TaskName: "dummy-delayed",
+    TaskAfter: ['dummy-resolve'], 
+    TaskScheduleMinSecs: 5,
+
+    execute: function(cancellable) {
+       print("delayed firing!");
+    }
+});
diff --git a/src/js/tasks/task-dummy-resolve.js b/src/js/tasks/task-dummy-resolve.js
new file mode 100644
index 0000000..48529ec
--- /dev/null
+++ b/src/js/tasks/task-dummy-resolve.js
@@ -0,0 +1,64 @@
+// Copyright (C) 2011 Colin Walters <walters verbum org>
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the
+// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+// Boston, MA 02111-1307, USA.
+
+const GLib = imports.gi.GLib;
+const Gio = imports.gi.Gio;
+const Lang = imports.lang;
+const Format = imports.format;
+
+const GSystem = imports.gi.GSystem;
+
+const JsonDB = imports.jsondb;
+const Builtin = imports.builtin;
+const Task = imports.task;
+const ProcUtil = imports.procutil;
+const JsonUtil = imports.jsonutil;
+const Snapshot = imports.snapshot;
+const BuildUtil = imports.buildutil;
+const Vcs = imports.vcs;
+const ArgParse = imports.argparse;
+
+const TaskDummyResolve = new Lang.Class({
+    Name: "TaskDummyResolve",
+    Extends: Task.TaskDef,
+
+    TaskName: "dummy-resolve",
+
+    DefaultParameters: {change: false},
+
+    _getDb: function() {
+       if (this._db == null) {
+           let snapshotdir = this.workdir.get_child('dummy-resolve');
+           this._db = new JsonDB.JsonDB(snapshotdir);
+       }
+       return this._db;
+    },
+
+    queryVersion: function() {
+       return this._getDb().getLatestVersion();
+    },
+
+    execute: function(cancellable) {
+       let change = this.parameters.change;
+       let latest = this.queryVersion();
+       if (!latest)
+           change = true;
+       if (change) {
+            let [path, modified] = this._getDb().store({timestamp: GLib.get_current_time() }, cancellable);
+       }
+    }
+});
diff --git a/src/js/tasks/task-zdisks.js b/src/js/tasks/task-zdisks.js
index 4cd6cec..edfb829 100644
--- a/src/js/tasks/task-zdisks.js
+++ b/src/js/tasks/task-zdisks.js
@@ -34,82 +34,31 @@ const JsonUtil = imports.jsonutil;
 const JSUtil = imports.jsutil;
 const GuestFish = imports.guestfish;
 
+const BuildDisks = imports.tasks['task-builddisks'];
+
 const TaskZDisks = new Lang.Class({
     Name: 'TaskZDisks',
-    Extends: Task.TaskDef,
+    Extends: BuildDisks.TaskBuildDisks,
 
     TaskName: "zdisks",
     TaskAfter: ['builddisks'],
+    TaskScheduleMinSecs: 60*60,  // Only do this once an hour
 
     // Legacy
     _VERSION_RE: /^(\d+)\.(\d+)$/,
 
-    execute: function(cancellable) {
-        let subworkdir = Gio.File.new_for_path('.');
-
-             let baseImageDir = this.workdir.resolve_relative_path('images/z');
-        GSystem.file_ensure_directory(baseImageDir, true, cancellable);
-             let currentImageLink = baseImageDir.get_child('current');
-
-             let sourceImageDir = this.workdir.get_child('images');
-        let sourceCurrent = sourceImageDir.get_child('current');
-        let sourceRevision = sourceCurrent.query_info('standard::symlink-target',
-                                                      Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
-                                                      cancellable).get_symlink_target();
-        let targetImageDir = baseImageDir.get_child(sourceRevision);
-        if (targetImageDir.query_exists(null)) {
-            print("Already created " + targetImageDir.get_path());
-            return;
-        }
-
-        let workImageDir = subworkdir.get_child('images');
-        GSystem.file_ensure_directory(workImageDir, true, cancellable);
-
-        let e = sourceCurrent.enumerate_children('standard::*', Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS,
-                                                 cancellable);
-        let info;
-             while ((info = e.next_file(cancellable)) != null) {
-                 let name = info.get_name();
-            if (!JSUtil.stringEndswith(name, '.qcow2'))
-                continue;
-            let inPath = e.get_child(info);
-            let outPath = workImageDir.get_child(name + '.gz');
-            let outStream = outPath.create(Gio.FileCreateFlags.REPLACE_DESTINATION, cancellable);
-            let compressor = Gio.ZlibCompressor.new(Gio.ZlibCompressorFormat.GZIP, 7);
-            let outConverter = Gio.ConverterOutputStream.new(outStream, compressor);
-            let inStream = inPath.read(cancellable);
-            outConverter.splice(inStream, Gio.OutputStreamSpliceFlags.CLOSE_SOURCE | 
-                                Gio.OutputStreamSpliceFlags.CLOSE_TARGET, cancellable);
-        }
-
-        GSystem.file_rename(workImageDir, targetImageDir, cancellable);
-
-        BuildUtil.atomicSymlinkSwap(currentImageLink, targetImageDir, cancellable);
-
-        this._cleanOldVersions(baseImageDir, 1, cancellable);
-    },
-
-    _loadVersionsFrom: function(dir, cancellable) {
-             let e = dir.enumerate_children('standard::*', Gio.FileQueryInfoFlags.NOFOLLOW_SYMLINKS, 
cancellable);
-             let info;
-             let results = [];
-             while ((info = e.next_file(cancellable)) != null) {
-                 let name = info.get_name();
-                 let match = this._VERSION_RE.exec(name);
-                 if (!match)
-                           continue;
-                 results.push(name);
-             }
-             results.sort(BuildUtil.compareVersions);
-             return results;
-    },
-
-    _cleanOldVersions: function(dir, retain, cancellable) {
-             let versions = this._loadVersionsFrom(dir, cancellable);
-             while (versions.length > retain) {
-                 let child = dir.get_child(versions.shift());
-                 GSystem.shutil_rm_rf(child, cancellable);
-             }
-    },
-
+    _imageSubdir = 'images/z',
+    _inheritPreviousDisk = false,
+
+    _postDiskCreation: function(diskPath, cancellable) {
+        let parent = diskPath.get_parent();
+        let outPath = parent.get_child(name + '.gz');
+        let outStream = outPath.create(Gio.FileCreateFlags.REPLACE_DESTINATION, cancellable);
+        let compressor = Gio.ZlibCompressor.new(Gio.ZlibCompressorFormat.GZIP, 7);
+        let outConverter = Gio.ConverterOutputStream.new(outStream, compressor);
+        let inStream = diskPath.read(cancellable);
+        outConverter.splice(inStream, Gio.OutputStreamSpliceFlags.CLOSE_SOURCE | 
+                            Gio.OutputStreamSpliceFlags.CLOSE_TARGET, cancellable);
+        diskPath.delete(cancellable);
+    }
 });


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]