Repository: ignite
Updated Branches:
  refs/heads/ignite-843-rc1 5427b87d2 -> bd7b27d3f


IGNITE-1200 WIP on IGFS support.


Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/87631e47
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/87631e47
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/87631e47

Branch: refs/heads/ignite-843-rc1
Commit: 87631e476d2b9881c063ecab8b43530af83914c2
Parents: a2e00c2
Author: Alexey Kuznetsov <[email protected]>
Authored: Tue Oct 20 17:42:25 2015 +0700
Committer: Alexey Kuznetsov <[email protected]>
Committed: Tue Oct 20 17:42:25 2015 +0700

----------------------------------------------------------------------
 modules/control-center-web/src/main/js/app.js   |   2 +
 .../src/main/js/controllers/common-module.js    |   9 +-
 .../src/main/js/controllers/igfs-controller.js  | 351 +++++++++++++++++++
 .../src/main/js/controllers/models/caches.json  |   6 +-
 .../main/js/controllers/models/clusters.json    |  31 +-
 .../src/main/js/controllers/models/igfs.json    | 154 ++++++++
 .../main/js/controllers/models/metadata.json    |   6 +-
 .../src/main/js/controllers/models/summary.json |   6 +-
 modules/control-center-web/src/main/js/db.js    |  32 ++
 .../src/main/js/routes/igfs.js                  | 169 +++++++++
 .../src/main/js/views/configuration/igfs.jade   |  46 +++
 .../main/js/views/configuration/sidebar.jade    |   3 +-
 12 files changed, 798 insertions(+), 17 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ignite/blob/87631e47/modules/control-center-web/src/main/js/app.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/app.js 
b/modules/control-center-web/src/main/js/app.js
index 3beb85f..2a0dc14 100644
--- a/modules/control-center-web/src/main/js/app.js
+++ b/modules/control-center-web/src/main/js/app.js
@@ -33,6 +33,7 @@ var clustersRouter = require('./routes/clusters');
 var cachesRouter = require('./routes/caches');
 var metadataRouter = require('./routes/metadata');
 var presetsRouter = require('./routes/presets');
+var igfsRouter = require('./routes/igfs');
 var summary = require('./routes/summary');
 var adminRouter = require('./routes/admin');
 var profileRouter = require('./routes/profile');
@@ -153,6 +154,7 @@ app.use('/configuration/clusters', clustersRouter);
 app.use('/configuration/caches', cachesRouter);
 app.use('/configuration/metadata', metadataRouter);
 app.use('/configuration/presets', presetsRouter);
+app.use('/configuration/igfs', igfsRouter);
 app.use('/configuration/summary', summary);
 
 app.use('/notebooks', mustAuthenticated, notebooksRoutes);

