Comparar commits
26 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 2eb037d800 | |||
| 162cefd77e | |||
| 5fc63001f0 | |||
| 16668468f4 | |||
| ffae88a168 | |||
| 25f5759c17 | |||
| 7a0eae386f | |||
| af5d74483a | |||
| 9bf7632aba | |||
| d7f3544bb3 | |||
| 19a7b2a8fa | |||
| aadd581189 | |||
| a5d00efd39 | |||
| a239c7bd44 | |||
| 5871b5058e | |||
| 3a8108b321 | |||
| b18a3b2747 | |||
| 884ba2557f | |||
| e2d3058de1 | |||
| 02739bfd62 | |||
| 89e2e387c7 | |||
| 0ac2b1b6ab | |||
| a36e8df404 | |||
| 93a89ddaa1 | |||
| 7281dcefc6 | |||
| bfc1f08c7e |
+9
-3
@@ -7,7 +7,13 @@
|
||||
**Notice**: DeepForge is still a work in progress and is also lacking significant documentation! That being said, any contributions and/or feedback is greatly appreciated (and feel free to always ask any questions on the gitter)!
|
||||
|
||||
# DeepForge
|
||||
DeepForge is an open-source visual development environment for deep learning. Currently, it supports Convolutional Neural Networks but we are planning on supporting additional deep learning classifiers such as RNNs and LSTMs. Additional features include real-time collaborative editing and version control.
|
||||
DeepForge is an open-source visual development environment for deep learning. Currently, it supports Convolutional Neural Networks, RNNs and LSTMs as well as the creation of custom layers. Additional features include:
|
||||
- Graphical architecture editor
|
||||
- Training/testing pipeline creation
|
||||
- Distributed pipeline execution
|
||||
- Real-time pipeline feedback
|
||||
- Collaborative editing
|
||||
- Automatic version control.
|
||||
|
||||
## Quick Start
|
||||
Simply run the following command to install deepforge with its dependencies:
|
||||
@@ -22,9 +28,9 @@ Or, if you already have NodeJS (v6) installed, simply run
|
||||
npm install -g deepforge
|
||||
```
|
||||
|
||||
Next, start deepforge with `deepforge start`!
|
||||
Finally, start deepforge with `deepforge start`and navigate to [http://localhost:8888](http://localhost:8888) to start using DeepForge! For more, detailed instructions, check out the [wiki](https://github.com/dfst/deepforge/wiki/Installation-Guide).
|
||||
|
||||
Finally, navigate to [http://localhost:8888](http://localhost:8888) to start using DeepForge! For more, detailed instructions, check out the [wiki](https://github.com/dfst/deepforge/wiki/Installation-Guide).
|
||||
**Note**: running deepforge w/ `deepforge start` will also require [MongoDB](https://www.mongodb.com/download-center?jmp=nav#community) to be installed locally.
|
||||
|
||||
Also, be sure to check out the other available features of the `deepforge` cli; it can be used to update, manage your torch installation, uninstall deepforge and run individual components!
|
||||
|
||||
|
||||
@@ -46,8 +46,8 @@
|
||||
"CHFLayout": {
|
||||
"panels": [
|
||||
{
|
||||
"id": "Header",
|
||||
"panel": "BreadcrumbHeader/BreadcrumbHeaderPanel",
|
||||
"id": "WorkerHeader",
|
||||
"panel": "WorkerHeader/WorkerHeaderPanel",
|
||||
"container": "header",
|
||||
"DEBUG_ONLY": false
|
||||
},
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
var config = require('./config.default');
|
||||
var config = require('./config.default'),
|
||||
path = require('path');
|
||||
|
||||
config.server.port = 9001;
|
||||
config.mongo.uri = 'mongodb://127.0.0.1:27017/webgme_tests';
|
||||
config.blob.fsDir = path.join(__dirname, '..', 'test-tmp', 'blob');
|
||||
|
||||
module.exports = config;
|
||||
module.exports = config;
|
||||
|
||||
+23
-20
@@ -6,33 +6,36 @@
|
||||
var config = require('webgme/config/config.default'),
|
||||
validateConfig = require('webgme/config/validator');
|
||||
|
||||
|
||||
// The paths can be loaded from the webgme-setup.json
|
||||
config.plugin.basePaths.push('src/plugins');
|
||||
config.plugin.basePaths.push('node_modules/webgme-simple-nodes/src/plugins');
|
||||
config.visualization.layout.basePaths.push('node_modules/webgme-chflayout/src/layouts');
|
||||
config.visualization.decoratorPaths.push('src/decorators');
|
||||
config.visualization.decoratorPaths.push('node_modules/webgme-easydag/src/decorators');
|
||||
config.seedProjects.basePaths.push('src/seeds/nn');
|
||||
config.seedProjects.basePaths.push('src/seeds/devTests');
|
||||
config.seedProjects.basePaths.push('src/seeds/devUtilTests');
|
||||
config.seedProjects.basePaths.push('src/seeds/pipeline');
|
||||
config.seedProjects.basePaths.push('src/seeds/devPipelineTests');
|
||||
config.seedProjects.basePaths.push('src/seeds/project');
|
||||
config.seedProjects.basePaths.push('src/seeds/cifar10');
|
||||
config.seedProjects.basePaths.push('src/seeds/xor');
|
||||
config.plugin.basePaths.push(__dirname + '/../src/plugins');
|
||||
config.plugin.basePaths.push(__dirname + '/../node_modules/webgme-simple-nodes/src/plugins');
|
||||
config.visualization.layout.basePaths.push(__dirname + '/../node_modules/webgme-chflayout/src/layouts');
|
||||
config.visualization.decoratorPaths.push(__dirname + '/../src/decorators');
|
||||
config.visualization.decoratorPaths.push(__dirname + '/../node_modules/webgme-easydag/src/decorators');
|
||||
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/nn');
|
||||
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/devTests');
|
||||
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/devUtilTests');
|
||||
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/pipeline');
|
||||
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/devPipelineTests');
|
||||
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/project');
|
||||
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/cifar10');
|
||||
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/xor');
|
||||
config.seedProjects.basePaths.push(__dirname + '/../src/seeds/devProject');
|
||||
|
||||
|
||||
|
||||
config.visualization.panelPaths.push('node_modules/webgme-fab/src/visualizers/panels');
|
||||
config.visualization.panelPaths.push('node_modules/webgme-breadcrumbheader/src/visualizers/panels');
|
||||
config.visualization.panelPaths.push('node_modules/webgme-autoviz/src/visualizers/panels');
|
||||
config.visualization.panelPaths.push('node_modules/webgme-easydag/src/visualizers/panels');
|
||||
config.visualization.panelPaths.push('src/visualizers/panels');
|
||||
config.visualization.panelPaths.push(__dirname + '/../node_modules/webgme-fab/src/visualizers/panels');
|
||||
config.visualization.panelPaths.push(__dirname + '/../node_modules/webgme-breadcrumbheader/src/visualizers/panels');
|
||||
config.visualization.panelPaths.push(__dirname + '/../node_modules/webgme-autoviz/src/visualizers/panels');
|
||||
config.visualization.panelPaths.push(__dirname + '/../node_modules/webgme-easydag/src/visualizers/panels');
|
||||
config.visualization.panelPaths.push(__dirname + '/../src/visualizers/panels');
|
||||
|
||||
|
||||
config.rest.components['execution/logs'] = __dirname + '/../src/routers/JobLogsAPI/JobLogsAPI.js';
|
||||
config.rest.components['job/origins'] = __dirname + '/../src/routers/JobOriginAPI/JobOriginAPI.js';
|
||||
|
||||
// Visualizer descriptors
|
||||
config.visualization.visualizerDescriptors.push('./src/visualizers/Visualizers.json');
|
||||
config.visualization.visualizerDescriptors.push(__dirname + '/../src/visualizers/Visualizers.json');
|
||||
// Add requirejs paths
|
||||
config.requirejsPaths = {
|
||||
'EllipseDecorator': 'node_modules/webgme-easydag/src/decorators/EllipseDecorator',
|
||||
|
||||
+4
-2
@@ -8,17 +8,19 @@
|
||||
"start-dev": "NODE_ENV=dev node app.js",
|
||||
"local": "node ./bin/start-local.js",
|
||||
"worker": "node ./bin/start-worker.js",
|
||||
"test": "node ./node_modules/mocha/bin/mocha --recursive test",
|
||||
"test": "mkdir ./test-tmp; node ./node_modules/mocha/bin/mocha --recursive test",
|
||||
"watch-test": "./node_modules/nodemon/bin/nodemon.js --exec 'node ./node_modules/mocha/bin/mocha --recursive test'",
|
||||
"build-nn": "node ./utils/nn-parser.js"
|
||||
},
|
||||
"version": "0.15.0",
|
||||
"version": "0.17.0",
|
||||
"dependencies": {
|
||||
"commander": "^2.9.0",
|
||||
"dotenv": "^2.0.0",
|
||||
"exists-file": "^2.1.0",
|
||||
"express": "^4.14.0",
|
||||
"lodash.difference": "^4.1.2",
|
||||
"lodash.merge": "^4.5.1",
|
||||
"mongodb": "^2.2.10",
|
||||
"nodemon": "^1.9.2",
|
||||
"q": "1.4.1",
|
||||
"rimraf": "^2.4.0",
|
||||
|
||||
@@ -5,7 +5,13 @@ define({
|
||||
// DeepForge metadata creation in dist execution
|
||||
START_CMD: 'deepforge-cmd',
|
||||
|
||||
IMAGE: 'IMG',
|
||||
IMAGE: { // all prefixed w/ 'IMG' for simple upload detection
|
||||
PREFIX: 'IMG',
|
||||
BASIC: 'IMG-B',
|
||||
CREATE: 'IMG-C',
|
||||
UPDATE: 'IMG-U',
|
||||
NAME: 'IMAGE-N' // No upload required
|
||||
},
|
||||
|
||||
GRAPH_CREATE: 'GRAPH',
|
||||
GRAPH_PLOT: 'PLOT',
|
||||
@@ -18,5 +24,8 @@ define({
|
||||
OP: {
|
||||
INPUT: 'Input',
|
||||
OUTPUT: 'Output'
|
||||
}
|
||||
},
|
||||
|
||||
// Job stdout update
|
||||
STDOUT_UPDATE: 'stdout_update'
|
||||
});
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*globals define*/
|
||||
define([
|
||||
'q',
|
||||
'superagent'
|
||||
], function(
|
||||
Q,
|
||||
superagent
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
// Wrap the ability to read, update, and delete logs using the JobLogsAPI
|
||||
var APIClient = function(params) {
|
||||
params = params || {};
|
||||
|
||||
this.logger = this.logger || params.logger.fork('APIClient');
|
||||
|
||||
// Get the server url
|
||||
this.token = params.token;
|
||||
this.origin = this._getServerUrl(params);
|
||||
this.relativeUrl = this.relativeUrl || '';
|
||||
this.url = this.origin + this.relativeUrl;
|
||||
|
||||
this.logger.debug(`Setting url to ${this.url}`);
|
||||
|
||||
this.branch = params.branchName;
|
||||
this.project = params.projectId;
|
||||
this._modifiedJobs = [];
|
||||
|
||||
this.logger.debug(`Using <project>:<branch>: "${this.project}"/"${this.branch}"`);
|
||||
this.logger.info('ctor finished');
|
||||
};
|
||||
|
||||
APIClient.prototype._getServerUrl = function(params) {
|
||||
if (typeof window !== 'undefined') {
|
||||
return window.location.origin;
|
||||
}
|
||||
|
||||
// If not in browser, set using the params
|
||||
var server = params.server || '127.0.0.1',
|
||||
port = params.port || '80',
|
||||
protocol = params.httpsecure ? 'https' : 'http'; // default is http
|
||||
|
||||
return params.origin || `${protocol}://${server}:${port}`;
|
||||
};
|
||||
|
||||
APIClient.prototype.getUrl = function() {
|
||||
return this.url;
|
||||
};
|
||||
|
||||
APIClient.prototype._request = function(method, jobId, content) {
|
||||
var deferred = Q.defer(),
|
||||
req = superagent[method](this.getUrl(jobId));
|
||||
|
||||
this.logger.info(`sending ${method} request to ${this.getUrl(jobId)}`);
|
||||
if (this.token) {
|
||||
req.set('Authorization', 'Bearer ' + this.token);
|
||||
}
|
||||
|
||||
if (content) {
|
||||
req = req.send(content);
|
||||
}
|
||||
|
||||
req.end((err, res) => {
|
||||
if (err || res.status > 399) {
|
||||
return deferred.reject(res || err);
|
||||
}
|
||||
|
||||
return deferred.resolve(res);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
return APIClient;
|
||||
});
|
||||
@@ -0,0 +1,92 @@
|
||||
/* globals define */
|
||||
define([
|
||||
'./APIClient',
|
||||
'q',
|
||||
'superagent'
|
||||
], function(
|
||||
APIClient,
|
||||
Q,
|
||||
superagent
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
// Wrap the ability to read, update, and delete logs using the JobLogsAPI
|
||||
var JobLogsClient = function(params) {
|
||||
params = params || {};
|
||||
|
||||
this.relativeUrl = '/execution/logs';
|
||||
this.logger = params.logger.fork('JobLogsClient');
|
||||
APIClient.call(this, params);
|
||||
|
||||
// Get the project, branch name
|
||||
if (!(params.branchName && params.projectId)) {
|
||||
throw Error('"branchName" and "projectId" required');
|
||||
}
|
||||
|
||||
this._modifiedJobs = [];
|
||||
|
||||
this.logger.debug(`Using <project>:<branch>: "${this.project}"/"${this.branch}"`);
|
||||
this.logger.info('ctor finished');
|
||||
};
|
||||
|
||||
JobLogsClient.prototype = Object.create(APIClient.prototype);
|
||||
|
||||
// This method could be optimized - it could make a log of requests
|
||||
JobLogsClient.prototype.fork = function(forkName) {
|
||||
var jobIds = this._modifiedJobs,
|
||||
deferred = Q.defer(),
|
||||
url = [
|
||||
this.url,
|
||||
'migrate',
|
||||
encodeURIComponent(this.project),
|
||||
encodeURIComponent(this.branch),
|
||||
encodeURIComponent(forkName)
|
||||
].join('/'),
|
||||
req = superagent.post(url);
|
||||
|
||||
this.logger.info(`migrating ${jobIds.length} jobs from ${this.branch} to ${forkName} in ${this.project}`);
|
||||
if (this.token) {
|
||||
req.set('Authorization', 'Bearer ' + this.token);
|
||||
}
|
||||
|
||||
req.send({jobs: jobIds})
|
||||
.end((err, res) => {
|
||||
if (err || res.status > 399) {
|
||||
return deferred.reject(err || res.status);
|
||||
}
|
||||
|
||||
return deferred.resolve(res);
|
||||
});
|
||||
|
||||
this.branch = forkName;
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
JobLogsClient.prototype.getUrl = function(jobId) {
|
||||
return [
|
||||
this.url,
|
||||
encodeURIComponent(this.project),
|
||||
encodeURIComponent(this.branch),
|
||||
encodeURIComponent(jobId)
|
||||
].join('/');
|
||||
};
|
||||
|
||||
JobLogsClient.prototype.appendTo = function(jobId, text) {
|
||||
this._modifiedJobs.push(jobId);
|
||||
this.logger.info(`Appending logs to ${jobId}`);
|
||||
return this._request('patch', jobId, {patch: text});
|
||||
};
|
||||
|
||||
JobLogsClient.prototype.getLog = function(jobId) {
|
||||
this.logger.info(`Getting logs for ${jobId}`);
|
||||
return this._request('get', jobId)
|
||||
.then(res => res.text);
|
||||
};
|
||||
|
||||
JobLogsClient.prototype.deleteLog = function(jobId) {
|
||||
this.logger.info(`Deleting logs for ${jobId}`);
|
||||
return this._request('delete', jobId);
|
||||
};
|
||||
|
||||
return JobLogsClient;
|
||||
});
|
||||
@@ -0,0 +1,60 @@
|
||||
/* globals define */
|
||||
define([
|
||||
'./APIClient'
|
||||
], function(
|
||||
APIClient
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
var JobOriginClient = function(params) {
|
||||
this.relativeUrl = '/job/origins/';
|
||||
this.logger = params.logger.fork('JobOriginClient');
|
||||
APIClient.call(this, params);
|
||||
};
|
||||
|
||||
JobOriginClient.prototype = Object.create(APIClient.prototype);
|
||||
|
||||
// - Record the origin
|
||||
// - Look up the origin
|
||||
// - Delete record
|
||||
JobOriginClient.prototype.getUrl = function(hash) {
|
||||
return this.url + hash;
|
||||
};
|
||||
|
||||
JobOriginClient.prototype.record = function(hash, info) {
|
||||
var jobInfo = {
|
||||
hash: hash,
|
||||
nodeId: info.nodeId,
|
||||
job: info.job,
|
||||
project: info.project || this.project,
|
||||
branch: info.branch || this.branch,
|
||||
execution: info.execution
|
||||
};
|
||||
|
||||
return this._request('post', hash, jobInfo)
|
||||
.catch(err => {
|
||||
throw err.text || err;
|
||||
});
|
||||
};
|
||||
|
||||
JobOriginClient.prototype.getOrigin = function(hash) {
|
||||
return this._request('get', hash)
|
||||
.then(res => JSON.parse(res.text))
|
||||
.catch(res => {
|
||||
if (res.status && res.status === 404) {
|
||||
return null;
|
||||
}
|
||||
throw res;
|
||||
});
|
||||
};
|
||||
|
||||
JobOriginClient.prototype.fork = function(hash, forkName) {
|
||||
return this._request('patch', hash, {branch: forkName});
|
||||
};
|
||||
|
||||
JobOriginClient.prototype.deleteRecord = function(hash) {
|
||||
return this._request('delete', hash);
|
||||
};
|
||||
|
||||
return JobOriginClient;
|
||||
});
|
||||
@@ -20,13 +20,13 @@ define([
|
||||
var output = cntrs
|
||||
.find(cntr => {
|
||||
var metaNode = this.core.getMetaType(cntr),
|
||||
metaName = this.core.getAttribute(metaNode, 'name');
|
||||
metaName = this.getAttribute(metaNode, 'name');
|
||||
return metaName === 'Outputs';
|
||||
});
|
||||
return this.core.loadChildren(output);
|
||||
})
|
||||
.then(dataNodes => {
|
||||
hash = this.core.getAttribute(dataNodes[0], 'data');
|
||||
hash = this.getAttribute(dataNodes[0], 'data');
|
||||
return this.getOutputs(node);
|
||||
})
|
||||
.then(outputTuples => {
|
||||
@@ -48,7 +48,7 @@ define([
|
||||
var hash,
|
||||
typeId = this.core.getPointerPath(node, 'type'),
|
||||
type,
|
||||
artifactName = this.core.getAttribute(node, 'artifactName');
|
||||
artifactName = this.getAttribute(node, 'artifactName');
|
||||
|
||||
return this.core.loadByPath(this.rootNode, typeId)
|
||||
.then(_type => {
|
||||
@@ -58,25 +58,20 @@ define([
|
||||
.then(saveDir => this.core.loadChildren(saveDir))
|
||||
.then(artifacts => {
|
||||
return artifacts.find(artifact =>
|
||||
this.core.getAttribute(artifact, 'name') === artifactName &&
|
||||
this.getAttribute(artifact, 'name') === artifactName &&
|
||||
this.isMetaTypeOf(artifact, type));
|
||||
})
|
||||
.then(matchingArtifact => {
|
||||
hash = matchingArtifact && this.core.getAttribute(matchingArtifact, 'data');
|
||||
hash = matchingArtifact && this.getAttribute(matchingArtifact, 'data');
|
||||
// If no hash, just continue (the subsequent ops will receive 'nil')
|
||||
if (!hash) {
|
||||
return this.onOperationComplete(node);
|
||||
} else {
|
||||
return this.getOutputs(node)
|
||||
.then(outputPairs => {
|
||||
var outputs = outputPairs.map(pair => pair[2]),
|
||||
paths;
|
||||
|
||||
paths = outputs.map(output => this.core.getPath(output));
|
||||
var outputs = outputPairs.map(pair => pair[2]);
|
||||
// Get the 'data' hash and store it in the output data ports
|
||||
this.logger.info(`Loading blob data (${hash}) to ${paths.map(p => `"${p}"`)}`);
|
||||
|
||||
outputs.forEach(output => this.core.setAttribute(output, 'data', hash));
|
||||
outputs.forEach(output => this.setAttribute(output, 'data', hash));
|
||||
|
||||
this.onOperationComplete(node);
|
||||
});
|
||||
@@ -99,7 +94,7 @@ define([
|
||||
|
||||
if (containers.length > 1) {
|
||||
saveDir = containers.find(c =>
|
||||
this.core.getAttribute(c, 'name').toLowerCase().indexOf('artifacts') > -1
|
||||
this.getAttribute(c, 'name').toLowerCase().indexOf('artifacts') > -1
|
||||
) || containers[0];
|
||||
}
|
||||
|
||||
@@ -121,8 +116,8 @@ define([
|
||||
.then(artifacts => {
|
||||
currNameHashPairs = artifacts
|
||||
.map(node => [
|
||||
this.core.getAttribute(node, 'name'),
|
||||
this.core.getAttribute(node, 'data')
|
||||
this.getAttribute(node, 'name'),
|
||||
this.getAttribute(node, 'data')
|
||||
]);
|
||||
return this.getInputs(node);
|
||||
})
|
||||
@@ -142,9 +137,9 @@ define([
|
||||
|
||||
// Remove nodes that already exist
|
||||
dataNodes = allDataNodes.filter(dataNode => {
|
||||
var hash = this.core.getAttribute(dataNode, 'data'),
|
||||
var hash = this.getAttribute(dataNode, 'data'),
|
||||
name = this.core.getOwnAttribute(node, 'saveName') ||
|
||||
this.core.getAttribute(dataNode, 'name');
|
||||
this.getAttribute(dataNode, 'name');
|
||||
|
||||
return !(currNameHashPairs
|
||||
.find(pair => pair[0] === name && pair[1] === hash));
|
||||
@@ -156,10 +151,10 @@ define([
|
||||
newName = this.core.getOwnAttribute(node, 'saveName');
|
||||
if (newName) {
|
||||
newNodes.forEach(node =>
|
||||
this.core.setAttribute(node, 'name', newName)
|
||||
this.setAttribute(node, 'name', newName)
|
||||
);
|
||||
}
|
||||
var hashes = dataNodes.map(n => this.core.getAttribute(n, 'data'));
|
||||
var hashes = dataNodes.map(n => this.getAttribute(n, 'data'));
|
||||
this.logger.info(`saving hashes: ${hashes.map(h => `"${h}"`)}`);
|
||||
} else if (allDataNodes.length === 0) {
|
||||
this.logger.warn('No data nodes found!');
|
||||
|
||||
Arquivo binário não exibido.
|
Antes Largura: | Altura: | Tamanho: 1.1 KiB Depois Largura: | Altura: | Tamanho: 2.0 KiB |
Arquivo binário não exibido.
|
Antes Largura: | Altura: | Tamanho: 3.1 KiB Depois Largura: | Altura: | Tamanho: 3.3 KiB |
+39
-4
@@ -1,7 +1,13 @@
|
||||
/* globals define*/
|
||||
define([
|
||||
], function(
|
||||
) {
|
||||
(function(root, factory){
|
||||
if(typeof define === 'function' && define.amd) {
|
||||
define([], function(){
|
||||
return (root.utils = factory());
|
||||
});
|
||||
} else if(typeof module === 'object' && module.exports) {
|
||||
module.exports = (root.utils = factory());
|
||||
}
|
||||
}(this, function() {
|
||||
var isBoolean = txt => {
|
||||
return typeof txt === 'boolean' || (txt === 'false' || txt === 'true');
|
||||
};
|
||||
@@ -51,8 +57,37 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
// Resolving stdout
|
||||
var resolveCarriageReturns = function(text) {
|
||||
// resolve \r
|
||||
var lines,
|
||||
chars,
|
||||
result,
|
||||
i = 0;
|
||||
|
||||
text = text.replace(/\u0000/g, '');
|
||||
lines = text.split('\n');
|
||||
for (var l = lines.length-1; l >= 0; l--) {
|
||||
i = 0;
|
||||
chars = lines[l].split('');
|
||||
result = [];
|
||||
|
||||
for (var c = 0; c < chars.length; c++) {
|
||||
if (chars[c] === '\r') {
|
||||
i = 0;
|
||||
}
|
||||
result[i] = chars[c];
|
||||
i++;
|
||||
}
|
||||
lines[l] = result.join('');
|
||||
}
|
||||
return lines;
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
getSetterSchema: getSetterSchema,
|
||||
resolveCarriageReturns: resolveCarriageReturns,
|
||||
abbr: abbr
|
||||
};
|
||||
});
|
||||
}));
|
||||
|
||||
@@ -38,6 +38,14 @@ define([
|
||||
context.managerConfig.namespace = 'pipeline';
|
||||
context.managerConfig.activeNode = node.getId();
|
||||
method = opts.useSecondary ? 'runBrowserPlugin' : 'runServerPlugin';
|
||||
|
||||
if (method === 'runServerPlugin' &&
|
||||
this.client.getBranchStatus() !== this.client.CONSTANTS.BRANCH_STATUS.SYNC) {
|
||||
|
||||
Materialize.toast('Cannot execute operations when client is out-of-sync', 2000);
|
||||
return;
|
||||
}
|
||||
|
||||
this.client[method](pluginId, context, (err, result) => {
|
||||
var msg = err ? `${name} failed!` : `${name} executed successfully!`,
|
||||
duration = err ? 4000 : 2000;
|
||||
|
||||
Diferenças do arquivo suprimidas por serem muito extensas
Carregar Diff
@@ -1,6 +1,13 @@
|
||||
-- Instantiate the deepforge object
|
||||
deepforge = {}
|
||||
|
||||
function deepforge.initialize()
|
||||
require 'nn'
|
||||
require 'rnn'
|
||||
require './classes/init'
|
||||
require './custom-layers'
|
||||
end
|
||||
|
||||
function deepforge.id()
|
||||
if __deepforge_id == nil then
|
||||
__deepforge_id = 0
|
||||
@@ -16,7 +23,7 @@ function deepforge._cmd(...)
|
||||
for i=1,n do
|
||||
cmd = cmd .. ' ' .. tostring(arg[i])
|
||||
end
|
||||
print(cmd)
|
||||
print(cmd .. ' ') -- guarantee ends w/ space
|
||||
end
|
||||
|
||||
-- Graph support
|
||||
@@ -46,7 +53,7 @@ function Graph:line(name, opts)
|
||||
end
|
||||
|
||||
-- Image support
|
||||
function deepforge.image(name, tensor)
|
||||
local function saveImage(name, tensor)
|
||||
require 'image'
|
||||
require 'paths'
|
||||
|
||||
@@ -59,7 +66,32 @@ function deepforge.image(name, tensor)
|
||||
end
|
||||
|
||||
image.save(path, tensor)
|
||||
deepforge._cmd("<%= IMAGE %>", name)
|
||||
end
|
||||
|
||||
function deepforge.image(name, tensor)
|
||||
saveImage(name, tensor)
|
||||
deepforge._cmd("<%= IMAGE.BASIC %>", deepforge.id(), name)
|
||||
end
|
||||
|
||||
Image = torch.class('deepforge.Image')
|
||||
function Image:__init(name, tensor)
|
||||
self.id = deepforge.id()
|
||||
self.name = name
|
||||
|
||||
if tensor ~= nil then
|
||||
saveImage(name, tensor)
|
||||
deepforge._cmd('<%= IMAGE.CREATE %>', self.id, self.name)
|
||||
end
|
||||
end
|
||||
|
||||
function Image:update(tensor)
|
||||
saveImage(self.name, tensor)
|
||||
deepforge._cmd('<%= IMAGE.UPDATE %>', self.id, self.name)
|
||||
end
|
||||
|
||||
function Image:title(name)
|
||||
self.name = name
|
||||
deepforge._cmd('<%= IMAGE.NAME %>', self.id, self.name)
|
||||
end
|
||||
|
||||
return deepforge
|
||||
|
||||
@@ -1,15 +1,12 @@
|
||||
-- load custom layers
|
||||
require './custom-layers'
|
||||
|
||||
-- load custom class definitions
|
||||
require './classes'
|
||||
-- load custom layers and classes
|
||||
deepforge.initialize()
|
||||
|
||||
-- input data<% inputs.forEach(function(pair) { var input = pair[0], isNil = pair[1];%>
|
||||
<%= isNil ? 'local ' : ''%><%= input %> = <% if (isNil) { %>nil<% } else { %>require './inputs/<%= input %>'<%}}); %>
|
||||
local <%= input %> = <% if (isNil) { %>nil<% } else { %>require './inputs/<%= input %>'<%}}); %>
|
||||
|
||||
-- load references<% pointers.forEach(function(pair) { var pointer = pair[0], isNil = pair[1];%>
|
||||
<%= isNil ? 'local ' : ''%><%= pointer %> = <% if (isNil) { %>nil<% } else { %>require './pointers/<%= pointer %>'<%}}); %>
|
||||
attributes = require './attributes'
|
||||
local <%= pointer %> = <% if (isNil) { %>nil<% } else { %>require './pointers/<%= pointer %>'<%}}); %>
|
||||
local attributes = require './attributes'
|
||||
|
||||
-- main operation code for <%= name %>
|
||||
<%= code %>
|
||||
|
||||
@@ -12,7 +12,7 @@ var spawn = require('child_process').spawn,
|
||||
|
||||
// Get the BlobClient...
|
||||
var COMMAND_PREFIX = '<%= START_CMD %>',
|
||||
IMAGE = '<%= IMAGE %>',
|
||||
IMAGE = '<%= IMAGE.PREFIX %>',
|
||||
requirejs = require('webgme').requirejs,
|
||||
remainingImageCount = 0,
|
||||
exitCode = null;
|
||||
@@ -80,7 +80,7 @@ requirejs([
|
||||
|
||||
var uploadImage = function(line) {
|
||||
var args = line.split(/\s+/),
|
||||
name = args.slice(2).join(' ').replace(/\s+$/, ''),
|
||||
name = args.slice(3).join(' ').replace(/\s+$/, ''),
|
||||
filename = 'metadata/' + name + '.png';
|
||||
|
||||
// Upload the image from metadata/
|
||||
|
||||
@@ -34,6 +34,11 @@ define([
|
||||
this.pluginMetadata = pluginMetadata;
|
||||
|
||||
this._currentSave = Q();
|
||||
this.changes = {};
|
||||
this.currentChanges = {}; // read-only changes being applied
|
||||
this.creations = {};
|
||||
this.deletions = [];
|
||||
this.createIdToMetadataId = {};
|
||||
this.initRun();
|
||||
};
|
||||
|
||||
@@ -101,7 +106,7 @@ define([
|
||||
// If starting with a pipeline, we will create an Execution first
|
||||
startPromise = this.createExecution(this.activeNode)
|
||||
.then(execNode => {
|
||||
this.logger.debug(`Finished creating execution "${this.core.getAttribute(execNode, 'name')}"`);
|
||||
this.logger.debug(`Finished creating execution "${this.getAttribute(execNode, 'name')}"`);
|
||||
this.activeNode = execNode;
|
||||
});
|
||||
} else if (this.core.isTypeOf(this.activeNode, this.META.Execution)) {
|
||||
@@ -120,7 +125,7 @@ define([
|
||||
var children = subtree
|
||||
.filter(n => this.core.getParent(n) === this.activeNode);
|
||||
|
||||
this.pipelineName = this.core.getAttribute(this.activeNode, 'name');
|
||||
this.pipelineName = this.getAttribute(this.activeNode, 'name');
|
||||
this.logger.debug(`Loaded subtree of ${this.pipelineName}. About to build cache`);
|
||||
this.buildCache(subtree);
|
||||
this.logger.debug('Parsing execution for job inter-dependencies');
|
||||
@@ -139,11 +144,13 @@ define([
|
||||
// before continuing
|
||||
this._currentSave = this._currentSave
|
||||
.then(() => this.updateForkName(this.pipelineName))
|
||||
.then(() => this.applyModelChanges())
|
||||
.then(() => CreateExecution.prototype.save.call(this, msg))
|
||||
.then(result => {
|
||||
var msg;
|
||||
if (result.status === STORAGE_CONSTANTS.FORKED) {
|
||||
this.currentForkName = result.forkName;
|
||||
this.logManager.fork(result.forkName);
|
||||
msg = `"${this.pipelineName}" execution has forked to "${result.forkName}"`;
|
||||
this.sendNotification(msg);
|
||||
} else if (result.status === STORAGE_CONSTANTS.MERGED) {
|
||||
@@ -173,6 +180,10 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.isExecutionCanceled = function () {
|
||||
return this.getAttribute(this.activeNode, 'status') === 'canceled';
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.isInputData = function (node) {
|
||||
var prnt = this.core.getParent(node);
|
||||
return this.core.isTypeOf(prnt, this.META.Inputs);
|
||||
@@ -192,14 +203,14 @@ define([
|
||||
nodes.filter(node => this.core.isTypeOf(node, this.META.Job))
|
||||
.forEach(node => {
|
||||
this.recordOldMetadata(node);
|
||||
this.core.setAttribute(node, 'status', 'pending');
|
||||
this.setAttribute(node, 'status', 'pending');
|
||||
});
|
||||
|
||||
// Set the status of the execution to 'running'
|
||||
this.core.setAttribute(this.activeNode, 'status', 'running');
|
||||
this.setAttribute(this.activeNode, 'status', 'running');
|
||||
this.logger.info('Setting all jobs status to "pending"');
|
||||
this.logger.debug(`Making a commit from ${this.currentHash}`);
|
||||
this.core.setAttribute(this.activeNode, 'startTime', Date.now());
|
||||
this.setAttribute(this.activeNode, 'startTime', Date.now());
|
||||
this.core.delAttribute(this.activeNode, 'endTime');
|
||||
return this.save(`Initializing ${this.pipelineName} for execution`);
|
||||
};
|
||||
@@ -291,24 +302,24 @@ define([
|
||||
ExecutePipeline.prototype.onOperationFail = function(node, err) {
|
||||
var job = this.core.getParent(node),
|
||||
id = this.core.getPath(node),
|
||||
name = this.core.getAttribute(node, 'name');
|
||||
name = this.getAttribute(node, 'name');
|
||||
|
||||
this.logger.debug(`Operation ${name} (${id}) failed: ${err}`);
|
||||
this.core.setAttribute(job, 'status', 'fail');
|
||||
this.setAttribute(job, 'status', 'fail');
|
||||
this.clearOldMetadata(job);
|
||||
this.onPipelineComplete(err);
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.onOperationCanceled = function(op) {
|
||||
var job = this.core.getParent(op);
|
||||
this.core.setAttribute(job, 'status', 'canceled');
|
||||
this.setAttribute(job, 'status', 'canceled');
|
||||
this.runningJobs--;
|
||||
this.logger.debug(`${this.core.getAttribute(job, 'name')} has been canceled`);
|
||||
this.logger.debug(`${this.getAttribute(job, 'name')} has been canceled`);
|
||||
this.onPipelineComplete();
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.onPipelineComplete = function(err) {
|
||||
var name = this.core.getAttribute(this.activeNode, 'name'),
|
||||
var name = this.getAttribute(this.activeNode, 'name'),
|
||||
msg = `"${this.pipelineName}" `;
|
||||
|
||||
if (err) {
|
||||
@@ -342,8 +353,8 @@ define([
|
||||
if (!isDeleted) {
|
||||
|
||||
this.logger.debug(`Pipeline "${name}" complete!`);
|
||||
this.core.setAttribute(this.activeNode, 'endTime', Date.now());
|
||||
this.core.setAttribute(this.activeNode, 'status',
|
||||
this.setAttribute(this.activeNode, 'endTime', Date.now());
|
||||
this.setAttribute(this.activeNode, 'status',
|
||||
(this.pipelineError ? 'failed' :
|
||||
(this.canceled ? 'canceled' : 'success')
|
||||
)
|
||||
@@ -420,7 +431,7 @@ define([
|
||||
};
|
||||
|
||||
ExecutePipeline.prototype.onOperationComplete = function (opNode) {
|
||||
var name = this.core.getAttribute(opNode, 'name'),
|
||||
var name = this.getAttribute(opNode, 'name'),
|
||||
nextPortIds = this.getOperationOutputIds(opNode),
|
||||
jNode = this.core.getParent(opNode),
|
||||
resultPorts,
|
||||
@@ -430,7 +441,7 @@ define([
|
||||
// Set the operation to 'success'!
|
||||
this.clearOldMetadata(jNode);
|
||||
this.runningJobs--;
|
||||
this.core.setAttribute(jNode, 'status', 'success');
|
||||
this.setAttribute(jNode, 'status', 'success');
|
||||
this.logger.info(`Setting ${jobId} status to "success"`);
|
||||
this.logger.info(`There are now ${this.runningJobs} running jobs`);
|
||||
this.logger.debug(`Making a commit from ${this.currentHash}`);
|
||||
@@ -449,11 +460,11 @@ define([
|
||||
.forEach(pair => { // [ resultPort, nextPort ]
|
||||
var result = pair[0],
|
||||
next = pair[1],
|
||||
hash = this.core.getAttribute(result, 'data');
|
||||
hash = this.getAttribute(result, 'data');
|
||||
|
||||
this.logger.info(`forwarding data (${hash}) from ${this.core.getPath(result)} ` +
|
||||
`to ${this.core.getPath(next)}`);
|
||||
this.core.setAttribute(next, 'data', hash);
|
||||
this.setAttribute(next, 'data', hash);
|
||||
this.logger.info(`Setting ${jobId} data to ${hash}`);
|
||||
});
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ define([
|
||||
this.addCustomLayersToMeta();
|
||||
this.LayerDict = createLayerDict(this.core, this.META);
|
||||
this.uniqueId = 2;
|
||||
this.varnames = {};
|
||||
this.varnames = {net: true};
|
||||
return PluginBase.prototype.main.apply(this, arguments);
|
||||
};
|
||||
|
||||
@@ -247,17 +247,27 @@ define([
|
||||
base = layer[Constants.BASE],
|
||||
desc,
|
||||
fn,
|
||||
layerCode;
|
||||
layerCode,
|
||||
args,
|
||||
i;
|
||||
|
||||
this.logger.debug(`Creating arg string for ${layer.name}`);
|
||||
layerCode = '(' + this.LayerDict[layer.name].args
|
||||
.map(arg => this.getValue(arg.name, layer))
|
||||
.filter(GenerateArchitecture.isSet)
|
||||
args = this.LayerDict[layer.name].args
|
||||
.map(arg => this.getValue(arg.name, layer));
|
||||
|
||||
for (i = args.length; i--;) {
|
||||
if (GenerateArchitecture.isSet(args[i])) {
|
||||
break;
|
||||
}
|
||||
args.pop();
|
||||
}
|
||||
|
||||
layerCode = '(' + args.map(arg => GenerateArchitecture.isSet(arg) ? arg : 'nil')
|
||||
.join(', ') + ')';
|
||||
|
||||
// Add any setters
|
||||
// For each setter, check if it has been changed (and needs to be set)
|
||||
for (var i = setterNames.length; i--;) {
|
||||
for (i = setterNames.length; i--;) {
|
||||
desc = setters[setterNames[i]];
|
||||
if (desc.setterType === 'const') {
|
||||
// if the value is not the default, add the given fn
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
var path = require('path'),
|
||||
Q = require('q'),
|
||||
fs = require('fs'),
|
||||
exists = require('exists-file'),
|
||||
utils = require('../../common/utils'),
|
||||
NO_LOG_FOUND = '';
|
||||
|
||||
var JobLogManager = function(logger, config) {
|
||||
this.rootDir = path.join(config.blob.fsDir, 'log-storage');
|
||||
this.logger = logger.fork('JobLogManager');
|
||||
this._onCopyFinished = {};
|
||||
};
|
||||
|
||||
JobLogManager.prototype._getFilePath = function(jInfo) {
|
||||
this.logger.debug(`getting file path for ${jInfo.job} in ${jInfo.project} on ${jInfo.branch}`);
|
||||
var jobId = jInfo.job.replace(/\//g, '_'),
|
||||
filename = `${jobId}.txt`;
|
||||
|
||||
return path.join(this.rootDir, jInfo.project, jInfo.branch, filename);
|
||||
};
|
||||
|
||||
JobLogManager.prototype.exists = function(jobInfo) {
|
||||
var filename = this._getFilePath(jobInfo);
|
||||
return Q.nfcall(exists, filename);
|
||||
};
|
||||
|
||||
JobLogManager.prototype.mkdirIfNeeded = function(dir) {
|
||||
return Q.nfcall(exists, dir).then(exist => {
|
||||
if (!exist) {
|
||||
this.logger.debug('making dir:', dir);
|
||||
return Q.nfcall(fs.mkdir, dir)
|
||||
.catch(() => this.logger.debug(`dir already created: ${dir}`));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
JobLogManager.prototype._copyFile = function(src, dst) {
|
||||
return Q.nfcall(exists, src).then(exists => {
|
||||
if (!exists) {
|
||||
this.logger.warn(`Cannot copy file from ${src}. File doesn't exist!`);
|
||||
return;
|
||||
}
|
||||
|
||||
return this.mkdirIfNeeded(path.dirname(dst)).then(() => {
|
||||
var deferred = Q.defer(),
|
||||
stream = fs.createReadStream(src).pipe(fs.createWriteStream(dst));
|
||||
|
||||
stream.on('error', deferred.reject);
|
||||
stream.on('finish', deferred.resolve);
|
||||
|
||||
return deferred.promise;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
// Copy one branch info to the next
|
||||
// Could optimize this to symlink until data appended...
|
||||
JobLogManager.prototype.migrate = function(migrationInfo, jobIds) {
|
||||
// Recursively copy the srcBranch dir to the dstBranch dir
|
||||
// Should probably use streams...
|
||||
// Need to block appends to the given files so they are not written
|
||||
// to until they have finished copying...
|
||||
// TODO
|
||||
var jobs,
|
||||
src,
|
||||
dst,
|
||||
i;
|
||||
|
||||
for (i = jobIds.length; i--;) {
|
||||
this._onCopyFinished[jobIds[i]] = [];
|
||||
}
|
||||
|
||||
// Copy the job files and evaluate each of the finish functions
|
||||
this.logger.debug('migrating from ' + migrationInfo.srcBranch + ' to '+ migrationInfo.dstBranch);
|
||||
return Q.all(jobIds.map(jobId => {
|
||||
src = this._getFilePath({
|
||||
project: migrationInfo.project,
|
||||
branch: migrationInfo.srcBranch,
|
||||
job: jobId
|
||||
});
|
||||
dst = this._getFilePath({
|
||||
project: migrationInfo.project,
|
||||
branch: migrationInfo.dstBranch,
|
||||
job: jobId
|
||||
});
|
||||
return this._copyFile(src, dst).then(() => {
|
||||
jobs = this._onCopyFinished[jobId];
|
||||
for (var j = jobs.length; j--;) {
|
||||
jobs[j]();
|
||||
}
|
||||
});
|
||||
}));
|
||||
};
|
||||
|
||||
JobLogManager.prototype._appendTo = function(filename, logs) {
|
||||
return Q.nfcall(exists, filename).then(exists => {
|
||||
var promise = Q().then(() => '');
|
||||
if (exists) {
|
||||
promise = Q.nfcall(fs.readFile, filename, 'utf8');
|
||||
}
|
||||
|
||||
return promise.then(content => {
|
||||
// This could be optimized to not re-read/write the whole file each time...
|
||||
var lines = utils.resolveCarriageReturns(content + logs);
|
||||
return Q.nfcall(fs.writeFile, filename, lines.join('\n'));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
JobLogManager.prototype.appendTo = function(jobInfo, logs) {
|
||||
var filename = this._getFilePath(jobInfo),
|
||||
branchDirname = path.dirname(filename),
|
||||
projDirname = path.dirname(branchDirname);
|
||||
|
||||
this.logger.debug(`Appending content to ${filename}`);
|
||||
// Make directory if needed
|
||||
return this.mkdirIfNeeded(this.rootDir)
|
||||
.then(() => this.mkdirIfNeeded(projDirname))
|
||||
.then(() => this.mkdirIfNeeded(branchDirname))
|
||||
.then(() => this._appendTo(filename, logs));
|
||||
};
|
||||
|
||||
JobLogManager.prototype.getLog = function(jobInfo) {
|
||||
var filename = this._getFilePath(jobInfo);
|
||||
|
||||
this.logger.info(`Getting log content from ${filename}`);
|
||||
return this.exists(jobInfo)
|
||||
.then(exists => {
|
||||
if (exists) {
|
||||
return Q.nfcall(fs.readFile, filename);
|
||||
}
|
||||
return NO_LOG_FOUND;
|
||||
});
|
||||
};
|
||||
|
||||
JobLogManager.prototype.delete = function(jobInfo) {
|
||||
var filename = this._getFilePath(jobInfo);
|
||||
|
||||
return this.exists(jobInfo)
|
||||
.then(exists => {
|
||||
if (exists) {
|
||||
this.logger.debug(`Removing file ${filename}`);
|
||||
return Q.nfcall(fs.unlink, filename);
|
||||
}
|
||||
this.logger.debug(`${filename} doesn't exist. No need to delete...`);
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = JobLogManager;
|
||||
@@ -0,0 +1,93 @@
|
||||
/*jshint node:true*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var express = require('express'),
|
||||
JobLogManager = require('./JobLogManager'),
|
||||
router = express.Router();
|
||||
|
||||
/**
|
||||
* Called when the server is created but before it starts to listening to incoming requests.
|
||||
* N.B. gmeAuth, safeStorage and workerManager are not ready to use until the start function is called.
|
||||
* (However inside an incoming request they are all ensured to have been initialized.)
|
||||
*
|
||||
* @param {object} middlewareOpts - Passed by the webgme server.
|
||||
* @param {GmeConfig} middlewareOpts.gmeConfig - GME config parameters.
|
||||
* @param {GmeLogger} middlewareOpts.logger - logger
|
||||
* @param {function} middlewareOpts.ensureAuthenticated - Ensures the user is authenticated.
|
||||
* @param {function} middlewareOpts.getUserId - If authenticated retrieves the userId from the request.
|
||||
* @param {object} middlewareOpts.gmeAuth - Authorization module.
|
||||
* @param {object} middlewareOpts.safeStorage - Accesses the storage and emits events (PROJECT_CREATED, COMMIT..).
|
||||
* @param {object} middlewareOpts.workerManager - Spawns and keeps track of "worker" sub-processes.
|
||||
*/
|
||||
function initialize(middlewareOpts) {
|
||||
var logger = middlewareOpts.logger.fork('JobLogsAPI'),
|
||||
ensureAuthenticated = middlewareOpts.ensureAuthenticated,
|
||||
gmeConfig = middlewareOpts.gmeConfig,
|
||||
logManager = new JobLogManager(logger, gmeConfig);
|
||||
|
||||
logger.debug('initializing ...');
|
||||
|
||||
// Ensure authenticated can be used only after this rule.
|
||||
router.use('*', function (req, res, next) {
|
||||
// This header ensures that any failures with authentication won't redirect.
|
||||
res.setHeader('X-WebGME-Media-Type', 'webgme.v1');
|
||||
next();
|
||||
});
|
||||
|
||||
// Use ensureAuthenticated if the routes require authentication. (Can be set explicitly for each route.)
|
||||
router.use('*', ensureAuthenticated);
|
||||
|
||||
router.get('/:project/:branch/:job', function (req, res/*, next*/) {
|
||||
// Retrieve the job logs for the given job
|
||||
logManager.getLog(req.params).then(log => {
|
||||
res.set('Content-Type', 'text/plain');
|
||||
res.send(log);
|
||||
});
|
||||
});
|
||||
|
||||
router.patch('/:project/:branch/:job', function (req, res/*, next*/) {
|
||||
var logs = req.body.patch;
|
||||
logger.info(`Received append request for ${req.params.job} in ${req.params.project}`);
|
||||
logManager.appendTo(req.params, logs)
|
||||
.then(() => res.send('Append successful'))
|
||||
.catch(err => logger.error(`Append failed: ${err}`));
|
||||
});
|
||||
|
||||
router.delete('/:project/:branch/:job', function (req, res/*, next*/) {
|
||||
logManager.delete(req.params).then(() => res.send('delete successful'));
|
||||
});
|
||||
|
||||
router.post('/migrate/:project/:srcBranch/:dstBranch', function (req, res/*, next*/) {
|
||||
var jobs = req.body.jobs;
|
||||
logManager.migrate(req.params, jobs)
|
||||
.then(() => res.send('migration successful'))
|
||||
.fail(err => logger.error(err));
|
||||
});
|
||||
|
||||
logger.debug('ready');
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before the server starts listening.
|
||||
* @param {function} callback
|
||||
*/
|
||||
function start(callback) {
|
||||
callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the server stopped listening.
|
||||
* @param {function} callback
|
||||
*/
|
||||
function stop(callback) {
|
||||
callback();
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
initialize: initialize,
|
||||
router: router,
|
||||
start: start,
|
||||
stop: stop
|
||||
};
|
||||
@@ -0,0 +1,161 @@
|
||||
/*jshint node:true*/
|
||||
|
||||
/**
|
||||
* This is an API to record the executor job hash to originating project, execution and job
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
// This contains
|
||||
var express = require('express'),
|
||||
MONGO_COLLECTION = 'JobOrigins',
|
||||
Q = require('q'),
|
||||
router = express.Router(),
|
||||
mongodb = require('mongodb');
|
||||
|
||||
/**
|
||||
* Called when the server is created but before it starts to listening to incoming requests.
|
||||
* N.B. gmeAuth, safeStorage and workerManager are not ready to use until the start function is called.
|
||||
* (However inside an incoming request they are all ensured to have been initialized.)
|
||||
*
|
||||
* @param {object} middlewareOpts - Passed by the webgme server.
|
||||
* @param {GmeConfig} middlewareOpts.gmeConfig - GME config parameters.
|
||||
* @param {GmeLogger} middlewareOpts.logger - logger
|
||||
* @param {function} middlewareOpts.ensureAuthenticated - Ensures the user is authenticated.
|
||||
* @param {function} middlewareOpts.getUserId - If authenticated retrieves the userId from the request.
|
||||
* @param {object} middlewareOpts.gmeAuth - Authorization module.
|
||||
* @param {object} middlewareOpts.safeStorage - Accesses the storage and emits events (PROJECT_CREATED, COMMIT..).
|
||||
* @param {object} middlewareOpts.workerManager - Spawns and keeps track of "worker" sub-processes.
|
||||
*/
|
||||
// When testing, use in memory storage...
|
||||
function initialize(middlewareOpts) {
|
||||
var logger = middlewareOpts.logger.fork('JobOriginAPI'),
|
||||
gmeConfig = middlewareOpts.gmeConfig,
|
||||
ensureAuthenticated = middlewareOpts.ensureAuthenticated,
|
||||
REQUIRED_FIELDS = ['hash', 'project', 'execution', 'job', 'nodeId', 'branch'],
|
||||
mongo;
|
||||
|
||||
logger.debug('initializing ...');
|
||||
|
||||
// Ensure authenticated can be used only after this rule.
|
||||
router.use('*', function (req, res, next) {
|
||||
// This header ensures that any failures with authentication won't redirect.
|
||||
res.setHeader('X-WebGME-Media-Type', 'webgme.v1');
|
||||
next();
|
||||
});
|
||||
|
||||
// Use ensureAuthenticated if the routes require authentication. (Can be set explicitly for each route.)
|
||||
router.use('*', ensureAuthenticated);
|
||||
|
||||
// Connect to mongo...
|
||||
Q.nfcall(mongodb.MongoClient.connect, gmeConfig.mongo.uri, gmeConfig.mongo.options)
|
||||
.then(db => {
|
||||
mongo = db.collection(MONGO_COLLECTION);
|
||||
logger.debug('Connected to mongo!');
|
||||
})
|
||||
.catch(err => {
|
||||
logger.error(`Could not connect to mongo: ${err}`);
|
||||
throw err;
|
||||
});
|
||||
|
||||
router.get('/:jobHash', function (req, res/*, next*/) {
|
||||
var hash = req.params.jobHash,
|
||||
jobInfo = {};
|
||||
|
||||
mongo.findOne({hash: hash})
|
||||
.then(result => {
|
||||
if (result) {
|
||||
// Filter the result object
|
||||
for (var i = REQUIRED_FIELDS.length; i--;) {
|
||||
jobInfo[REQUIRED_FIELDS[i]] = result[REQUIRED_FIELDS[i]];
|
||||
}
|
||||
return res.json(jobInfo);
|
||||
}
|
||||
res.sendStatus(404);
|
||||
})
|
||||
.catch(err => {
|
||||
logger.error(`Storing job info failed: ${err}`);
|
||||
res.status(500).send(err);
|
||||
});
|
||||
});
|
||||
|
||||
router.post('/:jobHash', function (req, res/*, next*/) {
|
||||
var hash = req.params.jobHash,
|
||||
jobInfo = {
|
||||
hash: hash,
|
||||
project: req.body.project,
|
||||
execution: req.body.execution,
|
||||
branch: req.body.branch,
|
||||
job: req.body.job, // job name
|
||||
nodeId: req.body.nodeId
|
||||
};
|
||||
|
||||
// Check that none of the fields are undefined
|
||||
logger.debug(`Storing job info for ${hash}`);
|
||||
var fields = REQUIRED_FIELDS;
|
||||
for (var i = fields.length; i--;) {
|
||||
if (!jobInfo[fields[i]]) {
|
||||
return res.status(400).send(`Missing required field: ${fields[i]}`);
|
||||
}
|
||||
}
|
||||
|
||||
return mongo.insertOne(jobInfo)
|
||||
.then(() => res.sendStatus(201))
|
||||
.catch(err => {
|
||||
logger.error(`Storing job info failed: ${err}`);
|
||||
res.status(500).send(err.toString());
|
||||
});
|
||||
});
|
||||
|
||||
router.delete('/:jobHash', function (req, res/*, next*/) {
|
||||
var hash = req.params.jobHash;
|
||||
|
||||
mongo.findOneAndDelete({hash: hash})
|
||||
.then(() => res.sendStatus(204));
|
||||
});
|
||||
|
||||
// on fork
|
||||
router.patch('/:jobHash', function (req, res) {
|
||||
var hash = req.params.jobHash;
|
||||
|
||||
if (!req.body.branch) {
|
||||
return res.status(400).send('Missing "branch" field');
|
||||
}
|
||||
|
||||
return mongo.findOneAndUpdate({hash: hash}, {$set: {branch: req.body.branch}})
|
||||
.then(() => {
|
||||
logger.debug('Finished updateOne!');
|
||||
res.sendStatus(200);
|
||||
})
|
||||
.catch(err => {
|
||||
logger.error(`Job update failed: ${err}`);
|
||||
res.status(500).send(err);
|
||||
});
|
||||
});
|
||||
|
||||
logger.debug('ready');
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before the server starts listening.
|
||||
* @param {function} callback
|
||||
*/
|
||||
function start(callback) {
|
||||
callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after the server stopped listening.
|
||||
* @param {function} callback
|
||||
*/
|
||||
function stop(callback) {
|
||||
callback();
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
initialize: initialize,
|
||||
router: router,
|
||||
start: start,
|
||||
stop: stop
|
||||
};
|
||||
Arquivo binário não exibido.
Arquivo binário não exibido.
Arquivo binário não exibido.
Arquivo binário não exibido.
@@ -100,5 +100,11 @@
|
||||
"title": "ExecutionIndex",
|
||||
"panel": "panels/ExecutionIndex/ExecutionIndexPanel",
|
||||
"DEBUG_ONLY": false
|
||||
},
|
||||
{
|
||||
"id": "WorkerHeader",
|
||||
"title": "WorkerHeader",
|
||||
"panel": "panels/WorkerHeader/WorkerHeaderPanel",
|
||||
"DEBUG_ONLY": false
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
@@ -161,7 +161,9 @@ define([
|
||||
desc.abbr = this.getUniqAbbreviation(desc);
|
||||
|
||||
// Create a territory for this origin and update it!
|
||||
this._selfPatterns[desc.originId] = {children: 0};
|
||||
if (desc.originId) {
|
||||
this._selfPatterns[desc.originId] = {children: 0};
|
||||
}
|
||||
setTimeout(() => this._client.updateTerritory(this._territoryId, this._selfPatterns), 0);
|
||||
} else if (type === 'Line') {
|
||||
desc = this.getLineDesc(node);
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/* globals define */
|
||||
// A notification widget which filters out stdout update notifications
|
||||
define([
|
||||
'deepforge/Constants',
|
||||
'js/Widgets/Notification/NotificationWidget'
|
||||
], function(
|
||||
CONSTANTS,
|
||||
GmeNotificationWidget
|
||||
) {
|
||||
var NotificationWidget = function() {
|
||||
GmeNotificationWidget.apply(this, arguments);
|
||||
};
|
||||
|
||||
NotificationWidget.prototype = Object.create(GmeNotificationWidget.prototype);
|
||||
|
||||
NotificationWidget.prototype.isUserNotication = function(data) {
|
||||
return data.message.indexOf(CONSTANTS.STDOUT_UPDATE) === -1;
|
||||
};
|
||||
|
||||
NotificationWidget.prototype._refreshNotifications = function(eventData) {
|
||||
|
||||
if (this.isUserNotication(eventData)) {
|
||||
GmeNotificationWidget.prototype._refreshNotifications.call(this, eventData);
|
||||
}
|
||||
};
|
||||
|
||||
return NotificationWidget;
|
||||
});
|
||||
@@ -1,8 +1,5 @@
|
||||
/*globals define, _, WebGMEGlobal, $ */
|
||||
/*jshint browser: true*/
|
||||
/**
|
||||
* @author rkereskenyi / https://github.com/rkereskenyi
|
||||
*/
|
||||
|
||||
define([
|
||||
'js/PanelBase/PanelBase',
|
||||
@@ -10,13 +7,15 @@ define([
|
||||
'js/Widgets/BranchStatus/BranchStatusWidget',
|
||||
'js/Widgets/BranchSelector/BranchSelectorWidget',
|
||||
'js/Widgets/KeyboardManager/KeyboardManagerWidget',
|
||||
'js/Widgets/Notification/NotificationWidget'
|
||||
], function (PanelBase,
|
||||
NetworkStatusWidget,
|
||||
BranchStatusWidget,
|
||||
BranchSelectorWidget,
|
||||
KeyboardManagerWidget,
|
||||
NotificationWidget) {
|
||||
'./FilteredNotificationWidget'
|
||||
], function (
|
||||
PanelBase,
|
||||
NetworkStatusWidget,
|
||||
BranchStatusWidget,
|
||||
BranchSelectorWidget,
|
||||
KeyboardManagerWidget,
|
||||
NotificationWidget
|
||||
) {
|
||||
|
||||
'use strict';
|
||||
|
||||
|
||||
@@ -2,9 +2,18 @@
|
||||
/*jshint browser: true*/
|
||||
|
||||
// This is a read-only view of the 'stdout' attribute for a Job node
|
||||
// if the job is running, get the logs from the log-storage
|
||||
define([
|
||||
'q',
|
||||
'deepforge/api/JobLogsClient',
|
||||
'js/Constants',
|
||||
'deepforge/Constants',
|
||||
'panels/TextEditor/TextEditorControl'
|
||||
], function (
|
||||
Q,
|
||||
JobLogsClient,
|
||||
GME_CONSTANTS,
|
||||
CONSTANTS,
|
||||
TextEditorControl
|
||||
) {
|
||||
|
||||
@@ -19,11 +28,68 @@ define([
|
||||
|
||||
_.extend(LogViewerControl.prototype, TextEditorControl.prototype);
|
||||
|
||||
LogViewerControl.prototype.getFullDescriptor = function (id) {
|
||||
var desc = LogViewerControl.prototype._getObjectDescriptor.call(this, id);
|
||||
|
||||
return this._getRunningLogs(id).then(text => {
|
||||
// Use attribute or running log if none
|
||||
desc.text = desc.text || text;
|
||||
return desc;
|
||||
});
|
||||
};
|
||||
|
||||
LogViewerControl.prototype.getUpdatedJobId = function (msg) {
|
||||
// verify that it is the given notification type
|
||||
if (msg.indexOf(CONSTANTS.STDOUT_UPDATE) !== -1) {
|
||||
return msg.replace(/^[^\/]*\//, '');
|
||||
}
|
||||
};
|
||||
|
||||
LogViewerControl.prototype.selectedObjectChanged = function (id) {
|
||||
TextEditorControl.prototype.selectedObjectChanged.call(this, id);
|
||||
// Listen for notifications about updated logs
|
||||
this.removeNotificationHandler();
|
||||
this.notificationHandler = (sender, data) => {
|
||||
var nodeId = this.getUpdatedJobId(data.message);
|
||||
if (nodeId === id) {
|
||||
this._onUpdate(id);
|
||||
}
|
||||
};
|
||||
this._client.addEventListener(GME_CONSTANTS.CLIENT.NOTIFICATION, this.notificationHandler);
|
||||
};
|
||||
|
||||
LogViewerControl.prototype.removeNotificationHandler = function () {
|
||||
// Remove the notifications listener
|
||||
if (this.notificationHandler) {
|
||||
this._client.removeEventListener();
|
||||
this.notificationHandler = null;
|
||||
}
|
||||
};
|
||||
|
||||
LogViewerControl.prototype.destroy = function () {
|
||||
TextEditorControl.prototype.destroy.call(this);
|
||||
this.removeNotificationHandler();
|
||||
};
|
||||
|
||||
LogViewerControl.prototype._onLoad = function (id) {
|
||||
this.getFullDescriptor(id).then(desc => this._widget.addNode(desc));
|
||||
};
|
||||
|
||||
LogViewerControl.prototype._onUpdate = function (id) {
|
||||
if (id === this._currentNodeId) {
|
||||
TextEditorControl.prototype._onUpdate.call(this, id);
|
||||
this.getFullDescriptor(id).then(desc => this._widget.updateNode(desc));
|
||||
}
|
||||
};
|
||||
|
||||
LogViewerControl.prototype._getRunningLogs = function (id) {
|
||||
var logManager = new JobLogsClient({
|
||||
logger: this._logger,
|
||||
projectId: this._client.getActiveProjectId(),
|
||||
branchName: this._client.getActiveBranchName()
|
||||
});
|
||||
|
||||
return logManager.getLog(id);
|
||||
};
|
||||
|
||||
return LogViewerControl;
|
||||
});
|
||||
|
||||
@@ -33,12 +33,33 @@ define([
|
||||
this._widget.deletePipeline = id => {
|
||||
var node = this._client.getNode(id),
|
||||
name = node.getAttribute('name'),
|
||||
msg = `Deleting pipeline "${name}"`;
|
||||
msg = `Deleting pipeline "${name}"`,
|
||||
delTerritory = {},
|
||||
delUI,
|
||||
ids = [id];
|
||||
|
||||
// Change the current active object
|
||||
this._client.startTransaction(msg);
|
||||
this._client.delMoreNodes([id]);
|
||||
this._client.completeTransaction();
|
||||
// Delete all associated executions
|
||||
ids = node.getMemberIds('executions');
|
||||
for (var i = ids.length; i--;) {
|
||||
delTerritory[ids[i]] = {children: 0};
|
||||
}
|
||||
|
||||
delUI = this._client.addUI(this, events => {
|
||||
var ids = [id];
|
||||
|
||||
for (i = events.length; i--;) {
|
||||
if (events[i].eid && events[i].etype === CONSTANTS.TERRITORY_EVENT_LOAD) {
|
||||
ids.push(events[i].eid);
|
||||
}
|
||||
}
|
||||
|
||||
this._client.startTransaction(msg);
|
||||
this._client.delMoreNodes(ids);
|
||||
this._client.completeTransaction();
|
||||
|
||||
this._client.removeUI(delUI);
|
||||
});
|
||||
this._client.updateTerritory(delUI, delTerritory);
|
||||
};
|
||||
|
||||
this._widget.setName = (id, name) => {
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
/* globals define, WebGMEGlobal */
|
||||
define([
|
||||
'js/Dialogs/Projects/ProjectsDialog',
|
||||
'./WorkerDialog',
|
||||
'js/Panels/Header/ProjectNavigatorController'
|
||||
], function(
|
||||
ProjectsDialog,
|
||||
WorkerDialog,
|
||||
GMEProjectNavigatorController
|
||||
) {
|
||||
'use strict';
|
||||
var ProjectNavigatorController = function() {
|
||||
GMEProjectNavigatorController.apply(this, arguments);
|
||||
};
|
||||
|
||||
ProjectNavigatorController.prototype = Object.create(GMEProjectNavigatorController.prototype);
|
||||
|
||||
ProjectNavigatorController.prototype.initialize = function () {
|
||||
var self = this,
|
||||
newProject,
|
||||
manageProjects,
|
||||
manageWorkers;
|
||||
|
||||
|
||||
// initialize model structure for view
|
||||
self.$scope.navigator = {
|
||||
items: [],
|
||||
separator: true
|
||||
};
|
||||
|
||||
|
||||
manageProjects = function (/*data*/) {
|
||||
var pd = new ProjectsDialog(self.gmeClient);
|
||||
pd.show();
|
||||
};
|
||||
newProject = function (data) {
|
||||
var pd = new ProjectsDialog(self.gmeClient, true, data.newType);
|
||||
pd.show();
|
||||
};
|
||||
self.userId = WebGMEGlobal.userInfo._id;
|
||||
|
||||
manageWorkers = function() {
|
||||
// Create the worker dialog
|
||||
var pd = new WorkerDialog(self.logger);
|
||||
pd.show();
|
||||
};
|
||||
|
||||
// initialize root menu
|
||||
// projects id is mandatory
|
||||
if (self.config.disableProjectActions === false) {
|
||||
self.root.menu = [
|
||||
{
|
||||
id: 'top',
|
||||
items: [
|
||||
{
|
||||
id: 'manageProject',
|
||||
label: 'Manage projects ...',
|
||||
iconClass: 'glyphicon glyphicon-folder-open',
|
||||
action: manageProjects,
|
||||
actionData: {}
|
||||
},
|
||||
{
|
||||
id: 'newProject',
|
||||
label: 'New project ...',
|
||||
disabled: WebGMEGlobal.userInfo.canCreate !== true,
|
||||
iconClass: 'glyphicon glyphicon-plus',
|
||||
action: newProject,
|
||||
actionData: {newType: 'seed'}
|
||||
},
|
||||
{
|
||||
id: 'importProject',
|
||||
label: 'Import project ...',
|
||||
disabled: WebGMEGlobal.userInfo.canCreate !== true,
|
||||
iconClass: 'glyphicon glyphicon-import',
|
||||
action: newProject,
|
||||
actionData: {newType: 'import'}
|
||||
},
|
||||
{
|
||||
id: 'manageWorkers',
|
||||
label: 'View workers ...',
|
||||
iconClass: 'glyphicon glyphicon-cloud',
|
||||
action: manageWorkers
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
id: 'projects',
|
||||
label: 'Recent projects',
|
||||
totalItems: 20,
|
||||
items: [],
|
||||
showAllItems: manageProjects
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
self.initWithClient();
|
||||
|
||||
// only root is selected by default
|
||||
self.$scope.navigator = {
|
||||
items: self.config.disableProjectActions ? [] : [self.root],
|
||||
separator: true
|
||||
};
|
||||
};
|
||||
|
||||
return ProjectNavigatorController;
|
||||
});
|
||||
@@ -0,0 +1,239 @@
|
||||
/* globals define, $ */
|
||||
define([
|
||||
'q',
|
||||
'superagent',
|
||||
'deepforge/viz/Utils',
|
||||
'deepforge/api/JobOriginClient',
|
||||
'text!./WorkerModal.html',
|
||||
'text!./WorkerTemplate.html.ejs',
|
||||
'text!./WorkerJobItem.html',
|
||||
'css!./WorkerModal.css'
|
||||
], function(
|
||||
Q,
|
||||
superagent,
|
||||
utils,
|
||||
JobOriginClient,
|
||||
WorkerHtml,
|
||||
WorkerTemplate,
|
||||
WorkerJobItem
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
var WORKER_ENDPOINT = '/rest/executor/worker',
|
||||
JOBS_ENDPOINT = '/rest/executor';
|
||||
|
||||
var WorkerDialog = function(logger) {
|
||||
this.workerDict = {};
|
||||
this.workers = {};
|
||||
this.runningWorkers = [];
|
||||
this.jobsDict = {};
|
||||
this.jobs = {};
|
||||
this.active = false;
|
||||
this.logger = logger.fork('WorkerDialog');
|
||||
this.originManager = new JobOriginClient({
|
||||
logger: this.logger
|
||||
});
|
||||
};
|
||||
|
||||
WorkerDialog.prototype.initialize = function() {
|
||||
this._dialog = $(WorkerHtml);
|
||||
this._table = this._dialog.find('.worker-list');
|
||||
this.$noJobs = this._dialog.find('.no-jobs-msg');
|
||||
this.$noWorkers = this._dialog.find('.no-workers-msg');
|
||||
this._isShowingJobs = false;
|
||||
this._isShowingWorkers = true;
|
||||
this._queue = this._dialog.find('.job-queue-list');
|
||||
this._dialog.modal('show');
|
||||
this._dialog.on('hidden.bs.modal', () => this.active = false);
|
||||
};
|
||||
|
||||
WorkerDialog.prototype.show = function() {
|
||||
this.active = true;
|
||||
this.update();
|
||||
this.initialize();
|
||||
};
|
||||
|
||||
WorkerDialog.prototype.get = function(url) {
|
||||
var deferred = Q.defer();
|
||||
|
||||
superagent.get(url)
|
||||
.end((err, res) => {
|
||||
if (err) {
|
||||
return deferred.reject(err);
|
||||
}
|
||||
deferred.resolve(JSON.parse(res.text));
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
};
|
||||
|
||||
WorkerDialog.prototype.update = function() {
|
||||
// Poll the workers
|
||||
return Q.all([
|
||||
this.get(WORKER_ENDPOINT).then(workers => this.updateWorkers(workers)),
|
||||
this.get(JOBS_ENDPOINT).then(jobs => this.updateJobs(jobs))
|
||||
]).then(() => {
|
||||
if (this.active) {
|
||||
setTimeout(this.update.bind(this), 1000);
|
||||
}
|
||||
})
|
||||
.catch(err => this.logger.error('Update failed:', err));
|
||||
};
|
||||
|
||||
WorkerDialog.prototype.updateWorkers = function(workerDict) {
|
||||
var ids = Object.keys(workerDict),
|
||||
oldWorkerIds,
|
||||
visibleWorkers = false,
|
||||
i;
|
||||
|
||||
this.runningWorkers = [];
|
||||
for (i = ids.length; i--;) {
|
||||
this.updateWorker(workerDict[ids[i]]);
|
||||
visibleWorkers = true;
|
||||
delete this.workerDict[ids[i]];
|
||||
}
|
||||
this.toggleNoWorkersMsg(!visibleWorkers);
|
||||
|
||||
// Clear old workers
|
||||
oldWorkerIds = Object.keys(this.workerDict);
|
||||
for (i = oldWorkerIds.length; i--;) {
|
||||
this.removeWorker(oldWorkerIds[i]);
|
||||
}
|
||||
|
||||
this.workerDict = workerDict;
|
||||
};
|
||||
|
||||
WorkerDialog.prototype.updateWorker = function(worker) {
|
||||
var row = this.workers[worker.clientId] || $(WorkerTemplate),
|
||||
clazz;
|
||||
|
||||
worker.lastSeen = utils.getDisplayTime(worker.lastSeen*1000);
|
||||
worker.status = worker.jobs.length ? 'RUNNING' : 'READY';
|
||||
|
||||
clazz = worker.status === 'RUNNING' ? 'warning' : 'success';
|
||||
row[0].className = clazz;
|
||||
|
||||
row.find('.lastSeen').text(worker.lastSeen);
|
||||
row.find('.clientId').text(worker.clientId);
|
||||
row.find('.status').text(worker.status);
|
||||
if (!this.workers[worker.clientId]) {
|
||||
this._table.append(row);
|
||||
this.workers[worker.clientId] = row;
|
||||
}
|
||||
|
||||
if (worker.status === 'RUNNING') {
|
||||
this.runningWorkers.push(worker);
|
||||
}
|
||||
};
|
||||
|
||||
WorkerDialog.prototype.removeWorker = function(workerId) {
|
||||
this.workers[workerId].remove();
|
||||
delete this.workers[workerId];
|
||||
};
|
||||
|
||||
WorkerDialog.prototype.updateJobs = function(jobsDict) {
|
||||
var allJobIds = Object.keys(jobsDict),
|
||||
hasJobs = false,
|
||||
id;
|
||||
|
||||
this.jobsDict = jobsDict;
|
||||
for (var i = allJobIds.length; i--;) {
|
||||
id = allJobIds[i];
|
||||
if (this.jobs[id] || !this.isFinished(id)) {
|
||||
hasJobs = this.updateJobItem(id) || hasJobs;
|
||||
}
|
||||
}
|
||||
this.setNoJobsMessage(!hasJobs); // hide if no queue
|
||||
};
|
||||
|
||||
WorkerDialog.prototype.setNoJobsMessage = function(visible) {
|
||||
var visibility = visible ? 'inherit' : 'none',
|
||||
wasVisible = !this._isShowingJobs;
|
||||
|
||||
if (visible !== wasVisible) {
|
||||
this.$noJobs.css('display', visibility);
|
||||
this._isShowingJobs = !visible;
|
||||
}
|
||||
};
|
||||
|
||||
WorkerDialog.prototype.toggleNoWorkersMsg = function(visible) {
|
||||
var visibility = visible ? 'inherit' : 'none';
|
||||
|
||||
if (visible !== this._isShowingWorkers) {
|
||||
this.$noWorkers.css('display', visibility);
|
||||
this._isShowingWorkers = visible;
|
||||
}
|
||||
};
|
||||
|
||||
WorkerDialog.prototype.isFinished = function(jobId) {
|
||||
return this.jobsDict[jobId].status === 'FAILED_TO_EXECUTE' ||
|
||||
this.jobsDict[jobId].status === 'SUCCESS' ||
|
||||
this.jobsDict[jobId].status === 'CANCELED';
|
||||
};
|
||||
|
||||
WorkerDialog.prototype.updateJobItemName = function(jobId) {
|
||||
return this.originManager.getOrigin(jobId)
|
||||
.then(info => {
|
||||
var job = this.jobs[jobId],
|
||||
project = info.project.replace(/^guest\+/, '');
|
||||
|
||||
if (job && this.active) {
|
||||
if (info.branch !== 'master') {
|
||||
project += ' (' + info.branch + ')';
|
||||
}
|
||||
job.find('.job-id').text(info.job);
|
||||
job.find('.execution').text(info.execution);
|
||||
job.find('.project').text(project);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
WorkerDialog.prototype.getWorkerWithJob = function(jobId) {
|
||||
var jobs;
|
||||
|
||||
for (var i = this.runningWorkers.length; i--;) {
|
||||
jobs = this.runningWorkers[i].jobs;
|
||||
for (var j = jobs.length; j--;) {
|
||||
if (jobs[j].hash === jobId) {
|
||||
return this.runningWorkers[i].clientId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 'unknown';
|
||||
};
|
||||
|
||||
WorkerDialog.prototype.updateJobItem = function(jobId) {
|
||||
var job = this.jobs[jobId] || $(WorkerJobItem),
|
||||
info = this.jobsDict[jobId],
|
||||
createdTime = new Date(info.createTime).getTime(),
|
||||
clazz = utils.ClassForJobStatus[info.status.toLowerCase()],
|
||||
status = info.status;
|
||||
|
||||
job[0].className = `job-tag ${clazz}`;
|
||||
|
||||
// Add the worker id if running
|
||||
if (info.status.toLowerCase() === 'running') {
|
||||
var workerId = this.getWorkerWithJob(jobId);
|
||||
status += ' (' + workerId + ')';
|
||||
}
|
||||
job.find('.status').text(status);
|
||||
|
||||
if (!this.jobs[jobId]) {
|
||||
job.find('.job-id').text('Loading');
|
||||
job.find('.createdAt').text(utils.getDisplayTime(createdTime));
|
||||
this.updateJobItemName(jobId);
|
||||
this._queue.append(job);
|
||||
this.jobs[jobId] = job;
|
||||
}
|
||||
|
||||
if (this.isFinished(jobId)) {
|
||||
job.remove();
|
||||
delete this.jobs[jobId];
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
return WorkerDialog;
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
/*globals define, angular, _,*/
|
||||
/*jshint browser: true*/
|
||||
|
||||
define([
|
||||
'panels/BreadcrumbHeader/BreadcrumbHeaderPanel',
|
||||
'js/Widgets/UserProfile/UserProfileWidget',
|
||||
'js/Widgets/ConnectedUsers/ConnectedUsersWidget',
|
||||
'js/Panels/Header/DefaultToolbar',
|
||||
'panels/BreadcrumbHeader/NodePathNavigator',
|
||||
'js/Toolbar/Toolbar',
|
||||
'./ProjectNavigatorController'
|
||||
], function (
|
||||
BreadcrumbHeader,
|
||||
UserProfileWidget,
|
||||
ConnectedUsersWidget,
|
||||
DefaultToolbar,
|
||||
NodePathNavigator,
|
||||
Toolbar,
|
||||
ProjectNavigatorController
|
||||
) {
|
||||
'use strict';
|
||||
|
||||
var HeaderPanel;
|
||||
|
||||
HeaderPanel = function (layoutManager, params) {
|
||||
BreadcrumbHeader.call(this, layoutManager, params);
|
||||
};
|
||||
|
||||
//inherit from PanelBaseWithHeader
|
||||
_.extend(HeaderPanel.prototype, BreadcrumbHeader.prototype);
|
||||
|
||||
HeaderPanel.prototype._initialize = function () {
|
||||
BreadcrumbHeader.prototype._initialize.call(this);
|
||||
var app = angular.module('gmeApp');
|
||||
|
||||
app.controller('ProjectNavigatorController', ['$scope', 'gmeClient', '$timeout', '$window', '$http',
|
||||
ProjectNavigatorController]);
|
||||
};
|
||||
|
||||
return HeaderPanel;
|
||||
});
|
||||
@@ -0,0 +1,7 @@
|
||||
<tr>
|
||||
<td class="job-id"></td>
|
||||
<td class="execution">unknown</td>
|
||||
<td class="project">unknown</td>
|
||||
<td class="createdAt">unknown</td>
|
||||
<td class="status">unknown</td>
|
||||
</tr>
|
||||
@@ -0,0 +1,47 @@
|
||||
.worker-modal .modal-content .modal-header span {
|
||||
font-size: 28px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.worker-modal .modal-content .modal-header .header-icon {
|
||||
height: 28px;
|
||||
width: 28px;
|
||||
margin-right: 1ex;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
background-size: 28px 28px;
|
||||
}
|
||||
|
||||
.worker-modal .modal-content .modal-body th {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.worker-modal .job-tag {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.worker-modal .queue-title {
|
||||
float: left;
|
||||
margin-right: 5px;
|
||||
font-size: 1.4em;
|
||||
color: #555555;
|
||||
font-weight: bold;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.worker-modal .no-jobs-msg {
|
||||
font-style: italic;
|
||||
font-size: 1.3em;
|
||||
color: #777;
|
||||
}
|
||||
|
||||
.worker-modal .no-workers-msg {
|
||||
font-style: italic;
|
||||
font-size: 1.3em;
|
||||
color: #777;
|
||||
}
|
||||
|
||||
.worker-modal .job-queue {
|
||||
padding-top: 1em;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<div class="worker-modal modal fade in" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">x</button>
|
||||
<i class="header-icon gme-icon"></i>
|
||||
<span>Overview</span>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div>
|
||||
<div class="queue-title">Connected Workers</div>
|
||||
<table class="table table-projects">
|
||||
<thead>
|
||||
<tr class="with-children">
|
||||
<th class="title-owner">Worker Id
|
||||
<!--<i class="glyphicon glyphicon-sort-by-attributes-alt sorted in-order"></i>
|
||||
<i class="glyphicon glyphicon-sort-by-attributes sorted rev-order"></i>-->
|
||||
</th>
|
||||
<th class="title-name">Last Seen
|
||||
<!--<i class="glyphicon glyphicon-sort-by-attributes-alt sorted in-order"></i>
|
||||
<i class="glyphicon glyphicon-sort-by-attributes sorted rev-order"></i>-->
|
||||
</th>
|
||||
<th class="title-modified">Status
|
||||
<!--<i class="glyphicon glyphicon-sort-by-attributes-alt sorted in-order"></i>
|
||||
<i class="glyphicon glyphicon-sort-by-attributes sorted rev-order"></i>-->
|
||||
</th>
|
||||
</tr>
|
||||
<!--<tr class="with-no-children">
|
||||
<th>No projects in this group...</th>
|
||||
</tr>-->
|
||||
</thead>
|
||||
<tbody class="worker-list">
|
||||
<tr><td class="no-workers-msg">No Connected Workers...</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="job-queue">
|
||||
<div class="queue-title">Job Queue</div>
|
||||
<table class="table table-projects">
|
||||
<thead>
|
||||
<tr class="with-children">
|
||||
<th>Job</th>
|
||||
<th>Execution</th>
|
||||
<th>Project</th>
|
||||
<th>Creation Date</th>
|
||||
<th>Status</th>
|
||||
</tr>
|
||||
<!--<tr class="with-no-children">-->
|
||||
<!--<th>No queued jobs</th>-->
|
||||
<!--</tr>-->
|
||||
</thead>
|
||||
<tbody class="job-queue-list">
|
||||
<tr><td class="no-jobs-msg">No Running Jobs...</td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,5 @@
|
||||
<tr>
|
||||
<td class="clientId"></td>
|
||||
<td class="lastSeen">unknown</td>
|
||||
<td class="status">unknown</td>
|
||||
</tr>
|
||||
@@ -3,10 +3,12 @@
|
||||
define([
|
||||
'widgets/EasyDAG/SelectionManager',
|
||||
'widgets/EasyDAG/Buttons',
|
||||
'deepforge/Constants',
|
||||
'underscore'
|
||||
], function(
|
||||
EasyDAGSelectionManager,
|
||||
Buttons,
|
||||
CONSTANTS,
|
||||
_
|
||||
) {
|
||||
'use strict';
|
||||
@@ -18,16 +20,19 @@ define([
|
||||
_.extend(SelectionManager.prototype, EasyDAGSelectionManager.prototype);
|
||||
|
||||
SelectionManager.prototype.createActionButtons = function(width/*, height*/) {
|
||||
// Add 'watch' and 'jumpToDef' buttons
|
||||
// TODO
|
||||
new Buttons.Enter({
|
||||
context: this._widget,
|
||||
$pEl: this.$selection,
|
||||
item: this.selectedItem,
|
||||
icon: 'monitor',
|
||||
x: width,
|
||||
y: 0
|
||||
});
|
||||
var jobName = this.selectedItem.desc.name;
|
||||
|
||||
// Check if it is an Input or Output job
|
||||
if (jobName !== CONSTANTS.OP.INPUT && jobName !== CONSTANTS.OP.OUTPUT) {
|
||||
new Buttons.Enter({
|
||||
context: this._widget,
|
||||
$pEl: this.$selection,
|
||||
item: this.selectedItem,
|
||||
icon: 'monitor',
|
||||
x: width,
|
||||
y: 0
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return SelectionManager;
|
||||
|
||||
@@ -82,7 +82,6 @@ define([
|
||||
|
||||
ImageViewerWidget.prototype.updateImage = function (url) {
|
||||
url = url || NO_IMAGE_URL;
|
||||
this.zoom = 1;
|
||||
this.$image.attr('src', url);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"deepforge": [
|
||||
"Graph",
|
||||
"initialize",
|
||||
"image"
|
||||
],
|
||||
"torch": [
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
var testFixture = require('../../globals'),
|
||||
expect = testFixture.expect,
|
||||
assert = require('assert'),
|
||||
path = testFixture.path,
|
||||
gmeConfig = testFixture.getGmeConfig(),
|
||||
blobDir = gmeConfig.blob.fsDir,
|
||||
server = testFixture.WebGME.standaloneServer(gmeConfig),
|
||||
Logger = require('webgme/src/server/logger'),
|
||||
logger = Logger.createWithGmeConfig('gme', gmeConfig, true),
|
||||
JobLogsClient = testFixture.requirejs('deepforge/api/JobLogsClient'),
|
||||
rm_rf = require('rimraf'),
|
||||
exists = require('exists-file');
|
||||
|
||||
describe('JobLogsClient', function() {
|
||||
var logClient = new JobLogsClient({
|
||||
logger: logger,
|
||||
origin: server.getUrl(),
|
||||
projectId: 'testProject',
|
||||
branchName: 'master'
|
||||
}),
|
||||
jobId = '/4/q/l',
|
||||
firstLog = 'hello world';
|
||||
|
||||
before(function(done) {
|
||||
testFixture.mkdir(blobDir);
|
||||
server.start(done);
|
||||
});
|
||||
|
||||
after(function(done) {
|
||||
rm_rf.sync(blobDir);
|
||||
server.stop(done);
|
||||
});
|
||||
|
||||
describe('appendTo', function() {
|
||||
|
||||
before(function(done) {
|
||||
logClient.appendTo(jobId, firstLog)
|
||||
.then(() => done())
|
||||
.catch(err => done(err));
|
||||
});
|
||||
|
||||
it('should create job-logs directory', function() {
|
||||
assert(exists.sync(path.join(blobDir, 'log-storage')));
|
||||
});
|
||||
|
||||
describe('getLog', function() {
|
||||
it('should return the logs from the job', function(done) {
|
||||
logClient.getLog(jobId).then(log => {
|
||||
expect(log).to.contain(firstLog);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should append additional logs to the file', function(done) {
|
||||
var secondLog = 'goodbye world';
|
||||
logClient.appendTo(jobId, secondLog)
|
||||
.then(() => logClient.getLog(jobId))
|
||||
.then(log => {
|
||||
expect(log).to.contain(secondLog);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe('delete', function() {
|
||||
var delJobId = '/4/8/l';
|
||||
|
||||
before(function(done) {
|
||||
logClient.appendTo(delJobId, firstLog).then(() => done());
|
||||
});
|
||||
|
||||
it('should delete the file from job-logs directory', function(done) {
|
||||
logClient.deleteLog(delJobId)
|
||||
.then(() => logClient.getLog(delJobId))
|
||||
.then(log => {
|
||||
expect(log).to.equal('');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('migration', function() {
|
||||
var client,
|
||||
jId = '/asd/4/q',
|
||||
logs = 'asdfasde',
|
||||
newBranch = 'otherBranch';
|
||||
|
||||
before(function(done) {
|
||||
client = new JobLogsClient({
|
||||
logger: logger,
|
||||
origin: server.getUrl(),
|
||||
projectId: 'migTest',
|
||||
branchName: 'master'
|
||||
});
|
||||
// Write logs to job
|
||||
client.appendTo(jId, logs)
|
||||
.then(() => client.fork(newBranch))
|
||||
.catch(err => done(err))
|
||||
.then(() => done());
|
||||
});
|
||||
|
||||
it('should migrate the edited nodes to the new branch', function(done) {
|
||||
client.getLog(jId).then(log => {
|
||||
expect(log).to.equal(logs);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('new logs', function() {
|
||||
it('should not edit old job logs', function() {
|
||||
var c2 = new JobLogsClient({
|
||||
logger: logger,
|
||||
origin: server.getUrl(),
|
||||
projectId: 'migTest',
|
||||
branchName: 'master'
|
||||
});
|
||||
c2.getLog(jId).then(log => {
|
||||
expect(log).to.equal(logs);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should write new logs', function() {
|
||||
client.appendTo(jId, 'moreStuff')
|
||||
.then(() => client.getLog(jId))
|
||||
.then(log => {
|
||||
expect(log).to.contain('moreStuff');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: Test that, on a fork, the logClient will copy all the current jobs to
|
||||
// the new fork name
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,81 @@
|
||||
var testFixture = require('../../globals'),
|
||||
expect = testFixture.expect,
|
||||
gmeConfig = testFixture.getGmeConfig(),
|
||||
server = testFixture.WebGME.standaloneServer(gmeConfig),
|
||||
Logger = require('webgme/src/server/logger'),
|
||||
logger = Logger.createWithGmeConfig('gme', gmeConfig, true),
|
||||
JobOriginClient = testFixture.requirejs('deepforge/api/JobOriginClient');
|
||||
|
||||
describe('JobOriginClient', function() {
|
||||
var client = new JobOriginClient({
|
||||
logger: logger,
|
||||
origin: server.getUrl(),
|
||||
projectId: 'testProject',
|
||||
branchName: 'master'
|
||||
}),
|
||||
hashes = {},
|
||||
getJobInfo = function() {
|
||||
var hash = 'hashOrigin'+Math.ceil(Math.random()*100000);
|
||||
|
||||
while (hashes[hash]) {
|
||||
hash = 'hashOrigin'+Math.ceil(Math.random()*100000);
|
||||
}
|
||||
hashes[hash] = true;
|
||||
|
||||
return {
|
||||
hash: hash,
|
||||
job: 'SomeJob',
|
||||
execution: 'train_execution',
|
||||
nodeId: 'K/6/1'
|
||||
};
|
||||
};
|
||||
|
||||
before(function(done) {
|
||||
server.start(done);
|
||||
});
|
||||
|
||||
after(function(done) {
|
||||
server.stop(done);
|
||||
});
|
||||
|
||||
it('should store job info', function(done) {
|
||||
var job = getJobInfo();
|
||||
|
||||
client.record(job.hash, job)
|
||||
.nodeify(done);
|
||||
});
|
||||
|
||||
it('should read job info', function(done) {
|
||||
var job = getJobInfo();
|
||||
|
||||
client.record(job.hash, job)
|
||||
.then(() => client.getOrigin(job.hash))
|
||||
.then(jobInfo => {
|
||||
Object.keys(job).forEach(key => {
|
||||
expect(jobInfo[key]).equal(job[key]);
|
||||
});
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
|
||||
it('should delete job info', function(done) {
|
||||
var job = getJobInfo();
|
||||
|
||||
client.record(job.hash, job)
|
||||
.then(() => client.deleteRecord(job.hash))
|
||||
.then(() => client.getOrigin(job.hash))
|
||||
.then(res => expect(res).equal(null))
|
||||
.nodeify(done);
|
||||
});
|
||||
|
||||
it('should update job branch on fork', function(done) {
|
||||
var job = getJobInfo(),
|
||||
newBranch = 'newBranch';
|
||||
|
||||
client.record(job.hash, job)
|
||||
.then(() => client.fork(job.hash, newBranch))
|
||||
.then(() => client.getOrigin(job.hash))
|
||||
.then(res => expect(res.branch).equal(newBranch))
|
||||
.nodeify(done);
|
||||
});
|
||||
});
|
||||
@@ -7,6 +7,9 @@
|
||||
'use strict';
|
||||
|
||||
var testFixture = require('webgme/test/_globals'),
|
||||
path = require('path'),
|
||||
fs = require('fs'),
|
||||
exists = require('exists-file'),
|
||||
WEBGME_CONFIG_PATH = '../config';
|
||||
|
||||
// This flag will make sure the config.test.js is being used
|
||||
@@ -34,4 +37,18 @@ testFixture.requirejs.config({
|
||||
testFixture.getGmeConfig = getGmeConfig;
|
||||
|
||||
testFixture.DF_SEED_DIR = testFixture.path.join(__dirname, '..', 'src', 'seeds');
|
||||
|
||||
testFixture.mkdir = function(dir) {
|
||||
var dirs = path.resolve(dir).split(path.sep),
|
||||
shortDir,
|
||||
i = 1;
|
||||
|
||||
while (i++ < dirs.length) {
|
||||
shortDir = dirs.slice(0,i).join(path.sep);
|
||||
if (!exists.sync(shortDir)) {
|
||||
fs.mkdirSync(shortDir);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = testFixture;
|
||||
|
||||
@@ -10,12 +10,14 @@ describe('ExecuteJob', function () {
|
||||
PluginCliManager = testFixture.WebGME.PluginCliManager,
|
||||
projectName = 'testProject',
|
||||
pluginName = 'ExecuteJob',
|
||||
manager = new PluginCliManager(null, logger, gmeConfig),
|
||||
project,
|
||||
gmeAuth,
|
||||
storage,
|
||||
commitHash;
|
||||
|
||||
before(function (done) {
|
||||
this.timeout(10000);
|
||||
testFixture.clearDBAndGetGMEAuth(gmeConfig, projectName)
|
||||
.then(function (gmeAuth_) {
|
||||
gmeAuth = gmeAuth_;
|
||||
@@ -25,7 +27,7 @@ describe('ExecuteJob', function () {
|
||||
})
|
||||
.then(function () {
|
||||
var importParam = {
|
||||
projectSeed: testFixture.path.join(testFixture.SEED_DIR, 'EmptyProject.webgmex'),
|
||||
projectSeed: testFixture.path.join(testFixture.DF_SEED_DIR, 'devProject', 'devProject.webgmex'),
|
||||
projectName: projectName,
|
||||
branchName: 'master',
|
||||
logger: logger,
|
||||
@@ -51,9 +53,7 @@ describe('ExecuteJob', function () {
|
||||
});
|
||||
|
||||
it('should verify activeNode is "Job"', function (done) {
|
||||
var manager = new PluginCliManager(null, logger, gmeConfig),
|
||||
pluginConfig = {
|
||||
},
|
||||
var pluginConfig = {},
|
||||
context = {
|
||||
project: project,
|
||||
commitHash: commitHash,
|
||||
@@ -68,4 +68,285 @@ describe('ExecuteJob', function () {
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
////////// Helper Functions //////////
|
||||
var plugin,
|
||||
node,
|
||||
preparePlugin = function(done) {
|
||||
var context = {
|
||||
project: project,
|
||||
commitHash: commitHash,
|
||||
branchName: 'test',
|
||||
activeNode: '/K/R/p' // hello world job
|
||||
};
|
||||
|
||||
return manager.initializePlugin(pluginName)
|
||||
.then(plugin_ => {
|
||||
plugin = plugin_;
|
||||
return manager.configurePlugin(plugin, {}, context);
|
||||
})
|
||||
.then(() => node = plugin.activeNode)
|
||||
.nodeify(done);
|
||||
};
|
||||
|
||||
////////// END Helper Functions //////////
|
||||
|
||||
// Race condition checks w/ saving...
|
||||
describe('get/set', function() {
|
||||
beforeEach(preparePlugin);
|
||||
|
||||
it('should get correct attribute after set', function() {
|
||||
plugin.setAttribute(node, 'status', 'queued');
|
||||
var attrValue = plugin.getAttribute(node, 'status');
|
||||
expect(attrValue).to.equal('queued');
|
||||
});
|
||||
|
||||
it('should get correct attribute before updating nodes', function(done) {
|
||||
// Run setAttribute on some node
|
||||
plugin.setAttribute(node, 'status', 'queued');
|
||||
|
||||
// Check that the value is correct before applying node changes
|
||||
var updateNodes = plugin.updateNodes;
|
||||
plugin.updateNodes = function() {
|
||||
var attrValue = plugin.getAttribute(node, 'status');
|
||||
expect(attrValue).to.equal('queued');
|
||||
return updateNodes.apply(this, arguments);
|
||||
};
|
||||
plugin.save().nodeify(done);
|
||||
});
|
||||
|
||||
it('should get correct attribute (from new node) before updating nodes', function(done) {
|
||||
// Run setAttribute on some node
|
||||
var graphTmp = plugin.createNode('pipeline.Graph', node),
|
||||
newVal = 'testGraph',
|
||||
id = 'testId';
|
||||
|
||||
// Get the
|
||||
plugin.setAttribute(graphTmp, 'name', newVal);
|
||||
plugin._metadata[id] = graphTmp;
|
||||
plugin.createIdToMetadataId[graphTmp] = id;
|
||||
|
||||
// Check that the value is correct before applying node changes
|
||||
var updateNodes = plugin.updateNodes;
|
||||
plugin.updateNodes = function() {
|
||||
var graph = plugin._metadata[id],
|
||||
attrValue = plugin.getAttribute(graph, 'name');
|
||||
|
||||
expect(attrValue).to.equal(newVal);
|
||||
return updateNodes.apply(this, arguments);
|
||||
};
|
||||
plugin.save().nodeify(done);
|
||||
});
|
||||
|
||||
it('should get correct attribute after save', function(done) {
|
||||
// Run setAttribute on some node
|
||||
plugin.setAttribute(node, 'status', 'queued');
|
||||
|
||||
// Check that the value is correct before applying node changes
|
||||
plugin.save()
|
||||
.then(() => {
|
||||
var attrValue = plugin.getAttribute(node, 'status');
|
||||
expect(attrValue).to.equal('queued');
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
|
||||
it('should get correct attribute while applying node changes', function(done) {
|
||||
// Run setAttribute on some node
|
||||
plugin.setAttribute(node, 'status', 'queued');
|
||||
|
||||
// Check that the value is correct before applying node changes
|
||||
var oldApplyChanges = plugin._applyNodeChanges;
|
||||
plugin._applyNodeChanges = function() {
|
||||
var attrValue = plugin.getAttribute(node, 'status');
|
||||
expect(attrValue).to.equal('queued');
|
||||
return oldApplyChanges.apply(this, arguments);
|
||||
};
|
||||
plugin.save().nodeify(done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('createNode', function() {
|
||||
beforeEach(preparePlugin);
|
||||
|
||||
it('should update _metadata after applying changes', function(done) {
|
||||
// Run setAttribute on some node
|
||||
var graphTmp = plugin.createNode('pipeline.Graph', node),
|
||||
id = 'testId';
|
||||
|
||||
plugin._metadata[id] = graphTmp;
|
||||
plugin.createIdToMetadataId[graphTmp] = id;
|
||||
|
||||
// Check that the value is correct before applying node changes
|
||||
var applyModelChanges = plugin.applyModelChanges;
|
||||
plugin.applyModelChanges = function() {
|
||||
return applyModelChanges.apply(this, arguments)
|
||||
.then(() => {
|
||||
var graph = plugin._metadata[id];
|
||||
expect(graph).to.not.equal(graphTmp);
|
||||
});
|
||||
};
|
||||
plugin.save().nodeify(done);
|
||||
});
|
||||
|
||||
it('should update _metadata in updateNodes', function(done) {
|
||||
var id = 'testId';
|
||||
|
||||
plugin._metadata[id] = node;
|
||||
node.old = true;
|
||||
plugin.updateNodes()
|
||||
.then(() => {
|
||||
var graph = plugin._metadata[id];
|
||||
expect(graph.old).to.not.equal(true);
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
|
||||
// Check that it gets the correct value from a newly created node after
|
||||
// it has been saved/created
|
||||
it('should get changed attribute', function(done) {
|
||||
// Run setAttribute on some node
|
||||
var graphTmp = plugin.createNode('pipeline.Graph', node),
|
||||
id = 'testId';
|
||||
|
||||
plugin._metadata[id] = node;
|
||||
plugin.createIdToMetadataId[graphTmp] = id;
|
||||
|
||||
plugin.setAttribute(graphTmp, 'name', 'firstName');
|
||||
|
||||
// Check that the value is correct before applying node changes
|
||||
plugin.save()
|
||||
.then(() => {
|
||||
var graph = plugin._metadata[id],
|
||||
val = plugin.getAttribute(graph, 'name');
|
||||
expect(val).to.equal('firstName');
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
|
||||
it('should get inherited attribute', function(done) {
|
||||
// Run setAttribute on some node
|
||||
var graphTmp = plugin.createNode('pipeline.Graph', node),
|
||||
id = 'testId',
|
||||
val;
|
||||
|
||||
// Check that the value is correct before applying node changes
|
||||
plugin._metadata[id] = node;
|
||||
plugin.createIdToMetadataId[graphTmp] = id;
|
||||
|
||||
val = plugin.getAttribute(graphTmp, 'name');
|
||||
expect(val).to.equal('Graph');
|
||||
|
||||
plugin.save()
|
||||
.then(() => {
|
||||
var graph = plugin._metadata[id];
|
||||
|
||||
val = plugin.getAttribute(graph, 'name');
|
||||
|
||||
expect(val).to.equal('Graph');
|
||||
})
|
||||
.nodeify(done);
|
||||
});
|
||||
});
|
||||
|
||||
// Canceling
|
||||
describe('cancel', function() {
|
||||
beforeEach(preparePlugin);
|
||||
|
||||
it('should stop the job if the execution is canceled', function(done) {
|
||||
var job = node,
|
||||
hash = 'abc123',
|
||||
exec = {
|
||||
cancelJob: jobHash => expect(jobHash).equal(hash)
|
||||
};
|
||||
|
||||
plugin.setAttribute(node, 'secret', 'abc');
|
||||
plugin.isExecutionCanceled = () => true;
|
||||
plugin.onOperationCanceled = () => done();
|
||||
plugin.watchOperation(exec, hash, job, job);
|
||||
});
|
||||
|
||||
it('should stop the job if a job is canceled', function(done) {
|
||||
var job = node,
|
||||
hash = 'abc123',
|
||||
exec = {
|
||||
cancelJob: jobHash => expect(jobHash).equal(hash)
|
||||
};
|
||||
|
||||
plugin.setAttribute(job, 'secret', 'abc');
|
||||
plugin.canceled = true;
|
||||
plugin.onOperationCanceled = () => done();
|
||||
plugin.watchOperation(exec, hash, job, job);
|
||||
});
|
||||
|
||||
it('should set exec to running', function(done) {
|
||||
var job = node,
|
||||
execNode = plugin.core.getParent(job);
|
||||
|
||||
// Set the execution to canceled
|
||||
plugin.setAttribute(execNode, 'status', 'canceled');
|
||||
plugin.prepare = () => {
|
||||
var status = plugin.getAttribute(execNode, 'status');
|
||||
expect(status).to.not.equal('canceled');
|
||||
return {then: () => done()};
|
||||
};
|
||||
plugin.main();
|
||||
});
|
||||
});
|
||||
|
||||
describe('exec files', function() {
|
||||
describe('attribute file', function() {
|
||||
var boolString = /['"](true|false)['"]/g;
|
||||
|
||||
beforeEach(preparePlugin);
|
||||
|
||||
it('should not quote true (s) boolean values', function() {
|
||||
var files = {},
|
||||
content,
|
||||
matches;
|
||||
|
||||
plugin.setAttribute(node, 'debug', 'true');
|
||||
plugin.createAttributeFile(node, files);
|
||||
content = files['attributes.lua'];
|
||||
matches = content.match(boolString);
|
||||
expect(matches).to.equal(null);
|
||||
});
|
||||
|
||||
it('should not quote true boolean values', function() {
|
||||
var files = {},
|
||||
content,
|
||||
matches;
|
||||
|
||||
plugin.setAttribute(node, 'debug', true);
|
||||
plugin.createAttributeFile(node, files);
|
||||
content = files['attributes.lua'];
|
||||
matches = content.match(boolString);
|
||||
expect(matches).to.equal(null);
|
||||
});
|
||||
|
||||
it('should not quote false (s) boolean values', function() {
|
||||
var files = {},
|
||||
content,
|
||||
matches;
|
||||
|
||||
plugin.setAttribute(node, 'debug', 'false');
|
||||
plugin.createAttributeFile(node, files);
|
||||
content = files['attributes.lua'];
|
||||
matches = content.match(boolString);
|
||||
expect(matches).to.equal(null);
|
||||
});
|
||||
|
||||
it('should not quote false boolean values', function() {
|
||||
var files = {},
|
||||
content,
|
||||
matches;
|
||||
|
||||
plugin.setAttribute(node, 'debug', false);
|
||||
plugin.createAttributeFile(node, files);
|
||||
content = files['attributes.lua'];
|
||||
matches = content.match(boolString);
|
||||
expect(matches).to.equal(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -89,6 +89,7 @@ describe('GenerateArchitecture', function () {
|
||||
//['/o', 'basic.lua'],
|
||||
//['/8', 'basic-transfers.lua'],
|
||||
//['/M', 'concat-parallel.lua'],
|
||||
['/4', 'requiredOmitted.lua'],
|
||||
['/e', 'googlenet.lua'],
|
||||
['/X', 'overfeat.lua']
|
||||
];
|
||||
|
||||
@@ -14,7 +14,7 @@ var testFixture = require('../../globals'),
|
||||
];
|
||||
|
||||
describe('ImportTorch', function () {
|
||||
this.timeout(5000);
|
||||
this.timeout(7500);
|
||||
var gmeConfig = testFixture.getGmeConfig(),
|
||||
Q = testFixture.Q,
|
||||
GraphChecker = testFixture.requirejs('deepforge/GraphChecker'),
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
var testFixture = require('../../globals'),
|
||||
superagent = testFixture.superagent,
|
||||
Q = testFixture.Q,
|
||||
expect = testFixture.expect,
|
||||
assert = require('assert'),
|
||||
path = testFixture.path,
|
||||
gmeConfig = testFixture.getGmeConfig(),
|
||||
blobDir = gmeConfig.blob.fsDir,
|
||||
server = testFixture.WebGME.standaloneServer(gmeConfig),
|
||||
mntPt = 'execution/logs',
|
||||
rm_rf = require('rimraf'),
|
||||
exists = require('exists-file');
|
||||
|
||||
describe('JobLogsAPI', function() {
|
||||
var project = 'testProject',
|
||||
branch = 'master',
|
||||
jobId = encodeURIComponent('/4/q/l'),
|
||||
firstLog = 'hello world',
|
||||
url = [
|
||||
server.getUrl(),
|
||||
mntPt,
|
||||
project,
|
||||
branch,
|
||||
jobId
|
||||
].join('/');
|
||||
|
||||
before(function(done) {
|
||||
testFixture.mkdir(blobDir);
|
||||
server.start(done);
|
||||
});
|
||||
|
||||
after(function(done) {
|
||||
rm_rf.sync(blobDir);
|
||||
server.stop(done);
|
||||
});
|
||||
|
||||
describe('appendTo', function() {
|
||||
|
||||
before(function(done) {
|
||||
superagent.patch(url)
|
||||
.send({patch: firstLog})
|
||||
.end(function (err, res) {
|
||||
expect(res.status).equal(200, err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should create job-logs directory', function() {
|
||||
assert(exists.sync(path.join(blobDir, 'log-storage')));
|
||||
});
|
||||
|
||||
describe('getLog', function() {
|
||||
it('should return the logs from the job', function(done) {
|
||||
superagent.get(url)
|
||||
.end(function (err, res) {
|
||||
expect(res.status).equal(200, err);
|
||||
expect(res.text).to.contain(firstLog);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should append additional logs to the file', function(done) {
|
||||
var secondLog = 'goodbye world';
|
||||
superagent.patch(url)
|
||||
.send({patch: secondLog})
|
||||
.end(function (err, res) {
|
||||
expect(res.status).equal(200, err);
|
||||
superagent.get(url)
|
||||
.end(function (err, res) {
|
||||
expect(res.status).equal(200, err);
|
||||
expect(res.text).to.contain(secondLog);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
describe('delete', function() {
|
||||
var delUrl = [
|
||||
server.getUrl(),
|
||||
mntPt,
|
||||
'testProject',
|
||||
'other',
|
||||
encodeURIComponent('/4/8/l')
|
||||
].join('/');
|
||||
|
||||
before(function(done) {
|
||||
superagent.patch(delUrl)
|
||||
.send({patch: firstLog})
|
||||
.end(function (err, res) {
|
||||
expect(res.status).equal(200, err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should delete the file from job-logs directory', function(done) {
|
||||
superagent.delete(delUrl)
|
||||
.end(function (err, res) {
|
||||
expect(res.status).equal(200, err);
|
||||
superagent.get(delUrl)
|
||||
.end(function (err, res) {
|
||||
expect(res.status).equal(200, err);
|
||||
expect(res.text).to.equal('');
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function getUrl(project, branch, job) {
|
||||
return [
|
||||
server.getUrl(),
|
||||
mntPt,
|
||||
encodeURIComponent(project),
|
||||
encodeURIComponent(branch),
|
||||
encodeURIComponent(job)
|
||||
].join('/');
|
||||
}
|
||||
|
||||
function addLog(project, branch, job, log) {
|
||||
var deferred = Q.defer();
|
||||
|
||||
console.log('adding log', log);
|
||||
superagent.patch(getUrl(project, branch, job))
|
||||
.send({patch: log})
|
||||
.end(function (err, res) {
|
||||
if (err) {
|
||||
return deferred.reject(err + ' (' + job + ')');
|
||||
}
|
||||
return deferred.resolve(res);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
describe('migrate', function() {
|
||||
var j1 = '/s/p/3',
|
||||
j2 = '/1/d/4',
|
||||
b1 = 'asdfmaster',
|
||||
b2 = 'not-master',
|
||||
proj = 'someProject',
|
||||
j1log = 'I am ' + j1,
|
||||
j2log = 'I am ' + j2,
|
||||
url;
|
||||
|
||||
before(function(done) {
|
||||
Q.all([
|
||||
addLog(proj, b1, j1, j1log),
|
||||
addLog(proj, b1, j2, j2log),
|
||||
addLog(proj, b2, j2, 'otherStuff')
|
||||
]).then(() => {
|
||||
url = [
|
||||
server.getUrl(),
|
||||
mntPt + '/migrate',
|
||||
encodeURIComponent(proj),
|
||||
encodeURIComponent(b1),
|
||||
encodeURIComponent(b2)
|
||||
].join('/');
|
||||
superagent.post(url)
|
||||
.send({jobs: [j1]})
|
||||
.end(err => done(err));
|
||||
})
|
||||
.catch(err => done(err));
|
||||
|
||||
});
|
||||
|
||||
it('should copy the log content to the new branch', function(done) {
|
||||
url = getUrl(proj, b2, j1);
|
||||
superagent.get(url)
|
||||
.end((err, res) => {
|
||||
expect(res.text).to.equal(j1log);
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
it('should not copy other jobs', function(done) {
|
||||
url = getUrl(proj, b2, j2);
|
||||
superagent.get(url)
|
||||
.end((err, res) => {
|
||||
// This log shouldn't be updated
|
||||
expect(res.text).to.not.equal(j2log);
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
it('should not change original log', function(done) {
|
||||
url = getUrl(proj, b1, j1);
|
||||
superagent.get(url)
|
||||
.end((err, res) => {
|
||||
expect(res.text).to.equal(j1log);
|
||||
done(err);
|
||||
});
|
||||
});
|
||||
|
||||
it('should not crash on bad request', function(done) {
|
||||
url = [
|
||||
server.getUrl(),
|
||||
mntPt + '/migrate',
|
||||
encodeURIComponent(proj),
|
||||
encodeURIComponent('someBranch3'),
|
||||
encodeURIComponent(b2)
|
||||
].join('/');
|
||||
superagent.post(url)
|
||||
.send({jobs: [j1]})
|
||||
.end(err => done(err));
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,115 @@
|
||||
var testFixture = require('../../globals'),
|
||||
superagent = testFixture.superagent,
|
||||
expect = testFixture.expect,
|
||||
gmeConfig = testFixture.getGmeConfig(),
|
||||
server = testFixture.WebGME.standaloneServer(gmeConfig),
|
||||
mntPt = 'job/origins';
|
||||
|
||||
describe('JobOriginAPI', function() {
|
||||
var hashes = {},
|
||||
getUrl = function(hash) {
|
||||
return [
|
||||
server.getUrl(),
|
||||
mntPt,
|
||||
hash
|
||||
].join('/');
|
||||
},
|
||||
getJobInfo = function() {
|
||||
var hash = 'hash'+Math.ceil(Math.random()*100000);
|
||||
|
||||
while (hashes[hash]) {
|
||||
hash = 'hash'+Math.ceil(Math.random()*100000);
|
||||
}
|
||||
hashes[hash] = true;
|
||||
|
||||
return {
|
||||
hash: hash,
|
||||
job: 'SomeJob',
|
||||
branch: 'master',
|
||||
execution: 'train_execution',
|
||||
project: 'guest+example',
|
||||
nodeId: 'K/6/1'
|
||||
};
|
||||
};
|
||||
|
||||
before(function(done) {
|
||||
server.start(done);
|
||||
});
|
||||
|
||||
after(function(done) {
|
||||
server.stop(done);
|
||||
});
|
||||
|
||||
it('should store job info', function(done) {
|
||||
var job = getJobInfo();
|
||||
|
||||
superagent.post(getUrl(job.hash))
|
||||
.send(job)
|
||||
.end(function (err, res) {
|
||||
expect(res.status).equal(201, err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it('should read job info', function(done) {
|
||||
var job = getJobInfo(),
|
||||
url = getUrl(job.hash);
|
||||
|
||||
superagent.post(url)
|
||||
.send(job)
|
||||
.end(function (err, res) {
|
||||
expect(res.status).equal(201, err);
|
||||
superagent.get(url)
|
||||
.end((err, res) => {
|
||||
var jobInfo = JSON.parse(res.text);
|
||||
Object.keys(jobInfo).forEach(key => {
|
||||
expect(jobInfo[key]).equal(job[key]);
|
||||
});
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should delete job info', function(done) {
|
||||
var job = getJobInfo(),
|
||||
url = getUrl(job.hash);
|
||||
|
||||
superagent.post(url)
|
||||
.send(job)
|
||||
.end(function (err, res) {
|
||||
expect(res.status).equal(201, err);
|
||||
superagent.delete(url).end(err => {
|
||||
expect(err).equal(null);
|
||||
superagent.get(url)
|
||||
.end((err, res) => {
|
||||
expect(res.status).equal(404, err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should update job branch', function(done) {
|
||||
var job = getJobInfo(),
|
||||
url = getUrl(job.hash);
|
||||
|
||||
superagent.post(url) // create the job
|
||||
.send(job)
|
||||
.end(function (err, res) {
|
||||
expect(res.status).equal(201, err);
|
||||
superagent.patch(url) // update the branch
|
||||
.send({branch: 'newBranch'})
|
||||
.end(err => {
|
||||
expect(err).equal(null);
|
||||
|
||||
superagent.get(url) // check the new version
|
||||
.end((err, res) => {
|
||||
var info = JSON.parse(res.text);
|
||||
expect(info.branch).equal('newBranch');
|
||||
expect(res.status).equal(200, err);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -11,136 +11,130 @@ net:add(nn.SpatialConvolution(64, 192, 3, 3, 1, 1, 1, 1))
|
||||
net:add(nn.ReLU(true))
|
||||
net:add(nn.SpatialMaxPooling(3, 3, 2, 2))
|
||||
|
||||
local net = nn.Sequential()
|
||||
net:add(nn.SpatialConvolution(192, 64, 1, 1, 1, 1))
|
||||
net:add(nn.ReLU(true))
|
||||
net:add(nn.SpatialConvolution(64, 96, 3, 3, 1, 1, 1, 1))
|
||||
net:add(nn.ReLU(true))
|
||||
net:add(nn.SpatialConvolution(96, 96, 3, 3, 1, 1, 1, 1))
|
||||
net:add(nn.ReLU(true))
|
||||
|
||||
local net_2 = nn.Sequential()
|
||||
net_2:add(nn.SpatialConvolution(192, 64, 1, 1, 1, 1))
|
||||
net_2:add(nn.ReLU(true))
|
||||
net_2:add(nn.SpatialConvolution(64, 96, 3, 3, 1, 1, 1, 1))
|
||||
net_2:add(nn.ReLU(true))
|
||||
net_2:add(nn.SpatialConvolution(96, 96, 3, 3, 1, 1, 1, 1))
|
||||
net_2:add(nn.ReLU(true))
|
||||
|
||||
local net_3 = nn.Sequential()
|
||||
net_3:add(nn.SpatialConvolution(192, 64, 1, 1, 1, 1))
|
||||
net_3:add(nn.ReLU(true))
|
||||
net_3:add(nn.SpatialConvolution(64, 64, 3, 3, 1, 1, 1, 1))
|
||||
net_3:add(nn.ReLU(true))
|
||||
|
||||
local net_4 = nn.Sequential()
|
||||
net_4:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_4:add(nn.SpatialAveragePooling(3, 3, 1, 1))
|
||||
net_4:add(nn.SpatialConvolution(192, 32, 1, 1, 1, 1))
|
||||
net_4:add(nn.SpatialConvolution(192, 64, 1, 1, 1, 1))
|
||||
net_4:add(nn.ReLU(true))
|
||||
net_4:add(nn.SpatialConvolution(64, 64, 3, 3, 1, 1, 1, 1))
|
||||
net_4:add(nn.ReLU(true))
|
||||
|
||||
local net_5 = nn.Sequential()
|
||||
net_5:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_5:add(nn.SpatialAveragePooling(3, 3, 1, 1))
|
||||
net_5:add(nn.SpatialConvolution(192, 32, 1, 1, 1, 1))
|
||||
net_5:add(nn.ReLU(true))
|
||||
|
||||
local concat_24 = nn.Concat(2)
|
||||
concat_24:add(net_5)
|
||||
concat_24:add(net_4)
|
||||
concat_24:add(net_3)
|
||||
concat_24:add(net_2)
|
||||
concat_24:add(net)
|
||||
|
||||
net:add(concat_24)
|
||||
|
||||
local net_5 = nn.Sequential()
|
||||
net_5:add(nn.SpatialConvolution(256, 64, 1, 1, 1, 1))
|
||||
net_5:add(nn.ReLU(true))
|
||||
|
||||
local net_6 = nn.Sequential()
|
||||
net_6:add(nn.SpatialConvolution(256, 64, 1, 1, 1, 1))
|
||||
net_6:add(nn.ReLU(true))
|
||||
net_6:add(nn.SpatialConvolution(64, 96, 3, 3, 1, 1, 1, 1))
|
||||
net_6:add(nn.ReLU(true))
|
||||
|
||||
local net_7 = nn.Sequential()
|
||||
net_7:add(nn.SpatialConvolution(256, 64, 1, 1, 1, 1))
|
||||
net_7:add(nn.ReLU(true))
|
||||
net_7:add(nn.SpatialConvolution(64, 96, 3, 3, 1, 1, 1, 1))
|
||||
net_7:add(nn.ReLU(true))
|
||||
net_7:add(nn.SpatialConvolution(96, 96, 3, 3, 1, 1, 1, 1))
|
||||
net_7:add(nn.ReLU(true))
|
||||
|
||||
local net_8 = nn.Sequential()
|
||||
net_8:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_8:add(nn.SpatialAveragePooling(3, 3, 1, 1))
|
||||
net_8:add(nn.SpatialConvolution(256, 64, 1, 1, 1, 1))
|
||||
net_8:add(nn.ReLU(true))
|
||||
net_8:add(nn.SpatialConvolution(64, 96, 3, 3, 1, 1, 1, 1))
|
||||
net_8:add(nn.ReLU(true))
|
||||
net_8:add(nn.SpatialConvolution(96, 96, 3, 3, 1, 1, 1, 1))
|
||||
net_8:add(nn.ReLU(true))
|
||||
|
||||
local net_9 = nn.Sequential()
|
||||
net_9:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_9:add(nn.SpatialAveragePooling(3, 3, 1, 1))
|
||||
net_9:add(nn.SpatialConvolution(256, 64, 1, 1, 1, 1))
|
||||
net_9:add(nn.ReLU(true))
|
||||
|
||||
local concat_41 = nn.Concat(2)
|
||||
concat_41:add(net_9)
|
||||
concat_41:add(net_8)
|
||||
concat_41:add(net_7)
|
||||
concat_41:add(net_6)
|
||||
concat_41:add(net_5)
|
||||
|
||||
net:add(concat_41)
|
||||
|
||||
local net_9 = nn.Sequential()
|
||||
net_9:add(nn.SpatialConvolution(320, 128, 1, 1, 1, 1))
|
||||
net_9:add(nn.ReLU(true))
|
||||
net_9:add(nn.SpatialConvolution(128, 160, 3, 3, 1, 1, 1, 1))
|
||||
net_9:add(nn.ReLU(true))
|
||||
|
||||
local net_10 = nn.Sequential()
|
||||
net_10:add(nn.SpatialConvolution(320, 64, 1, 1, 1, 1))
|
||||
net_10:add(nn.SpatialConvolution(320, 128, 1, 1, 1, 1))
|
||||
net_10:add(nn.ReLU(true))
|
||||
net_10:add(nn.SpatialConvolution(64, 96, 3, 3, 1, 1, 1, 1))
|
||||
net_10:add(nn.ReLU(true))
|
||||
net_10:add(nn.SpatialConvolution(96, 96, 3, 3, 1, 1, 1, 1))
|
||||
net_10:add(nn.SpatialConvolution(128, 160, 3, 3, 1, 1, 1, 1))
|
||||
net_10:add(nn.ReLU(true))
|
||||
|
||||
local net_11 = nn.Sequential()
|
||||
net_11:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_11:add(nn.SpatialMaxPooling(3, 3, 1, 1))
|
||||
net_11:add(nn.SpatialConvolution(320, 64, 1, 1, 1, 1))
|
||||
net_11:add(nn.ReLU(true))
|
||||
net_11:add(nn.SpatialConvolution(64, 96, 3, 3, 1, 1, 1, 1))
|
||||
net_11:add(nn.ReLU(true))
|
||||
net_11:add(nn.SpatialConvolution(96, 96, 3, 3, 1, 1, 1, 1))
|
||||
net_11:add(nn.ReLU(true))
|
||||
|
||||
local net_12 = nn.Sequential()
|
||||
net_12:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_12:add(nn.SpatialMaxPooling(3, 3, 1, 1))
|
||||
|
||||
local concat_54 = nn.Concat(2)
|
||||
concat_54:add(net_12)
|
||||
concat_54:add(net_11)
|
||||
concat_54:add(net_10)
|
||||
concat_54:add(net_9)
|
||||
|
||||
net:add(concat_54)
|
||||
net:add(nn.SpatialConvolution(576, 576, 2, 2, 2, 2))
|
||||
|
||||
local net_12 = nn.Sequential()
|
||||
net_12:add(nn.SpatialConvolution(576, 224, 1, 1, 1, 1))
|
||||
net_12:add(nn.ReLU(true))
|
||||
|
||||
local net_13 = nn.Sequential()
|
||||
net_13:add(nn.SpatialConvolution(576, 64, 1, 1, 1, 1))
|
||||
net_13:add(nn.ReLU(true))
|
||||
net_13:add(nn.SpatialConvolution(64, 96, 3, 3, 1, 1, 1, 1))
|
||||
net_13:add(nn.SpatialConvolution(576, 224, 1, 1, 1, 1))
|
||||
net_13:add(nn.ReLU(true))
|
||||
|
||||
local net_14 = nn.Sequential()
|
||||
net_14:add(nn.SpatialConvolution(576, 96, 1, 1, 1, 1))
|
||||
net_14:add(nn.SpatialConvolution(576, 64, 1, 1, 1, 1))
|
||||
net_14:add(nn.ReLU(true))
|
||||
net_14:add(nn.SpatialConvolution(96, 128, 3, 3, 1, 1, 1, 1))
|
||||
net_14:add(nn.ReLU(true))
|
||||
net_14:add(nn.SpatialConvolution(128, 128, 3, 3, 1, 1, 1, 1))
|
||||
net_14:add(nn.SpatialConvolution(64, 96, 3, 3, 1, 1, 1, 1))
|
||||
net_14:add(nn.ReLU(true))
|
||||
|
||||
local net_15 = nn.Sequential()
|
||||
net_15:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_15:add(nn.SpatialAveragePooling(3, 3, 1, 1))
|
||||
net_15:add(nn.SpatialConvolution(576, 128, 1, 1, 1, 1))
|
||||
net_15:add(nn.SpatialConvolution(576, 96, 1, 1, 1, 1))
|
||||
net_15:add(nn.ReLU(true))
|
||||
net_15:add(nn.SpatialConvolution(96, 128, 3, 3, 1, 1, 1, 1))
|
||||
net_15:add(nn.ReLU(true))
|
||||
net_15:add(nn.SpatialConvolution(128, 128, 3, 3, 1, 1, 1, 1))
|
||||
net_15:add(nn.ReLU(true))
|
||||
|
||||
local net_16 = nn.Sequential()
|
||||
net_16:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_16:add(nn.SpatialAveragePooling(3, 3, 1, 1))
|
||||
net_16:add(nn.SpatialConvolution(576, 128, 1, 1, 1, 1))
|
||||
net_16:add(nn.ReLU(true))
|
||||
|
||||
local concat_72 = nn.Concat(2)
|
||||
concat_72:add(net_16)
|
||||
concat_72:add(net_15)
|
||||
concat_72:add(net_14)
|
||||
concat_72:add(net_13)
|
||||
concat_72:add(net_12)
|
||||
|
||||
net:add(concat_72)
|
||||
|
||||
local net_16 = nn.Sequential()
|
||||
net_16:add(nn.SpatialConvolution(576, 192, 1, 1, 1, 1))
|
||||
net_16:add(nn.ReLU(true))
|
||||
|
||||
local net_17 = nn.Sequential()
|
||||
net_17:add(nn.SpatialConvolution(576, 96, 1, 1, 1, 1))
|
||||
net_17:add(nn.ReLU(true))
|
||||
net_17:add(nn.SpatialConvolution(96, 128, 3, 3, 1, 1, 1, 1))
|
||||
net_17:add(nn.SpatialConvolution(576, 192, 1, 1, 1, 1))
|
||||
net_17:add(nn.ReLU(true))
|
||||
|
||||
local net_18 = nn.Sequential()
|
||||
@@ -148,31 +142,31 @@ net_18:add(nn.SpatialConvolution(576, 96, 1, 1, 1, 1))
|
||||
net_18:add(nn.ReLU(true))
|
||||
net_18:add(nn.SpatialConvolution(96, 128, 3, 3, 1, 1, 1, 1))
|
||||
net_18:add(nn.ReLU(true))
|
||||
net_18:add(nn.SpatialConvolution(128, 128, 3, 3, 1, 1, 1, 1))
|
||||
net_18:add(nn.ReLU(true))
|
||||
|
||||
local net_19 = nn.Sequential()
|
||||
net_19:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_19:add(nn.SpatialAveragePooling(3, 3, 1, 1))
|
||||
net_19:add(nn.SpatialConvolution(576, 128, 1, 1, 1, 1))
|
||||
net_19:add(nn.SpatialConvolution(576, 96, 1, 1, 1, 1))
|
||||
net_19:add(nn.ReLU(true))
|
||||
net_19:add(nn.SpatialConvolution(96, 128, 3, 3, 1, 1, 1, 1))
|
||||
net_19:add(nn.ReLU(true))
|
||||
net_19:add(nn.SpatialConvolution(128, 128, 3, 3, 1, 1, 1, 1))
|
||||
net_19:add(nn.ReLU(true))
|
||||
|
||||
local net_20 = nn.Sequential()
|
||||
net_20:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_20:add(nn.SpatialAveragePooling(3, 3, 1, 1))
|
||||
net_20:add(nn.SpatialConvolution(576, 128, 1, 1, 1, 1))
|
||||
net_20:add(nn.ReLU(true))
|
||||
|
||||
local concat_89 = nn.Concat(2)
|
||||
concat_89:add(net_20)
|
||||
concat_89:add(net_19)
|
||||
concat_89:add(net_18)
|
||||
concat_89:add(net_17)
|
||||
concat_89:add(net_16)
|
||||
|
||||
net:add(concat_89)
|
||||
|
||||
local net_20 = nn.Sequential()
|
||||
net_20:add(nn.SpatialConvolution(576, 160, 1, 1, 1, 1))
|
||||
net_20:add(nn.ReLU(true))
|
||||
|
||||
local net_21 = nn.Sequential()
|
||||
net_21:add(nn.SpatialConvolution(576, 128, 1, 1, 1, 1))
|
||||
net_21:add(nn.ReLU(true))
|
||||
net_21:add(nn.SpatialConvolution(128, 160, 3, 3, 1, 1, 1, 1))
|
||||
net_21:add(nn.SpatialConvolution(576, 160, 1, 1, 1, 1))
|
||||
net_21:add(nn.ReLU(true))
|
||||
|
||||
local net_22 = nn.Sequential()
|
||||
@@ -180,162 +174,168 @@ net_22:add(nn.SpatialConvolution(576, 128, 1, 1, 1, 1))
|
||||
net_22:add(nn.ReLU(true))
|
||||
net_22:add(nn.SpatialConvolution(128, 160, 3, 3, 1, 1, 1, 1))
|
||||
net_22:add(nn.ReLU(true))
|
||||
net_22:add(nn.SpatialConvolution(160, 160, 3, 3, 1, 1, 1, 1))
|
||||
net_22:add(nn.ReLU(true))
|
||||
|
||||
local net_23 = nn.Sequential()
|
||||
net_23:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_23:add(nn.SpatialAveragePooling(3, 3, 1, 1))
|
||||
net_23:add(nn.SpatialConvolution(576, 96, 1, 1, 1, 1))
|
||||
net_23:add(nn.SpatialConvolution(576, 128, 1, 1, 1, 1))
|
||||
net_23:add(nn.ReLU(true))
|
||||
net_23:add(nn.SpatialConvolution(128, 160, 3, 3, 1, 1, 1, 1))
|
||||
net_23:add(nn.ReLU(true))
|
||||
net_23:add(nn.SpatialConvolution(160, 160, 3, 3, 1, 1, 1, 1))
|
||||
net_23:add(nn.ReLU(true))
|
||||
|
||||
local concat_106 = nn.Concat(2)
|
||||
concat_106:add(net_23)
|
||||
concat_106:add(net_22)
|
||||
concat_106:add(net_21)
|
||||
concat_106:add(net_20)
|
||||
|
||||
net:add(concat_106)
|
||||
|
||||
local net_24 = nn.Sequential()
|
||||
net_24:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_24:add(nn.SpatialAveragePooling(3, 3, 1, 1))
|
||||
net_24:add(nn.SpatialConvolution(576, 96, 1, 1, 1, 1))
|
||||
net_24:add(nn.ReLU(true))
|
||||
|
||||
local concat_106 = nn.Concat(2)
|
||||
concat_106:add(net_24)
|
||||
concat_106:add(net_23)
|
||||
concat_106:add(net_22)
|
||||
concat_106:add(net_21)
|
||||
|
||||
net:add(concat_106)
|
||||
|
||||
local net_25 = nn.Sequential()
|
||||
net_25:add(nn.SpatialConvolution(576, 128, 1, 1, 1, 1))
|
||||
net_25:add(nn.ReLU(true))
|
||||
net_25:add(nn.SpatialConvolution(128, 192, 3, 3, 1, 1, 1, 1))
|
||||
net_25:add(nn.SpatialConvolution(576, 96, 1, 1, 1, 1))
|
||||
net_25:add(nn.ReLU(true))
|
||||
|
||||
local net_26 = nn.Sequential()
|
||||
net_26:add(nn.SpatialConvolution(576, 160, 1, 1, 1, 1))
|
||||
net_26:add(nn.SpatialConvolution(576, 128, 1, 1, 1, 1))
|
||||
net_26:add(nn.ReLU(true))
|
||||
net_26:add(nn.SpatialConvolution(160, 192, 3, 3, 1, 1, 1, 1))
|
||||
net_26:add(nn.ReLU(true))
|
||||
net_26:add(nn.SpatialConvolution(192, 192, 3, 3, 1, 1, 1, 1))
|
||||
net_26:add(nn.SpatialConvolution(128, 192, 3, 3, 1, 1, 1, 1))
|
||||
net_26:add(nn.ReLU(true))
|
||||
|
||||
local net_27 = nn.Sequential()
|
||||
net_27:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_27:add(nn.SpatialAveragePooling(3, 3, 1, 1))
|
||||
net_27:add(nn.SpatialConvolution(576, 96, 1, 1, 1, 1))
|
||||
net_27:add(nn.SpatialConvolution(576, 160, 1, 1, 1, 1))
|
||||
net_27:add(nn.ReLU(true))
|
||||
net_27:add(nn.SpatialConvolution(160, 192, 3, 3, 1, 1, 1, 1))
|
||||
net_27:add(nn.ReLU(true))
|
||||
net_27:add(nn.SpatialConvolution(192, 192, 3, 3, 1, 1, 1, 1))
|
||||
net_27:add(nn.ReLU(true))
|
||||
|
||||
local net_28 = nn.Sequential()
|
||||
net_28:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_28:add(nn.SpatialAveragePooling(3, 3, 1, 1))
|
||||
net_28:add(nn.SpatialConvolution(576, 96, 1, 1, 1, 1))
|
||||
net_28:add(nn.ReLU(true))
|
||||
|
||||
local concat_123 = nn.Concat(2)
|
||||
concat_123:add(net_28)
|
||||
concat_123:add(net_27)
|
||||
concat_123:add(net_26)
|
||||
concat_123:add(net_25)
|
||||
concat_123:add(net_24)
|
||||
|
||||
net:add(concat_123)
|
||||
|
||||
local net_28 = nn.Sequential()
|
||||
net_28:add(nn.SpatialConvolution(576, 192, 1, 1, 1, 1))
|
||||
net_28:add(nn.ReLU(true))
|
||||
net_28:add(nn.SpatialConvolution(192, 256, 3, 3, 1, 1, 1, 1))
|
||||
net_28:add(nn.ReLU(true))
|
||||
net_28:add(nn.SpatialConvolution(256, 256, 3, 3, 1, 1, 1, 1))
|
||||
net_28:add(nn.ReLU(true))
|
||||
|
||||
local net_29 = nn.Sequential()
|
||||
net_29:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_29:add(nn.SpatialMaxPooling(3, 3, 1, 1))
|
||||
net_29:add(nn.SpatialConvolution(576, 192, 1, 1, 1, 1))
|
||||
net_29:add(nn.ReLU(true))
|
||||
net_29:add(nn.SpatialConvolution(192, 256, 3, 3, 1, 1, 1, 1))
|
||||
net_29:add(nn.ReLU(true))
|
||||
net_29:add(nn.SpatialConvolution(256, 256, 3, 3, 1, 1, 1, 1))
|
||||
net_29:add(nn.ReLU(true))
|
||||
|
||||
local net_30 = nn.Sequential()
|
||||
net_30:add(nn.SpatialAveragePooling(5, 5, 3, 3))
|
||||
net_30:add(nn.SpatialConvolution(576, 128, 1, 1, 1, 1))
|
||||
net_30:add(nn.View())
|
||||
net_30:add(nn.Linear(2048, 768))
|
||||
net_30:add(nn.ReLU())
|
||||
net_30:add(nn.Linear(768, 4))
|
||||
net_30:add(nn.LogSoftMax())
|
||||
net_30:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_30:add(nn.SpatialMaxPooling(3, 3, 1, 1))
|
||||
|
||||
local net_31 = nn.Sequential()
|
||||
net_31:add(nn.SpatialAveragePooling(5, 5, 3, 3))
|
||||
net_31:add(nn.SpatialConvolution(576, 128, 1, 1, 1, 1))
|
||||
net_31:add(nn.ReLU(true))
|
||||
net_31:add(nn.SpatialConvolution(128, 192, 3, 3, 1, 1, 1, 1))
|
||||
net_31:add(nn.ReLU(true))
|
||||
net_31:add(nn.View())
|
||||
net_31:add(nn.Linear(2048, 768))
|
||||
net_31:add(nn.ReLU())
|
||||
net_31:add(nn.Linear(768, 4))
|
||||
net_31:add(nn.LogSoftMax())
|
||||
|
||||
local net_32 = nn.Sequential()
|
||||
net_32:add(nn.SpatialConvolution(576, 128, 1, 1, 1, 1))
|
||||
net_32:add(nn.ReLU(true))
|
||||
net_32:add(nn.SpatialConvolution(128, 192, 3, 3, 1, 1, 1, 1))
|
||||
net_32:add(nn.ReLU(true))
|
||||
|
||||
local concat_143 = nn.Concat(2)
|
||||
concat_143:add(net_31)
|
||||
concat_143:add(net_32)
|
||||
concat_143:add(net_30)
|
||||
concat_143:add(net_29)
|
||||
concat_143:add(net_28)
|
||||
|
||||
net:add(concat_143)
|
||||
local net_32 = nn.Sequential()
|
||||
net_32:add(nn.SpatialConvolution(1024, 1024, 2, 2, 2, 2))
|
||||
|
||||
local net_33 = nn.Sequential()
|
||||
net_33:add(nn.SpatialConvolution(1024, 352, 1, 1, 1, 1))
|
||||
net_33:add(nn.ReLU(true))
|
||||
net_33:add(nn.SpatialConvolution(1024, 1024, 2, 2, 2, 2))
|
||||
|
||||
local net_34 = nn.Sequential()
|
||||
net_34:add(nn.SpatialConvolution(1024, 192, 1, 1, 1, 1))
|
||||
net_34:add(nn.ReLU(true))
|
||||
net_34:add(nn.SpatialConvolution(192, 320, 3, 3, 1, 1, 1, 1))
|
||||
net_34:add(nn.SpatialConvolution(1024, 352, 1, 1, 1, 1))
|
||||
net_34:add(nn.ReLU(true))
|
||||
|
||||
local net_35 = nn.Sequential()
|
||||
net_35:add(nn.SpatialConvolution(1024, 160, 1, 1, 1, 1))
|
||||
net_35:add(nn.SpatialConvolution(1024, 192, 1, 1, 1, 1))
|
||||
net_35:add(nn.ReLU(true))
|
||||
net_35:add(nn.SpatialConvolution(160, 224, 3, 3, 1, 1, 1, 1))
|
||||
net_35:add(nn.ReLU(true))
|
||||
net_35:add(nn.SpatialConvolution(224, 224, 3, 3, 1, 1, 1, 1))
|
||||
net_35:add(nn.SpatialConvolution(192, 320, 3, 3, 1, 1, 1, 1))
|
||||
net_35:add(nn.ReLU(true))
|
||||
|
||||
local net_36 = nn.Sequential()
|
||||
net_36:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_36:add(nn.SpatialAveragePooling(3, 3, 1, 1))
|
||||
net_36:add(nn.SpatialConvolution(1024, 128, 1, 1, 1, 1))
|
||||
net_36:add(nn.SpatialConvolution(1024, 160, 1, 1, 1, 1))
|
||||
net_36:add(nn.ReLU(true))
|
||||
net_36:add(nn.SpatialConvolution(160, 224, 3, 3, 1, 1, 1, 1))
|
||||
net_36:add(nn.ReLU(true))
|
||||
net_36:add(nn.SpatialConvolution(224, 224, 3, 3, 1, 1, 1, 1))
|
||||
net_36:add(nn.ReLU(true))
|
||||
|
||||
local net_37 = nn.Sequential()
|
||||
net_37:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_37:add(nn.SpatialAveragePooling(3, 3, 1, 1))
|
||||
net_37:add(nn.SpatialConvolution(1024, 128, 1, 1, 1, 1))
|
||||
net_37:add(nn.ReLU(true))
|
||||
|
||||
local concat_161 = nn.Concat(2)
|
||||
concat_161:add(net_37)
|
||||
concat_161:add(net_36)
|
||||
concat_161:add(net_35)
|
||||
concat_161:add(net_34)
|
||||
concat_161:add(net_33)
|
||||
|
||||
net_32:add(concat_161)
|
||||
|
||||
local net_37 = nn.Sequential()
|
||||
net_37:add(nn.SpatialConvolution(1024, 352, 1, 1, 1, 1))
|
||||
net_37:add(nn.ReLU(true))
|
||||
net_33:add(concat_161)
|
||||
|
||||
local net_38 = nn.Sequential()
|
||||
net_38:add(nn.SpatialConvolution(1024, 192, 1, 1, 1, 1))
|
||||
net_38:add(nn.ReLU(true))
|
||||
net_38:add(nn.SpatialConvolution(192, 320, 3, 3, 1, 1, 1, 1))
|
||||
net_38:add(nn.SpatialConvolution(1024, 352, 1, 1, 1, 1))
|
||||
net_38:add(nn.ReLU(true))
|
||||
|
||||
local net_39 = nn.Sequential()
|
||||
net_39:add(nn.SpatialConvolution(1024, 192, 1, 1, 1, 1))
|
||||
net_39:add(nn.ReLU(true))
|
||||
net_39:add(nn.SpatialConvolution(192, 224, 3, 3, 1, 1, 1, 1))
|
||||
net_39:add(nn.ReLU(true))
|
||||
net_39:add(nn.SpatialConvolution(224, 224, 3, 3, 1, 1, 1, 1))
|
||||
net_39:add(nn.SpatialConvolution(192, 320, 3, 3, 1, 1, 1, 1))
|
||||
net_39:add(nn.ReLU(true))
|
||||
|
||||
local net_40 = nn.Sequential()
|
||||
net_40:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_40:add(nn.SpatialMaxPooling(3, 3, 1, 1))
|
||||
net_40:add(nn.SpatialConvolution(1024, 128, 1, 1, 1, 1))
|
||||
net_40:add(nn.SpatialConvolution(1024, 192, 1, 1, 1, 1))
|
||||
net_40:add(nn.ReLU(true))
|
||||
net_40:add(nn.SpatialConvolution(192, 224, 3, 3, 1, 1, 1, 1))
|
||||
net_40:add(nn.ReLU(true))
|
||||
net_40:add(nn.SpatialConvolution(224, 224, 3, 3, 1, 1, 1, 1))
|
||||
net_40:add(nn.ReLU(true))
|
||||
|
||||
local net_41 = nn.Sequential()
|
||||
net_41:add(nn.SpatialZeroPadding(1, 1, 1, 1))
|
||||
net_41:add(nn.SpatialMaxPooling(3, 3, 1, 1))
|
||||
net_41:add(nn.SpatialConvolution(1024, 128, 1, 1, 1, 1))
|
||||
net_41:add(nn.ReLU(true))
|
||||
|
||||
local concat_178 = nn.Concat(2)
|
||||
concat_178:add(net_41)
|
||||
concat_178:add(net_40)
|
||||
concat_178:add(net_39)
|
||||
concat_178:add(net_38)
|
||||
concat_178:add(net_37)
|
||||
|
||||
net_32:add(concat_178)
|
||||
net_32:add(nn.SpatialAveragePooling(7, 7, 1, 1))
|
||||
net_32:add(nn.View())
|
||||
net_32:add(nn.Linear(1024, 4))
|
||||
net_32:add(nn.LogSoftMax())
|
||||
net_33:add(concat_178)
|
||||
net_33:add(nn.SpatialAveragePooling(7, 7, 1, 1))
|
||||
net_33:add(nn.View())
|
||||
net_33:add(nn.Linear(1024, 4))
|
||||
net_33:add(nn.LogSoftMax())
|
||||
|
||||
local concat_183 = nn.Concat(2)
|
||||
concat_183:add(net_32)
|
||||
concat_183:add(net_30)
|
||||
concat_183:add(net_33)
|
||||
concat_183:add(net_31)
|
||||
|
||||
net:add(concat_183)
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
require 'nn'
|
||||
require 'rnn'
|
||||
|
||||
local net = nn.Sequential()
|
||||
net:add(nn.Add(nil, true))
|
||||
|
||||
return net
|
||||
+22
-1
@@ -230,6 +230,13 @@
|
||||
"panel": "src/visualizers/panels/ExecutionIndex",
|
||||
"secondary": false,
|
||||
"widget": "src/visualizers/widgets/ExecutionIndex"
|
||||
},
|
||||
"WorkerHeader": {
|
||||
"src": "panels/WorkerHeader/WorkerHeaderPanel",
|
||||
"title": "WorkerHeader",
|
||||
"panel": "src/visualizers/panels/WorkerHeader",
|
||||
"secondary": false,
|
||||
"widget": "src/visualizers/widgets/WorkerHeader"
|
||||
}
|
||||
},
|
||||
"addons": {},
|
||||
@@ -280,6 +287,19 @@
|
||||
},
|
||||
"xor": {
|
||||
"src": "src/seeds/xor"
|
||||
},
|
||||
"devProject": {
|
||||
"src": "src/seeds/devProject"
|
||||
}
|
||||
},
|
||||
"routers": {
|
||||
"JobLogsAPI": {
|
||||
"src": "src/routers/JobLogsAPI",
|
||||
"mount": "execution/logs"
|
||||
},
|
||||
"JobOriginAPI": {
|
||||
"src": "src/routers/JobOriginAPI",
|
||||
"mount": "job/origins"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -337,6 +357,7 @@
|
||||
"path": "node_modules/webgme-easydag/src/decorators/EllipseDecorator"
|
||||
}
|
||||
},
|
||||
"seeds": {}
|
||||
"seeds": {},
|
||||
"routers": {}
|
||||
}
|
||||
}
|
||||
Referência em uma Nova Issue
Bloquear um usuário