javascript/api/src/naming: Add a mounttable client library.
Also use it in the veyron_browser demo. I've only implemented
the parts I needed. It will be easy to add the rest.
Change-Id: I538249053601c383b1be9c23374f0f0a6ffe62c7
diff --git a/examples/veyron_browser/Makefile b/examples/veyron_browser/Makefile
index eb3c8a0..1c8bc3b 100644
--- a/examples/veyron_browser/Makefile
+++ b/examples/veyron_browser/Makefile
@@ -11,6 +11,7 @@
VEYRON_IDENTITYD= ../../../../bin/identityd
VEYRON_STORE= ../../../../bin/stored
VEYRON_MOUNTTABLE_PORT= 5167
+VEYRON_MOUNTTABLE_PORT2= 5168
VEYRON_PROXY_PORT= 5164
VEYRON_PROXY_ADDR= 127.0.0.1:$(VEYRON_PROXY_PORT)
VEYRON_WSPR_PORT= 5165
@@ -40,14 +41,17 @@
export VEYRON_IDENTITY=$(VEYRON_IDENTITY_PATH) ; \
$(VEYRON_IDENTITYD) --port=$(VEYRON_IDENTITY_PORT) & \
- $(VEYRON_MOUNTTABLE) --address=:$(VEYRON_MOUNTTABLE_PORT) & \
- export MOUNTTABLE_ROOT=/localhost:$(VEYRON_MOUNTTABLE_PORT)/mt ; \
+ $(VEYRON_MOUNTTABLE) --address=:$(VEYRON_MOUNTTABLE_PORT) --prefix= & \
+ export MOUNTTABLE_ROOT=/localhost:$(VEYRON_MOUNTTABLE_PORT) ; \
$(VEYRON_PROXY) -address=$(VEYRON_PROXY_ADDR) & \
$(VEYRON_WSPR) --v=3 -logtostderr=true -vproxy=$(VEYRON_PROXY_ADDR) --port $(VEYRON_WSPR_PORT) & \
+ $(VEYRON_MOUNTTABLE) --address=:$(VEYRON_MOUNTTABLE_PORT2) --name=global --prefix= & \
+ sleep 1 ; \
$(VEYRON_STORE) --address=:$(VEYRON_STORE_PORT) --name=global/$(USER)/store &
killdaemons:
kill `lsof -t -i:$(VEYRON_MOUNTTABLE_PORT)`; \
+ kill `lsof -t -i:$(VEYRON_MOUNTTABLE_PORT2)`; \
kill `lsof -t -i:$(VEYRON_IDENTITY_PORT)`; \
kill `lsof -t -i:$(VEYRON_WSPR_PORT)`; \
kill `lsof -t -i:$(VEYRON_PROXY_PORT)`; \
diff --git a/examples/veyron_browser/browser/client/client.html b/examples/veyron_browser/browser/client/client.html
index 87cecf8..7bd1880 100644
--- a/examples/veyron_browser/browser/client/client.html
+++ b/examples/veyron_browser/browser/client/client.html
@@ -19,7 +19,7 @@
</head>
<body onload="init()">
<div>
- Enter mounttable: <input id="mt" type="text" value="/localhost:5167//mt"></input><input type="submit" value="connect" onclick="init()"></input>
+ Enter mounttable: <input id="mt" type="text" value=""></input><input type="submit" value="connect" onclick="init()"></input>
</div>
<div>
Enter query: <input id="query" type="text" onkeyup="handleChange()" value="*"></input>
diff --git a/examples/veyron_browser/browser/client/client.js b/examples/veyron_browser/browser/client/client.js
index 5c8f933..4fc7c4d 100644
--- a/examples/veyron_browser/browser/client/client.js
+++ b/examples/veyron_browser/browser/client/client.js
@@ -1,81 +1,63 @@
var veyron = new Veyron(veyronConfig);
+var mountTable = veyron.newMountTable();
var client = veyron.newClient();
var mp;
-//TODO(bprosnitz) Remove setup mount. This is used to populate the mount table.
-var setupMounts = function() {
- return Promise.all([
- mp.appendToPath('other').mount('/@2@tcp@[::]:111@e73f89469f6ec8252f9e0c7bbe5dd516@1@1@@/FAKE/ADDRESS'),
- mp.appendToPath('recurse').mount(mp.addr),
- mp.appendToPath('a/b/recurse').mount(mp.addr)]);
-}
-
-var promiseChain = null;
var init = function() {
var mtAddr = document.getElementById('mt').value;
- mp = new MountPoint(client, mtAddr);
- promiseChain = setupMounts();
- handleChange();
+ mountTable.then(function(mt) {
+ mp = new MountPoint(client, mt, mtAddr);
+ handleChange();
+ });
}
var updateResults = function(query) {
var results = document.getElementById('results');
results.innerHTML = '<i>Loading results...</i>';
- promiseChain.then(function() {
- // perform query.
- mp.glob(query).then(function(items) {
- // generate the results list.
- var list = document.createElement('ul');
- for (var i in items) {
- var item = items[i];
- var li = document.createElement('li');
- var a = document.createElement('a');
-
- a.innerHTML = item.name + ' - ' + JSON.stringify(item);
- (function(item, a) {
- isMounttable(client, item).then(function(isMt) {
- if (!isMt) {
- a.className = "service";
+ // perform query.
+ mp.glob(query).then(function(items) {
+ // generate the results list.
+ var list = document.createElement('ul');
+ for (var i in items) {
+ var item = items[i];
+ var li = document.createElement('li');
+ var a = document.createElement('a');
+
+ a.innerHTML = item.name + ' - ' + JSON.stringify(item);
+ (function(item, a) {
+ isMounttable(client, item).then(function(isMt) {
+ if (!isMt) {
+ a.className = "service";
+ } else {
+ a.href = '#';
+ a.onclick = function() {
+ mp = mp.appendToPath(item.name);
+ handleChange();
+ };
+ if (item.servers.length > 0) {
+ a.className = 'remote';
} else {
- a.href = '#';
- if (item.servers.length > 0) {
- // switch mounttable address if this is a remote server.
- a.className = 'remote';
- a.onclick = function() {
- mt = item.servers[0].server;
- document.getElementById('mt').value = mt;
- document.getElementById('query').value = '*';
- handleChange();
- };
- } else {
- // if this is in the current mounttable, modify the query.
- a.className = 'local';
- a.onclick = function() {
- document.getElementById('query').value = item.name + '/*';
- handleChange();
- };
- }
+ a.className = 'local';
}
- }, function(reason) {
- console.error('Error testing mounttable: ', reason);
- a.className = "error";
- });
- })(item, a);
-
- li.appendChild(a);
- list.appendChild(li);
- }
- results.innerHTML = '';
- results.appendChild(list);
- }).catch(function(msg) {
- console.error('Problem loading page: ' + msg);
- });
- }).catch(function(err) {
- console.error(err);
+ }
+ }, function(reason) {
+ console.error('Error testing mounttable: ', reason);
+ a.className = "error";
+ });
+ })(item, a);
+
+ li.appendChild(a);
+ list.appendChild(li);
+ }
+ results.innerHTML = '';
+ results.appendChild(list);
+ }).catch(function(msg) {
+ console.error('Problem loading page: ' + msg);
});
}
var handleChange = function() {
+ document.getElementById('mt').value = mp.name;
updateResults(document.getElementById('query').value);
}
diff --git a/examples/veyron_browser/browser/client/mounttable.js b/examples/veyron_browser/browser/client/mounttable.js
index ad3bdbd..ad79a28 100644
--- a/examples/veyron_browser/browser/client/mounttable.js
+++ b/examples/veyron_browser/browser/client/mounttable.js
@@ -3,12 +3,30 @@
* MountPoint handles manipulating and querying from
* a mounttable.
* @param {object} client A veyron client.
+ * @param {object} mountTable A veyron MountTable instance.
* @param {...string} addressParts Parts of the address to join
* @constructor
*/
-var MountPoint = function(client, addressParts) {
- this.client = client
- this.addr = Array.prototype.slice.call(arguments, 1).join('/');
+var MountPoint = function(client, mountTable, addressParts) {
+ this.client = client;
+ this.mountTable = mountTable;
+ this.name = Array.prototype.slice.call(arguments, 2).join('/');
+ this._terminalNames = null;
+}
+
+/**
+ * A helper method that returns the terminal names for this
+ * MountPoint and memoizes them.
+ * @return {Promise} A promise that resolves to a list of terminal names.
+ */
+MountPoint.prototype._getTerminalNames = function() {
+ // We resolve to a terminal name manually because veyron rpc calls
+ // wont usually resolve a name if it's to a mounttable. We
+ // would like to interact with all kinds of servers.
+ if (!this._terminalNames) {
+ this._terminalNames = this.mountTable.resolveMaximally(this.name);
+ }
+ return this._terminalNames;
}
/**
@@ -19,8 +37,10 @@
*/
MountPoint.prototype.appendToPath = function(toAdd) {
var args = Array.prototype.slice.call(arguments);
- args.unshift(this.addr);
- return new MountPoint(this.client, args.join('/'));
+ if (this.name.length > 0) {
+ args.unshift(this.name);
+ }
+ return new MountPoint(this.client, this.mountTable, args.join('/'));
}
/**
@@ -29,8 +49,12 @@
* @return {promise} a promise that completes when it is mounted
*/
MountPoint.prototype.mount = function(target) {
- return this.client.bind(this.addr).then(function(mtService) {
- return mtService.mount(target, 0);
+ return this._getTerminalNames().then(function(terminalNames) {
+ // TODO(mattr): We should try all the names instead of just the first.
+ // Perhpas the library should allow me to pass a list of names.
+ return this.client.bind(terminalNames[0]).then(function(mtService) {
+ return mtService.mount(target, 0);
+ })
});
}
@@ -41,19 +65,23 @@
*/
MountPoint.prototype.glob = function(expr) {
var results = [];
- return this.client.bind(this.addr).then(function(mtService) {
- var promise = mtService.glob(expr);
- var stream = promise.stream;
-
- stream.on('readable', function() {
- var val = stream.read();
- if (val) {
- results.push(val);
- }
- });
-
- return promise.then(function() {
- return results;
+ return this._getTerminalNames().then(function(terminalNames) {
+ // TODO(mattr): We should try all the names instead of just the first.
+ // Perhpas the library should allow me to pass a list of names.
+ return this.client.bind(terminalNames[0]).then(function(mtService) {
+ var promise = mtService.glob(expr);
+ var stream = promise.stream;
+
+ stream.on('readable', function() {
+ var val = stream.read();
+ if (val) {
+ results.push(val);
+ }
+ });
+
+ return promise.then(function() {
+ return results;
+ });
});
});
};
@@ -96,4 +124,4 @@
exports.MountPoint = MountPoint;
exports.isMounttable = isMounttable;
-})(window);
\ No newline at end of file
+})(window);
diff --git a/examples/veyron_browser/browser/config.js b/examples/veyron_browser/browser/config.js
index 6147fda..041055e 100644
--- a/examples/veyron_browser/browser/config.js
+++ b/examples/veyron_browser/browser/config.js
@@ -16,4 +16,4 @@
// Daemon that handles JavaScript communication with the rest of Veyron
'proxy': 'http://localhost:5165'
-};
\ No newline at end of file
+};