emscripten Humble Cloud interface
Edward Rudd
2014-08-21 a4dfaf4e8da2877a7aa53a6267c0b32cb0e03a42

add in initial "basic syncing".. reading works.. not writing yet.

2 files modified
145 ■■■■■ changed files
client/library/library_cloudfs.js 141 ●●●●● patch | view | raw | blame | history
humble_cloud/urkle_cloud.js 4 ●●●● patch | view | raw | blame | history
client/library/library_cloudfs.js
@@ -32,8 +32,7 @@
                    console.log('source', src);
                    console.log('destination', dst);
                    // say we completed (for now)
                    callback(null);
                    CLOUDFS.reconcile(mount, src, dst, callback);
                });
            });
        },
@@ -134,6 +133,144 @@
          }, function(e) {
            callback(e || new Error('failed request'));
          });
        },
        // Fetching local and remote files
        loadLocalEntry: function(path, callback) {
            var stat, node;
            try {
                var lookup = FS.lookupPath(path);
                node = lookup.node;
                stat = FS.stat(path);
            } catch (e) {
                return callback(e);
            }
            if (FS.isDir(stat.mode)) {
                return callback(null, { timestamp: stat.mtime, mode: stat.mode });
            } else if (FS.isFile(stat.mode)) {
                // Performance consideration: storing a normal JavaScript array to a IndexedDB is much slower than storing a typed array.
                // Therefore always convert the file contents to a typed array first before writing the data to IndexedDB.
                node.contents = MEMFS.getFileDataAsTypedArray(node);
                return callback(null, { timestamp: stat.mtime, mode: stat.mode, contents: node.contents });
            } else {
                return callback(new Error('node type not supported'));
            }
        },
        loadRemoteEntry: function(mount, pathinfo, callback) {
            if (pathinfo.type == 'file') {
                mount.opts.provider.downloadFile(mount.opts.cloud, pathinfo.url,
                    function(data) {
                        callback(null, { contents: data, timestamp: pathinfo.timestamp, mode: {{{ cDefine('S_IFREG') | 0777 }}} });
                    },
                    function(e) {
                        callback(e);
                    });
            } else {
                callback(null, { timestamp: pathinfo.timestamp, mode: {{{ cDefine('S_IFDIR') | 0777 }}} });
            }
        },
        // storing local and remote files
        storeLocalEntry: function(path, entry, callback) {
            try {
                if (FS.isDir(entry.mode)) {
                    FS.mkdir(path, entry.mode);
                } else if (FS.isFile(entry.mode)) {
                    FS.writeFile(path, entry.contents, { encoding: 'binary', canOwn: true });
                } else {
                    return callback(new Error('node type not supported'));
                }
                FS.utime(path, entry.timestamp, entry.timestamp);
            } catch (e) {
                return callback(e);
            }
            callback(null);
        },
        storeRemoteEntry: function(mount, pathinfo, entry, callback) {
            if (FS.isFile(entry.mode)) {
                mount.opts.provider.uploadFile(mount.opts.cloud, pathinfo.path, entry.contents, function() {
                    callback(null);
                },
                function(e) {
                    callback(e);
                })
            }
        },
        // handling the diffing of "haves" and "have nots"
        reconcile: function(mount, src, dst, callback) {
            var total = 0;
            var create = [];
            Object.keys(src.entries).forEach(function (key) {
                var e = src.entries[key];
                var e2 = dst.entries[key];
                if (!e2 || e.timestamp > e2.timestamp) {
                    create.push(key);
                    total++;
                }
            });
/*
            var remove = [];
            Object.keys(dst.entries).forEach(function (key) {
                var e = dst.entries[key];
                var e2 = src.entries[key];
                if (!e2) {
                    remove.push(key);
                    total++;
                }
            });
*/
            if (!total) {
                return callback(null);
            }
            var completed = 0;
            function done(err) {
                console.log('Done called', completed, total);
                if (err) {
                    if (!done.errored) {
                        done.errored = true;
                        return callback(err);
                    }
                    return;
                }
                if (++completed >= total) {
                    return callback(null);
                }
            };
            // sort paths in ascending order so directory entries are created
            // before the files inside them
            create.sort().forEach(function (path) {
                var pathinfo = src.entries[path];
                if (dst.type === 'local') {
                    CLOUDFS.loadRemoteEntry(mount, pathinfo, function (err, entry) {
                        if (err) return done(err);
                        CLOUDFS.storeLocalEntry(path, entry, done);
                    });
                } else {
                    CLOUDFS.loadLocalEntry(path, function (err, entry) {
                        if (err) return done(err);
                        CLOUDFS.storeRemoteEntry(mount, pathinfo, entry, done);
                    });
                }
            });
            return;
            // sort paths in descending order so files are deleted before their
            // parent directories
            remove.sort().reverse().forEach(function(path) {
                var info = dst.entries[path];
                if (dst.type === 'local') {
                    CLOUDFS.removeLocalEntry(path, info, done);
                } else {
                    CLOUDFS.removeRemoteEntry(path, info, done);
                }
            });
        }
    }
};
humble_cloud/urkle_cloud.js
@@ -37,8 +37,8 @@
                onsuccess(ret)
            }, onerror);
        },
        downloadFile: function() {
        downloadFile: function(options, url, onsuccess, onerror) {
            xhrGET(url, onsuccess, onerror);
        },
        uploadFile: function() {