http://git-wip-us.apache.org/repos/asf/ignite/blob/87631e47/modules/control-center-web/src/main/js/controllers/common-module.js
----------------------------------------------------------------------
diff --git 
a/modules/control-center-web/src/main/js/controllers/common-module.js 
b/modules/control-center-web/src/main/js/controllers/common-module.js
index 1330cbd..664b67d 100644
--- a/modules/control-center-web/src/main/js/controllers/common-module.js
+++ b/modules/control-center-web/src/main/js/controllers/common-module.js
@@ -1870,10 +1870,11 @@ consoleModule.directive('onClickFocus', function 
($focus) {
 consoleModule.controller('activeLink', [
     '$scope', function ($scope) {
         $scope.configurationDropdown = [
-            { "text": "Clusters", "href": "/configuration/clusters" },
-            { "text": "Caches", "href": "/configuration/caches" },
-            { "text": "Metadata", "href": "/configuration/metadata" },
-            { "text": "Summary", "href": "/configuration/summary" }
+            {"text": "Clusters", "href": "/configuration/clusters"},
+            {"text": "Caches", "href": "/configuration/caches"},
+            {"text": "Metadata", "href": "/configuration/metadata"},
+            {"text": "IGFS", "href": "/configuration/igfs"},
+            {"text": "Summary", "href": "/configuration/summary"}
         ];
 
         $scope.isActive = function (path) {

http://git-wip-us.apache.org/repos/asf/ignite/blob/87631e47/modules/control-center-web/src/main/js/controllers/igfs-controller.js
----------------------------------------------------------------------
diff --git 
a/modules/control-center-web/src/main/js/controllers/igfs-controller.js 
b/modules/control-center-web/src/main/js/controllers/igfs-controller.js
new file mode 100644
index 0000000..785545f
--- /dev/null
+++ b/modules/control-center-web/src/main/js/controllers/igfs-controller.js
@@ -0,0 +1,351 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Controller for IGFS screen.
+consoleModule.controller('igfsController', [
+    '$scope', '$controller', '$filter', '$http', '$timeout', '$common', 
'$focus', '$confirm', '$message', '$clone', '$table', '$preview', '$loading', 
'$unsavedChangesGuard',
+    function ($scope, $controller, $filter, $http, $timeout, $common, $focus, 
$confirm, $message, $clone, $table, $preview, $loading, $unsavedChangesGuard) {
+            $unsavedChangesGuard.install($scope);
+
+            // Initialize the super class and extend it.
+            angular.extend(this, $controller('save-remove', {$scope: $scope}));
+
+            $scope.ui = $common.formUI();
+
+            $scope.showMoreInfo = $message.message;
+
+            $scope.joinTip = $common.joinTip;
+            $scope.getModel = $common.getModel;
+            $scope.javaBuildInClasses = $common.javaBuildInClasses;
+            $scope.compactJavaName = $common.compactJavaName;
+            $scope.saveBtnTipText = $common.saveBtnTipText;
+
+            $scope.tableVisibleRow = $table.tableVisibleRow;
+            $scope.tableReset = $table.tableReset;
+            $scope.tableNewItem = $table.tableNewItem;
+            $scope.tableNewItemActive = $table.tableNewItemActive;
+            $scope.tableEditing = $table.tableEditing;
+            $scope.tableStartEdit = $table.tableStartEdit;
+            $scope.tableRemove = function (item, field, index) {
+                $table.tableRemove(item, field, index);
+            };
+
+            $scope.tableSimpleSave = $table.tableSimpleSave;
+            $scope.tableSimpleSaveVisible = $table.tableSimpleSaveVisible;
+            $scope.tableSimpleUp = $table.tableSimpleUp;
+            $scope.tableSimpleDown = $table.tableSimpleDown;
+            $scope.tableSimpleDownVisible = $table.tableSimpleDownVisible;
+
+            $scope.tablePairSave = $table.tablePairSave;
+            $scope.tablePairSaveVisible = $table.tablePairSaveVisible;
+
+            var previews = [];
+
+            $scope.previewInit = function (preview) {
+                previews.push(preview);
+
+                $preview.previewInit(preview);
+            };
+
+            $scope.previewChanged = $preview.previewChanged;
+
+            $scope.hidePopover = $common.hidePopover;
+
+            var showPopoverMessage = $common.showPopoverMessage;
+
+            $scope.igfsModes = $common.mkOptions(['PRIMARY', 'PROXY', 
'DUAL_SYNC', 'DUAL_ASYNC']);
+
+            $scope.toggleExpanded = function () {
+                $scope.ui.expanded = !$scope.ui.expanded;
+
+                $common.hidePopover();
+            };
+
+            $scope.panels = {activePanels: [0]};
+
+            $scope.general = [];
+            $scope.advanced = [];
+            $scope.igfss = [];
+            $scope.clusters = [];
+
+            $scope.preview = {
+                general: {xml: '', java: '', allDefaults: true},
+                ipc: {xml: '', java: '', allDefaults: true},
+                fragmentizer: {xml: '', java: '', allDefaults: true},
+                misc: {xml: '', java: '', allDefaults: true}
+            };
+
+            $scope.required = function (field) {
+                return false;
+            };
+
+            $scope.tableSimpleValid = function (item, field, fx, index) {
+                return true;
+            };
+
+            $scope.tablePairValid = function (item, field, index) {
+                return true;
+            };
+
+            function selectFirstItem() {
+                if ($scope.igfss.length > 0)
+                    $scope.selectItem($scope.igfss[0]);
+            }
+
+            $loading.start('loadingIgfsScreen');
+
+            // When landing on the page, get IGFSs and show them.
+            $http.post('igfs/list')
+                .success(function (data) {
+                    $scope.spaces = data.spaces;
+                    $scope.igfss = data.igfss;
+                    $scope.clusters = data.clusters;
+
+                    // Load page descriptor.
+                    $http.get('/models/igfs.json')
+                        .success(function (data) {
+                            $scope.screenTip = data.screenTip;
+                            $scope.moreInfo = data.moreInfo;
+                            $scope.general = data.general;
+                            $scope.advanced = data.advanced;
+
+                            $scope.ui.addGroups(data.general, data.advanced);
+
+                            if ($common.getQueryVariable('new'))
+                                $scope.createItem();
+                            else {
+                                var lastSelectedIgfs = 
angular.fromJson(sessionStorage.lastSelectedIgfs);
+
+                                if (lastSelectedIgfs) {
+                                    var idx = _.findIndex($scope.igfss, 
function (igfs) {
+                                        return igfs._id == lastSelectedIgfs;
+                                    });
+
+                                    if (idx >= 0)
+                                        $scope.selectItem($scope.igfss[idx]);
+                                    else {
+                                        
sessionStorage.removeItem('lastSelectedIgfs');
+
+                                        selectFirstItem();
+                                    }
+
+                                }
+                                else
+                                    selectFirstItem();
+                            }
+
+                            $scope.$watch('backupItem', function (val) {
+                                if (val) {
+                                    var srcItem = $scope.selectedItem ? 
$scope.selectedItem : prepareNewItem();
+
+                                    $scope.ui.checkDirty(val, srcItem);
+
+                                    var varName = 
$commonUtils.toJavaName('igfs', val.name);
+
+                                    $scope.preview.general.xml = 
$generatorXml.igfs(val).asString();
+                                    $scope.preview.general.java = 
$generatorJava.igfs(val, varName).asString();
+                                    $scope.preview.general.allDefaults = 
$common.isEmptyString($scope.preview.general.xml);
+                                }
+                            }, true);
+                        })
+                        .error(function (errMsg) {
+                            $common.showError(errMsg);
+                        });
+                })
+                .error(function (errMsg) {
+                    $common.showError(errMsg);
+                })
+                .finally(function () {
+                    $scope.ui.ready = true;
+                    $loading.finish('loadingIgfsScreen');
+                });
+
+            $scope.selectItem = function (item, backup) {
+                function selectItem() {
+                    $table.tableReset();
+
+                    $scope.selectedItem = angular.copy(item);
+
+                    try {
+                        if (item)
+                            sessionStorage.lastSelectedIgfs = 
angular.toJson(item._id);
+                        else
+                            sessionStorage.removeItem('lastSelectedIgfs');
+                    }
+                    catch (error) { }
+
+                    _.forEach(previews, function(preview) {
+                        preview.attractAttention = false;
+                    });
+
+                    if (backup)
+                        $scope.backupItem = backup;
+                    else if (item)
+                        $scope.backupItem = angular.copy(item);
+                    else
+                        $scope.backupItem = undefined;
+                }
+
+                $common.confirmUnsavedChanges($scope.ui.isDirty(), selectItem);
+
+                $scope.ui.formTitle = $common.isDefined($scope.backupItem) && 
$scope.backupItem._id ?
+                    'Selected IGFS: ' + $scope.backupItem.name : 'New IGFS';
+            };
+
+            function prepareNewItem() {
+                return {
+                    space: $scope.spaces[0]._id,
+                    mode: 'PRIMARY'
+                }
+            }
+
+            // Add new IGFS.
+            $scope.createItem = function () {
+                $table.tableReset();
+
+                $timeout(function () {
+                    $common.ensureActivePanel($scope.panels, 'general', 
'igfsName');
+                });
+
+                $scope.selectItem(undefined, prepareNewItem());
+            };
+
+            // Check IGFS logical consistency.
+            function validate(item) {
+                if ($common.isEmptyString(item.name))
+                    return showPopoverMessage($scope.panels, 'general', 
'igfsName', 'Name should not be empty');
+
+                return true;
+            }
+
+            // Save IGFS into database.
+            function save(item) {
+                $http.post('igfs/save', item)
+                    .success(function (_id) {
+                        $scope.ui.markPristine();
+
+                        var idx = _.findIndex($scope.igfss, function (igfs) {
+                            return igfs._id == _id;
+                        });
+
+                        if (idx >= 0)
+                            angular.extend($scope.igfss[idx], item);
+                        else {
+                            item._id = _id;
+                            $scope.igfss.push(item);
+                        }
+
+                        $scope.selectItem(item);
+
+                        $common.showInfo('IGFS "' + item.name + '" saved.');
+                    })
+                    .error(function (errMsg) {
+                        $common.showError(errMsg);
+                    });
+            }
+
+            // Save IGFS.
+            $scope.saveItem = function () {
+                $table.tableReset();
+
+                var item = $scope.backupItem;
+
+                if (validate(item))
+                    save(item);
+            };
+
+            // Save IGFS with new name.
+            $scope.cloneItem = function () {
+                $table.tableReset();
+
+                if (validate($scope.backupItem))
+                    $clone.confirm($scope.backupItem.name).then(function 
(newName) {
+                        var item = angular.copy($scope.backupItem);
+
+                        item._id = undefined;
+                        item.name = newName;
+
+                        save(item);
+                    });
+            };
+
+            // Remove IGFS from db.
+            $scope.removeItem = function () {
+                $table.tableReset();
+
+                var selectedItem = $scope.selectedItem;
+
+                $confirm.confirm('Are you sure you want to remove IGFS: "' + 
selectedItem.name + '"?')
+                    .then(function () {
+                            var _id = selectedItem._id;
+
+                            $http.post('igfs/remove', {_id: _id})
+                                .success(function () {
+                                    $common.showInfo('IGFS has been removed: ' 
+ selectedItem.name);
+
+                                    var igfss = $scope.igfss;
+
+                                    var idx = _.findIndex(igfss, function 
(igfs) {
+                                        return igfs._id == _id;
+                                    });
+
+                                    if (idx >= 0) {
+                                        igfss.splice(idx, 1);
+
+                                        if (igfss.length > 0)
+                                            $scope.selectItem(igfss[0]);
+                                        else
+                                            $scope.selectItem(undefined, 
undefined);
+                                    }
+                                })
+                                .error(function (errMsg) {
+                                    $common.showError(errMsg);
+                                });
+                    });
+            };
+
+            // Remove all igfss from db.
+            $scope.removeAllItems = function () {
+                $table.tableReset();
+
+                $confirm.confirm('Are you sure you want to remove all IGFS?')
+                    .then(function () {
+                            $http.post('igfs/remove/all')
+                                .success(function () {
+                                    $common.showInfo('All IGFS have been 
removed');
+
+                                    $scope.igfss = [];
+
+                                    $scope.selectItem(undefined, undefined);
+                                })
+                                .error(function (errMsg) {
+                                    $common.showError(errMsg);
+                                });
+                    });
+            };
+
+            $scope.resetItem = function (group) {
+                var resetTo = $scope.selectedItem;
+
+                if (!$common.isDefined(resetTo))
+                    resetTo = prepareNewItem();
+
+                $common.resetItem($scope.backupItem, resetTo, $scope.general, 
group);
+                $common.resetItem($scope.backupItem, resetTo, $scope.advanced, 
group);
+            }
+        }]
+);

http://git-wip-us.apache.org/repos/asf/ignite/blob/87631e47/modules/control-center-web/src/main/js/controllers/models/caches.json
----------------------------------------------------------------------
diff --git 
a/modules/control-center-web/src/main/js/controllers/models/caches.json 
b/modules/control-center-web/src/main/js/controllers/models/caches.json
index 087cb1b..93a6ef3 100644
--- a/modules/control-center-web/src/main/js/controllers/models/caches.json
+++ b/modules/control-center-web/src/main/js/controllers/models/caches.json
@@ -15,10 +15,10 @@
     ]
   },
   "moreInfo": {
-    "title": "Caches page",
-    "content": ["Manage you cluster's caches on current page.",
+    "title": "Caches screen",
+    "content": ["Manage you cluster's caches on current screen.",
       "Caches can be linked with specified <a 
href='/configuration/clusters'>clusters</a> and <a 
href='/configuration/metadata'>metadata</a>",
-      "Generated cluster with caches configuration available on <a 
href='/configuration/summary'>summary</a> page."]
+      "Generated cluster with caches configuration available on <a 
href='/configuration/summary'>summary</a> screen."]
   },
   "general": [
     {

http://git-wip-us.apache.org/repos/asf/ignite/blob/87631e47/modules/control-center-web/src/main/js/controllers/models/clusters.json
----------------------------------------------------------------------
diff --git 
a/modules/control-center-web/src/main/js/controllers/models/clusters.json 
b/modules/control-center-web/src/main/js/controllers/models/clusters.json
index 7baaf53..59ca422 100644
--- a/modules/control-center-web/src/main/js/controllers/models/clusters.json
+++ b/modules/control-center-web/src/main/js/controllers/models/clusters.json
@@ -13,9 +13,9 @@
     ]
   },
   "moreInfo": {
-    "title": "Clusters page",
-    "content": ["Manage you clusters on current page.",
-      "Generated clusters configuration available on <a 
href='/configuration/summary'>summary</a> page."]
+    "title": "Clusters screen",
+    "content": ["Manage you clusters on current screen.",
+      "Generated clusters configuration available on <a 
href='/configuration/summary'>summary</a> screen."]
   },
   "general": [
     {
@@ -1031,6 +1031,31 @@
       ]
     },
     {
+      "label": "IGFS",
+      "group": "igfs",
+      "tip": [
+        "IGFS (Ignite In-Memory File System) configurations"
+      ],
+      "fields": [
+        {
+          "label": "IGFS",
+          "id": "igfs",
+          "type": "dropdown-multiple",
+          "model": "igfs",
+          "placeholder": "Choose IGFS",
+          "placeholderEmpty": "No IGFS configured",
+          "items": "igfs",
+          "tip": [
+            "Select IGFS to start in cluster or add a new IGFS"
+          ],
+          "addLink": {
+            "label": "Add cache(s)",
+            "ref": "/configuration/igfs?new"
+          }
+        }
+      ]
+    },
+    {
       "label": "Marshaller",
       "group": "marshaller",
       "tip": [

http://git-wip-us.apache.org/repos/asf/ignite/blob/87631e47/modules/control-center-web/src/main/js/controllers/models/igfs.json
----------------------------------------------------------------------
diff --git 
a/modules/control-center-web/src/main/js/controllers/models/igfs.json 
b/modules/control-center-web/src/main/js/controllers/models/igfs.json
new file mode 100644
index 0000000..7891bff
--- /dev/null
+++ b/modules/control-center-web/src/main/js/controllers/models/igfs.json
@@ -0,0 +1,154 @@
+{
+  "screenTip": {
+    "workflowTitle": "On This Screen:",
+    "workflowContent": [
+      "Configure IGFS file systems",
+      "more-info"
+    ],
+    "whatsNextTitle": "Next Steps:",
+    "whatsNextContent": [
+      "Continue to <a href='/configuration/summary'>Summary</a>",
+      "Back to <a href='/configuration/clusters'>Clusters</a>"
+    ]
+  },
+  "moreInfo": {
+    "title": "IGFS screen",
+    "content": [
+      "Manage you IGFS file systems on current screen.",
+      "IGFS can be assigned to specified <a 
href='/configuration/clusters'>clusters</a>.",
+      "Generated cluster with IGFS available on <a 
href='/configuration/summary'>summary</a> screen."
+    ]
+  },
+  "general": [
+    {
+      "label": "General",
+      "group": "general",
+      "tip": [
+        "IGFS properties"
+      ],
+      "fields": [
+        {
+          "label": "Name",
+          "id": "igfsName",
+          "type": "text",
+          "model": "name",
+          "required": true,
+          "placeholder": "Input name"
+        },
+        {
+          "label": "Block size",
+          "id": "BlockSize",
+          "type": "number",
+          "model": "blockSize",
+          "placeholder": "65536",
+          "tip": [
+            "File's data block size (bytes)"
+          ]
+        },
+        {
+          "label": "Stream buffer size",
+          "id": "streamBufferSize",
+          "type": "number",
+          "model": "streamBufferSize"
+        },
+        {
+          "label": "DefaultMode"
+        },
+        {
+          "label": "MaxSpaceSize"
+        },
+        {
+          "label": "MaximumTaskRangeLength"
+        },
+        {
+          "label": "ManagementPort"
+        },
+        {
+          "label": "PathModes"
+        },
+        {
+          "label": "PerNodeBatchSize"
+        },
+        {
+          "label": "PerNodeParallelBatchCount"
+        },
+        {
+          "label": "PrefetchBlocks"
+        },
+        {
+          "label": "SequentialReadsBeforePrefetch"
+        },
+        {
+          "label": "TrashPurgeTimeout"
+        }
+      ]
+    }
+  ],
+  "advanced": [
+    {
+      "label": "IPC",
+      "group": "ipc",
+      "tip": [
+        "TODO"
+      ],
+      "fields": [
+        {
+          "label": "isIpcEndpointEnabled",
+          "type": "check",
+          "model": "ipcEndpointEnabled"
+        },
+        {
+          "label": "IpcEndpointConfiguration"
+        }
+      ]
+    },
+    {
+      "label": "Fragmentizer",
+      "group": "fragmentizer",
+      "tip": [
+        "Fragmentizer settings"
+      ],
+      "fields": [
+        {
+          "label": "Fragmentizer enabled",
+          "id": "fragmentizerEnabled",
+          "type": "check",
+          "model": "fragmentizerEnabled"
+        },
+        {
+          "label": "Fragmentizer concurrent files",
+          "id": "fragmentizerConcurrentFiles",
+          "type": "check",
+          "model": "fragmentizerConcurrentFiles"
+        },
+        {
+          "label": "FragmentizerThrottlingBlockLength"
+        },
+        {
+          "label": "FragmentizerThrottlingDelay"
+        }
+      ]
+    },
+    {
+      "label": "Dual mode",
+      "group": "dualMode",
+      "tip": [
+        "TODO"
+      ],
+      "fields": [
+        {
+          "label": "DualModeMaxPendingPutsSize"
+        },
+        {
+          "label": "DualModePutExecutorService"
+        },
+        {
+          "label": "DualModePutExecutorServiceShutdown"
+        }
+      ]
+    },
+    {
+      "label": "Miscellaneous"
+    }
+  ]
+}

http://git-wip-us.apache.org/repos/asf/ignite/blob/87631e47/modules/control-center-web/src/main/js/controllers/models/metadata.json
----------------------------------------------------------------------
diff --git 
a/modules/control-center-web/src/main/js/controllers/models/metadata.json 
b/modules/control-center-web/src/main/js/controllers/models/metadata.json
index 387a02c..9cc5135 100644
--- a/modules/control-center-web/src/main/js/controllers/models/metadata.json
+++ b/modules/control-center-web/src/main/js/controllers/models/metadata.json
@@ -14,10 +14,10 @@
     ]
   },
   "moreInfo": {
-    "title": "Metadata page",
-    "content": ["Manage you type metadata on current page.",
+    "title": "Metadata screen",
+    "content": ["Manage you type metadata on current screen.",
       "Metadata can be assigned to specified <a 
href='/configuration/caches'>caches</a>.",
-      "Generated cluster with caches with metadata configuration available on 
<a href='/configuration/summary'>summary</a> page."]
+      "Generated cluster with caches with metadata configuration available on 
<a href='/configuration/summary'>summary</a> screen."]
   },
   "metadata": [
     {

http://git-wip-us.apache.org/repos/asf/ignite/blob/87631e47/modules/control-center-web/src/main/js/controllers/models/summary.json
----------------------------------------------------------------------
diff --git 
a/modules/control-center-web/src/main/js/controllers/models/summary.json 
b/modules/control-center-web/src/main/js/controllers/models/summary.json
index 88ad6b4..d9ef74c 100644
--- a/modules/control-center-web/src/main/js/controllers/models/summary.json
+++ b/modules/control-center-web/src/main/js/controllers/models/summary.json
@@ -15,12 +15,12 @@
     ]
   },
   "moreInfo": {
-    "title": "Summary page",
-    "content": ["Generated cluster's configuration showed on this page.",
+    "title": "Summary screen",
+    "content": ["Generated cluster's configuration showed on this screen.",
       "Configurations available in XML, Java and Dockerfile format for Server 
and Client mode.",
       "Database table POJO classes for cluster's metadatas available on 
\"POJO\" tab.",
       "Use \"Download\" button to receive configurations in ZIP file.",
-      "Go back to change configuration on <a 
href='/configuration/clusters'>clusters</a>, <a 
href='/configuration/caches'>caches</a> or <a 
href='/configuration/metadata'>metadata</a> pages."
+      "Go back to change configuration on <a 
href='/configuration/clusters'>clusters</a>, <a 
href='/configuration/caches'>caches</a> or <a 
href='/configuration/metadata'>metadata</a> screen."
     ]
   },
   "clientFields": [

http://git-wip-us.apache.org/repos/asf/ignite/blob/87631e47/modules/control-center-web/src/main/js/db.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/db.js 
b/modules/control-center-web/src/main/js/db.js
index cfdd6be..c987da3 100644
--- a/modules/control-center-web/src/main/js/db.js
+++ b/modules/control-center-web/src/main/js/db.js
@@ -219,6 +219,37 @@ CacheSchema.plugin(deepPopulate, {
 // Define Cache model.
 exports.Cache = mongoose.model('Cache', CacheSchema);
 
+var IgfsSchema = new Schema({
+    space: {type: ObjectId, ref: 'Space'},
+    name: String,
+    blockSize: Number,
+    streamBufferSize: Number,
+    dataCacheName: String,
+    metaCacheName: String,
+    defaultMode: {type: String, enum: ['PRIMARY', 'PROXY', 'DUAL_SYNC', 
'DUAL_ASYNC']},
+    dualModeMaxPendingPutsSize: Number,
+    //dualModePutExec = cfg.getDualModePutExecutorService();
+    dualModePutExecutorServiceShutdown: Boolean,
+    fragmentizerConcurrentFiles: Number,
+    fragmentizerEnabled: Boolean,
+    fragmentizerThrottlingBlockLength: Number,
+    fragmentizerThrottlingDelay: Number,
+    ipcEndpointConfiguration: {},
+    ipcEndpointEnabled: Boolean,
+    maxSpaceSize: Number,
+    maximumTaskRangeLength: Number,
+    managementPort: Number,
+    pathModes: [{path: String, mode: {type: String, enum: ['PRIMARY', 'PROXY', 
'DUAL_SYNC', 'DUAL_ASYNC']}}],
+    perNodeBatchSize: Number,
+    perNodeParallelBatchCount: Number,
+    prefetchBlocks: Number,
+    sequentialReadsBeforePrefetch: Number,
+    trashPurgeTimeout: Number
+});
+
+// Define IGFS model.
+exports.Igfs = mongoose.model('Igfs', IgfsSchema);
+
 // Define Cluster schema.
 var ClusterSchema = new Schema({
     space: {type: ObjectId, ref: 'Space'},
@@ -295,6 +326,7 @@ var ClusterSchema = new Schema({
     deploymentMode: {type: String, enum: ['PRIVATE', 'ISOLATED', 'SHARED', 
'CONTINUOUS']},
     discoveryStartupDelay: Number,
     igfsThreadPoolSize: Number,
+    igfs: [{type: ObjectId, ref: 'Igfs'}],
     includeEventTypes: [{
         type: String, enum: ['EVTS_CHECKPOINT', 'EVTS_DEPLOYMENT', 
'EVTS_ERROR', 'EVTS_DISCOVERY',
             'EVTS_JOB_EXECUTION', 'EVTS_TASK_EXECUTION', 'EVTS_CACHE', 
'EVTS_CACHE_REBALANCE', 'EVTS_CACHE_LIFECYCLE',

http://git-wip-us.apache.org/repos/asf/ignite/blob/87631e47/modules/control-center-web/src/main/js/routes/igfs.js
----------------------------------------------------------------------
diff --git a/modules/control-center-web/src/main/js/routes/igfs.js 
b/modules/control-center-web/src/main/js/routes/igfs.js
new file mode 100644
index 0000000..bc5b282
--- /dev/null
+++ b/modules/control-center-web/src/main/js/routes/igfs.js
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var _ = require('lodash');
+var router = require('express').Router();
+var db = require('../db');
+
+/* GET caches page. */
+router.get('/', function (req, res) {
+    res.render('configuration/igfs');
+});
+
+/**
+ * Get spaces and IGFSs accessed for user account.
+ *
+ * @param req Request.
+ * @param res Response.
+ */
+router.post('/list', function (req, res) {
+    var user_id = req.currentUserId();
+
+    // Get owned space and all accessed space.
+    db.Space.find({$or: [{owner: user_id}, {usedBy: {$elemMatch: {account: 
user_id}}}]}, function (err, spaces) {
+        if (db.processed(err, res)) {
+            var space_ids = spaces.map(function (value) {
+                return value._id;
+            });
+
+            // Get all clusters for spaces.
+            db.Cluster.find({space: {$in: space_ids}}, '_id 
name').sort('name').exec(function (err, clusters) {
+                if (db.processed(err, res)) {
+                    // Get all caches type metadata for spaces.
+                    db.CacheTypeMetadata.find({space: {$in: 
space_ids}}).sort('name').exec(function (err, metadatas) {
+                        if (db.processed(err, res)) {
+                            // Get all caches for spaces.
+                            db.Cache.find({space: {$in: 
space_ids}}).sort('name').exec(function (err, caches) {
+                                if (db.processed(err, res)) {
+                                    _.forEach(caches, function (cache) {
+                                        // Remove deleted clusters.
+                                        cache.clusters = 
_.filter(cache.clusters, function (clusterId) {
+                                            return _.findIndex(clusters, 
function (cluster) {
+                                                    return 
cluster._id.equals(clusterId);
+                                                }) >= 0;
+                                        });
+
+                                        // Remove deleted metadata.
+                                        cache.metadatas = 
_.filter(cache.metadatas, function (metaId) {
+                                            return _.findIndex(metadatas, 
function (meta) {
+                                                    return 
meta._id.equals(metaId);
+                                                }) >= 0;
+                                        });
+                                    });
+
+                                    res.json({
+                                        spaces: spaces,
+                                        clusters: clusters.map(function 
(cluster) {
+                                            return {value: cluster._id, label: 
cluster.name};
+                                        }),
+                                        metadatas: metadatas,
+                                        caches: caches
+                                    });
+                                }
+                            });
+                        }
+                    });
+                }
+            });
+        }
+    });
+});
+
+/**
+ * Save cache.
+ */
+router.post('/save', function (req, res) {
+    var params = req.body;
+    var cacheId = params._id;
+    var clusters = params.clusters;
+    var metadatas = params.metadatas;
+
+    if (params._id) {
+        db.Cache.update({_id: cacheId}, params, {upsert: true}, function (err) 
{
+            if (db.processed(err, res))
+                db.Cluster.update({_id: {$in: clusters}}, {$addToSet: {caches: 
cacheId}}, {multi: true}, function (err) {
+                    if (db.processed(err, res))
+                        db.Cluster.update({_id: {$nin: clusters}}, {$pull: 
{caches: cacheId}}, {multi: true}, function (err) {
+                            if (db.processed(err, res))
+                                db.CacheTypeMetadata.update({_id: {$in: 
metadatas}}, {$addToSet: {caches: cacheId}}, {multi: true}, function (err) {
+                                    if (db.processed(err, res))
+                                        db.CacheTypeMetadata.update({_id: 
{$nin: metadatas}}, {$pull: {caches: cacheId}}, {multi: true}, function (err) {
+                                            if (db.processed(err, res))
+                                                res.send(params._id);
+                                        });
+                                });
+                        });
+                });
+        })
+    }
+    else
+        db.Cache.findOne({space: params.space, name: params.name}, function 
(err, cache) {
+            if (db.processed(err, res)) {
+                if (cache)
+                    return res.status(500).send('Cache with name: "' + 
cache.name + '" already exist.');
+
+                (new db.Cache(params)).save(function (err, cache) {
+                    if (db.processed(err, res)) {
+                        cacheId = cache._id;
+
+                        db.Cluster.update({_id: {$in: clusters}}, {$addToSet: 
{caches: cacheId}}, {multi: true}, function (err) {
+                            if (db.processed(err, res))
+                                db.CacheTypeMetadata.update({_id: {$in: 
metadatas}}, {$addToSet: {caches: cacheId}}, {multi: true}, function (err) {
+                                    if (db.processed(err, res))
+                                        res.send(cacheId);
+                                });
+                        });
+                    }
+                });
+            }
+        });
+});
+
+/**
+ * Remove cache by ._id.
+ */
+router.post('/remove', function (req, res) {
+    db.Cache.remove(req.body, function (err) {
+        if (db.processed(err, res))
+            res.sendStatus(200);
+    })
+});
+
+/**
+ * Remove all caches.
+ */
+router.post('/remove/all', function (req, res) {
+    var user_id = req.currentUserId();
+
+    // Get owned space and all accessed space.
+    db.Space.find({$or: [{owner: user_id}, {usedBy: {$elemMatch: {account: 
user_id}}}]}, function (err, spaces) {
+        if (db.processed(err, res)) {
+            var space_ids = spaces.map(function (value) {
+                return value._id;
+            });
+
+            db.Cache.remove({space: {$in: space_ids}}, function (err) {
+                if (err)
+                    return res.status(500).send(err.message);
+
+                res.sendStatus(200);
+            })
+        }
+    });
+});
+
+module.exports = router;

http://git-wip-us.apache.org/repos/asf/ignite/blob/87631e47/modules/control-center-web/src/main/js/views/configuration/igfs.jade
----------------------------------------------------------------------
diff --git 
a/modules/control-center-web/src/main/js/views/configuration/igfs.jade 
b/modules/control-center-web/src/main/js/views/configuration/igfs.jade
new file mode 100644
index 0000000..28c4384
--- /dev/null
+++ b/modules/control-center-web/src/main/js/views/configuration/igfs.jade
@@ -0,0 +1,46 @@
+//-
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+extends sidebar
+
+append scripts
+    script(src='/igfs-controller.js')
+
+include ../includes/controls
+
+block content
+    .docs-header
+        h1 Create and Configure IGFS
+    .docs-body(ng-controller='igfsController')
+        div(dw-loading='loadingIgfsScreen' dw-loading-options='{text: "Loading 
IGFS screen...", className: "page-loading-overlay"}')
+            div(ng-show='ui.ready')
+                +block-callout('{{screenTip.workflowTitle}}', 
'screenTip.workflowContent', '{{screenTip.whatsNextTitle}}', 
'screenTip.whatsNextContent')
+                hr
+                +main-table('IGFS:', 'igfs', 'igfsName', 'selectItem(row)', 
'{{$index + 1}}) {{row.name}}')
+                .padding-top-dflt(bs-affix)
+                    .panel-tip-container(data-placement='bottom' bs-tooltip 
data-title='Create new caches')
+                        button.btn.btn-primary(id='new-item' 
ng-click='createItem()') Add IGFS
+                    +save-remove-buttons('igfs')
+                    hr
+                form.form-horizontal(name='ui.inputForm' ng-show='backupItem 
&& tableVisibleRow(displayedRows, selectedItem)' novalidate 
unsaved-warning-form)
+                    .panel-group(bs-collapse ng-model='panels.activePanels' 
data-allow-multiple='true' ng-click='triggerDigest = true')
+                        +groups('general', 'backupItem')
+                        div(ng-show='ui.expanded')
+                            +advanced-options
+                            +groups('advanced', 'backupItem')
+                    +advanced-options
+                    .section(ng-show='ui.expanded')
+                        +save-remove-buttons('igfs')

http://git-wip-us.apache.org/repos/asf/ignite/blob/87631e47/modules/control-center-web/src/main/js/views/configuration/sidebar.jade
----------------------------------------------------------------------
diff --git 
a/modules/control-center-web/src/main/js/views/configuration/sidebar.jade 
b/modules/control-center-web/src/main/js/views/configuration/sidebar.jade
index abd0ba8..2208d89 100644
--- a/modules/control-center-web/src/main/js/views/configuration/sidebar.jade
+++ b/modules/control-center-web/src/main/js/views/configuration/sidebar.jade
@@ -41,7 +41,8 @@ block container
                     +sidebar-item('/configuration/clusters', 1, 'Clusters')
                     +sidebar-item('/configuration/caches', 2, 'Caches')
                     +sidebar-item('/configuration/metadata', 3, 'Metadata')
-                    +sidebar-item('/configuration/summary', 4, 'Summary')
+                    +sidebar-item('/configuration/igfs', 4, 'IGFS')
+                    +sidebar-item('/configuration/summary', 5, 'Summary')
 
         .col-xs-9.col-sm-9.col-md-10.border-left.section-right
             .docs-content

Reply via email to