You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ak...@apache.org on 2019/04/05 11:13:26 UTC

[ignite] branch master updated: IGNITE-11284 Web console: Actualized cluster configuration.

This is an automated email from the ASF dual-hosted git repository.

akuznetsov pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git


The following commit(s) were added to refs/heads/master by this push:
     new b6a07f6  IGNITE-11284 Web console: Actualized cluster configuration.
b6a07f6 is described below

commit b6a07f65bba402e5bfa165957f526cee95098f44
Author: Vasiliy Sisko <vs...@gridgain.com>
AuthorDate: Fri Apr 5 18:13:08 2019 +0700

    IGNITE-11284 Web console: Actualized cluster configuration.
---
 modules/web-console/backend/app/schemas.js         | 14 +++-
 .../components/model-edit-form/templates/query.pug | 72 ++++++++++++++++++++-
 .../generator/generator/ConfigurationGenerator.js  | 74 ++++++++++++++++++++--
 .../generator/generator/JavaTransformer.service.js |  4 +-
 .../generator/SpringTransformer.service.js         |  6 +-
 .../generator/generator/defaults/Cache.service.js  | 12 ++++
 .../frontend/app/configuration/services/Models.ts  | 41 ++++++++++++
 .../WebConsoleConfigurationSelfTest.java           |  6 ++
 8 files changed, 216 insertions(+), 13 deletions(-)

diff --git a/modules/web-console/backend/app/schemas.js b/modules/web-console/backend/app/schemas.js
index 4741776..29493a5 100644
--- a/modules/web-console/backend/app/schemas.js
+++ b/modules/web-console/backend/app/schemas.js
@@ -122,12 +122,21 @@ module.exports.factory = function(mongoose) {
             javaFieldType: String
         }],
         queryKeyFields: [String],
-        fields: [{name: String, className: String}],
+        fields: [{
+            name: String,
+            className: String,
+            notNull: Boolean,
+            defaultValue: String,
+            precision: Number,
+            scale: Number
+        }],
         aliases: [{field: String, alias: String}],
         indexes: [{
             name: String,
             indexType: {type: String, enum: ['SORTED', 'FULLTEXT', 'GEOSPATIAL']},
-            fields: [{name: String, direction: Boolean}]
+            fields: [{name: String, direction: Boolean}],
+            inlineSizeType: Number,
+            inlineSize: Number
         }],
         generatePojo: Boolean
     });
@@ -182,6 +191,7 @@ module.exports.factory = function(mongoose) {
 
         backups: Number,
         memoryMode: {type: String, enum: ['ONHEAP_TIERED', 'OFFHEAP_TIERED', 'OFFHEAP_VALUES']},
+        offHeapMode: Number,
         offHeapMaxMemory: Number,
         startSize: Number,
         swapEnabled: Boolean,
diff --git a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/model-edit-form/templates/query.pug b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/model-edit-form/templates/query.pug
index 2dbb565..9f14980 100644
--- a/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/model-edit-form/templates/query.pug
+++ b/modules/web-console/frontend/app/configuration/components/page-configure-advanced/components/model-edit-form/templates/query.pug
@@ -77,12 +77,12 @@ panel-collapsible(ng-form=form opened=`!!${model}.queryMetadata`)
                             ng-change=`$ctrl.onQueryFieldsChange(${model})`
                         )
                             list-editable-item-view
-                                | {{ $item.name}} / {{ $item.className}}
+                                | {{$ctrl.Models.fieldProperties.fieldPresentation($item, $ctrl.available)}}
 
                             list-editable-item-edit
                                 - form = '$parent.form'
                                 .pc-form-grid-row
-                                    .pc-form-grid-col-30(divider='/')
+                                    .pc-form-grid-col-30
                                         +form-field__text({
                                             label: 'Field name:',
                                             model: '$item.name',
@@ -98,7 +98,7 @@ panel-collapsible(ng-form=form opened=`!!${model}.queryMetadata`)
                                     .pc-form-grid-col-30
                                         +form-field__java-class--typeahead({
                                             label: 'Field full class name:',
-                                            model: `$item.className`,
+                                            model: '$item.className',
                                             name: '"className"',
                                             options: '$ctrl.queryFieldTypes',
                                             required: 'true',
@@ -107,6 +107,41 @@ panel-collapsible(ng-form=form opened=`!!${model}.queryMetadata`)
                                             ng-model-options='{allowInvalid: true}'
                                             extra-valid-java-identifiers='$ctrl.queryFieldTypes'
                                         )
+                                    .pc-form-grid-col-60(ng-if='$ctrl.available("2.4.0")')
+                                        +form-field__text({
+                                            label: 'Default value:',
+                                            model: '$item.defaultValue',
+                                            name: '"defaultValue"',
+                                            placeholder: 'Enter default value'
+                                        })
+                                    .pc-form-grid-col-30(ng-if-start='$ctrl.available("2.7.0") && $ctrl.Models.fieldProperties.precisionAvailable($item)')
+                                        +form-field__number({
+                                            label: 'Precision:',
+                                            model: '$item.precision',
+                                            name: '"Precision"',
+                                            placeholder: 'Input field precision',
+                                            min: '1',
+                                            tip: 'Precision of field',
+                                            required: '$item.scale'
+                                        })
+                                    .pc-form-grid-col-30(ng-if-end)
+                                        +form-field__number({
+                                            label: 'Scale:',
+                                            model: '$item.scale',
+                                            name: '"Scale"',
+                                            placeholder: 'input field scale',
+                                            disabled: '!$ctrl.Models.fieldProperties.scaleAvailable($item)',
+                                            min: '0',
+                                            max: '{{$item.precision}}',
+                                            tip: 'Scale of field'
+                                        })
+                                    .pc-form-grid-col-60(ng-if='$ctrl.available("2.3.0")')
+                                        +form-field__checkbox({
+                                            label: 'Not NULL',
+                                            model: '$item.notNull',
+                                            name: '"notNull"',
+                                            tip: 'Field must have non-null value'
+                                        })
 
                             list-editable-no-items
                                 list-editable-add-item-button(
@@ -223,6 +258,37 @@ panel-collapsible(ng-form=form opened=`!!${model}.queryMetadata`)
                                         placeholder: 'Select index type',
                                         options: '::$ctrl.Models.indexType.values'
                                     })
+                                .pc-form-grid-col-60(ng-if='$ctrl.available("2.3.0")')
+                                    +form-field__dropdown({
+                                        label: 'Inline size:',
+                                        model: `queryIndex.inlineSizeType`,
+                                        name: '"InlineSizeKind"',
+                                        placeholder: '{{::$ctrl.Models.inlineSizeType.default}}',
+                                        options: '{{::$ctrl.Models.inlineSizeTypes}}',
+                                        tip: `Inline size
+                                            <ul>
+                                                <li>Auto - Determine inline size automatically</li>
+                                                <li>Custom - Fixed index inline</li>
+                                                <li>Disabled - Index inline is disabled</li>
+                                            </ul>`
+                                    })(
+                                        ng-change=`$ctrl.Models.inlineSizeType.onChange(queryIndex)`
+                                        ng-model-options='{allowInvalid: true}'
+                                    )
+                                .pc-form-grid-col-60(ng-if='$ctrl.available("2.3.0") && queryIndex.inlineSizeType === 1')
+                                    form-field-size(
+                                        label='Inline size:'
+                                        ng-model=`queryIndex.inlineSize`
+                                        ng-model-options='{allowInvalid: true}'
+                                        name=`InlineSize`
+                                        tip='Index inline size in bytes. Part of indexed value will be placed directly to index pages thus minimizing data page accesses'
+                                        placeholder='Input inline size'
+                                        min=`1`
+                                        size-scale-label='kb'
+                                        size-type='bytes'
+                                        required='true'
+                                    )
+                                        +form-field__error({error: 'min', message: 'Inline size should be greater than 0'})
                                 .pc-form-grid-col-60
                                     .ignite-form-field
                                         +form-field__label({ label: 'Index fields:', name: '"indexFields"', required: true })
diff --git a/modules/web-console/frontend/app/configuration/generator/generator/ConfigurationGenerator.js b/modules/web-console/frontend/app/configuration/generator/generator/ConfigurationGenerator.js
index a71f518..98bfaf2 100644
--- a/modules/web-console/frontend/app/configuration/generator/generator/ConfigurationGenerator.js
+++ b/modules/web-console/frontend/app/configuration/generator/generator/ConfigurationGenerator.js
@@ -1952,8 +1952,54 @@ export default class IgniteConfigurationGenerator {
     // Generate domain model for query group.
     static domainModelQuery(domain, available, cfg = this.domainConfigurationBean(domain)) {
         if (cfg.valueOf('queryMetadata') === 'Configuration') {
+            const notNull = [];
+            const precisions = [];
+            const scales = [];
+            const defaultValues = [];
+
+            const notNullAvailable = available('2.3.0');
+            const defaultAvailable = available('2.4.0');
+            const precisionAvailable = available('2.7.0');
+
             const fields = _.filter(_.map(domain.fields,
-                (e) => ({name: e.name, className: javaTypes.stringClassName(e.className)})), (field) => {
+                (e) => {
+                    if (notNullAvailable && e.notNull)
+                        notNull.push(e.name);
+
+                    if (defaultAvailable && e.defaultValue) {
+                        let value = e.defaultValue;
+
+                        switch (e.className) {
+                            case 'String':
+                                value = new Bean('java.lang.String', 'value', e).stringConstructorArgument('defaultValue');
+
+                                break;
+
+                            case 'BigDecimal':
+                                value = new Bean('java.math.BigDecimal', 'value', e).stringConstructorArgument('defaultValue');
+
+                                break;
+
+                            case 'byte[]':
+                                value = null;
+
+                                break;
+
+                            default: // No-op.
+                        }
+
+                        defaultValues.push({name: e.name, value});
+                    }
+
+                    if (precisionAvailable && e.precision) {
+                        precisions.push({name: e.name, value: e.precision});
+
+                        if (e.scale)
+                            scales.push({name: e.name, value: e.scale});
+                    }
+
+                    return {name: e.name, className: javaTypes.stringClassName(e.className)};
+                }), (field) => {
                 return field.name !== domain.keyFieldName && field.name !== domain.valueFieldName;
             });
 
@@ -1977,12 +2023,30 @@ export default class IgniteConfigurationGenerator {
                 .mapProperty('fields', fields, 'fields', true)
                 .mapProperty('aliases', 'aliases');
 
-            const indexes = _.map(domain.indexes, (index) =>
-                new Bean('org.apache.ignite.cache.QueryIndex', 'index', index, cacheDflts.indexes)
+            if (notNullAvailable && notNull)
+                cfg.collectionProperty('notNullFields', 'notNullFields', notNull, 'java.lang.String', 'java.util.HashSet');
+
+            if (defaultAvailable && defaultValues)
+                cfg.mapProperty('defaultFieldValues', defaultValues, 'defaultFieldValues');
+
+            if (precisionAvailable && precisions) {
+                cfg.mapProperty('fieldsPrecision', precisions, 'fieldsPrecision');
+
+                if (scales)
+                    cfg.mapProperty('fieldsScale', scales, 'fieldsScale');
+            }
+
+            const indexes = _.map(domain.indexes, (index) => {
+                const bean = new Bean('org.apache.ignite.cache.QueryIndex', 'index', index, cacheDflts.indexes)
                     .stringProperty('name')
                     .enumProperty('indexType')
-                    .mapProperty('indFlds', 'fields', 'fields', true)
-            );
+                    .mapProperty('indFlds', 'fields', 'fields', true);
+
+                if (available('2.3.0'))
+                    bean.intProperty('inlineSize');
+
+                return bean;
+            });
 
             cfg.collectionProperty('indexes', 'indexes', indexes, 'org.apache.ignite.cache.QueryIndex');
         }
diff --git a/modules/web-console/frontend/app/configuration/generator/generator/JavaTransformer.service.js b/modules/web-console/frontend/app/configuration/generator/generator/JavaTransformer.service.js
index fdaf829..c1e1cfd 100644
--- a/modules/web-console/frontend/app/configuration/generator/generator/JavaTransformer.service.js
+++ b/modules/web-console/frontend/app/configuration/generator/generator/JavaTransformer.service.js
@@ -17,6 +17,8 @@
 
 import {nonEmpty} from 'app/utils/lodashMixins';
 
+import { Bean } from './Beans';
+
 import AbstractTransformer from './AbstractTransformer';
 import StringBuilder from './StringBuilder';
 import VersionService from 'app/services/Version.service';
@@ -413,7 +415,7 @@ export default class IgniteJavaTransformer extends AbstractTransformer {
                 case 'PROPERTY_INT':
                     return `Integer.parseInt(props.getProperty("${item}"))`;
                 default:
-                    if (this._isBean(clsName)) {
+                    if (this._isBean(clsName) || val instanceof Bean) {
                         if (item.isComplex())
                             return item.id;
 
diff --git a/modules/web-console/frontend/app/configuration/generator/generator/SpringTransformer.service.js b/modules/web-console/frontend/app/configuration/generator/generator/SpringTransformer.service.js
index db9109b..5d90ed4 100644
--- a/modules/web-console/frontend/app/configuration/generator/generator/SpringTransformer.service.js
+++ b/modules/web-console/frontend/app/configuration/generator/generator/SpringTransformer.service.js
@@ -17,6 +17,8 @@
 
 import _ from 'lodash';
 
+import { Bean } from './Beans';
+
 import AbstractTransformer from './AbstractTransformer';
 import StringBuilder from './StringBuilder';
 import VersionService from 'app/services/Version.service';
@@ -138,8 +140,8 @@ export default class IgniteSpringTransformer extends AbstractTransformer {
             const key = entry[map.keyField];
             const val = entry[map.valField];
 
-            const isKeyBean = this._isBean(map.keyClsName);
-            const isValBean = this._isBean(map.valClsName);
+            const isKeyBean = key instanceof Bean || this._isBean(map.keyClsName);
+            const isValBean = val instanceof Bean || this._isBean(map.valClsName);
 
 
             if (isKeyBean || isValBean) {
diff --git a/modules/web-console/frontend/app/configuration/generator/generator/defaults/Cache.service.js b/modules/web-console/frontend/app/configuration/generator/generator/defaults/Cache.service.js
index 2e818ba..94fc8db 100644
--- a/modules/web-console/frontend/app/configuration/generator/generator/defaults/Cache.service.js
+++ b/modules/web-console/frontend/app/configuration/generator/generator/defaults/Cache.service.js
@@ -97,6 +97,18 @@ const DFLT_CACHE = {
         valField: 'className',
         entries: []
     },
+    defaultFieldValues: {
+        keyClsName: 'java.lang.String',
+        valClsName: 'java.lang.Object'
+    },
+    fieldsPrecision: {
+        keyClsName: 'java.lang.String',
+        valClsName: 'java.lang.Integer'
+    },
+    fieldsScale: {
+        keyClsName: 'java.lang.String',
+        valClsName: 'java.lang.Integer'
+    },
     aliases: {
         keyClsName: 'java.lang.String',
         valClsName: 'java.lang.String',
diff --git a/modules/web-console/frontend/app/configuration/services/Models.ts b/modules/web-console/frontend/app/configuration/services/Models.ts
index ecd06d8..1fda485 100644
--- a/modules/web-console/frontend/app/configuration/services/Models.ts
+++ b/modules/web-console/frontend/app/configuration/services/Models.ts
@@ -53,6 +53,47 @@ export default class Models {
         ]
     };
 
+    inlineSizeTypes = [
+        {label: 'Auto', value: -1},
+        {label: 'Custom', value: 1},
+        {label: 'Disabled', value: 0}
+    ];
+
+    inlineSizeType = {
+        _val(queryIndex) {
+            return (queryIndex.inlineSizeType === null || queryIndex.inlineSizeType === void 0) ? -1 : queryIndex.inlineSizeType;
+        },
+        onChange: (queryIndex) => {
+            const inlineSizeType = this.inlineSizeType._val(queryIndex);
+            switch (inlineSizeType) {
+                case 1:
+                    return queryIndex.inlineSize = queryIndex.inlineSize > 0 ? queryIndex.inlineSize : null;
+                case 0:
+                case -1:
+                    return queryIndex.inlineSize = queryIndex.inlineSizeType;
+                default: break;
+            }
+        },
+        default: 'Auto'
+    };
+
+    fieldProperties = {
+        typesWithPrecision: ['BigDecimal', 'String', 'byte[]'],
+        fieldPresentation: (entity, available) => {
+            if (!entity)
+                return '';
+
+            const precision = available('2.7.0') && this.fieldProperties.precisionAvailable(entity);
+            const scale = available('2.7.0') && this.fieldProperties.scaleAvailable(entity);
+
+            return `${entity.name || ''} ${entity.className || ''}${precision && entity.precision ? ' (' + entity.precision : ''}\
+${scale && entity.precision && entity.scale ? ',' + entity.scale : ''}${precision && entity.precision ? ')' : ''}\
+${available('2.3.0') && entity.notNull ? ' Not NULL' : ''}${available('2.4.0') && entity.defaultValue ? ' DEFAULT ' + entity.defaultValue : ''}`;
+        },
+        precisionAvailable: (entity) => entity && this.fieldProperties.typesWithPrecision.includes(entity.className),
+        scaleAvailable: (entity) => entity && entity.className === 'BigDecimal'
+    };
+
     indexSortDirection = {
         values: [
             {value: true, label: 'ASC'},
diff --git a/modules/web-console/src/test/java/org/apache/ignite/console/configuration/WebConsoleConfigurationSelfTest.java b/modules/web-console/src/test/java/org/apache/ignite/console/configuration/WebConsoleConfigurationSelfTest.java
index 66a4ac7..a163a39 100644
--- a/modules/web-console/src/test/java/org/apache/ignite/console/configuration/WebConsoleConfigurationSelfTest.java
+++ b/modules/web-console/src/test/java/org/apache/ignite/console/configuration/WebConsoleConfigurationSelfTest.java
@@ -792,6 +792,7 @@ public class WebConsoleConfigurationSelfTest {
         jdbcPojoStoreProps.add("hasher");
         jdbcPojoStoreProps.add("transformer");
         jdbcPojoStoreProps.add("sqlEscapeAll");
+        jdbcPojoStoreProps.add("types");
 
         // Configured via dataSource property.
         Set<String> jdbcPojoStorePropsExcl = new HashSet<>();
@@ -927,12 +928,17 @@ public class WebConsoleConfigurationSelfTest {
         qryEntityProps.add("keyFieldName");
         qryEntityProps.add("valueFieldName");
         qryEntityProps.add("keyFields");
+        qryEntityProps.add("fieldsPrecision");
+        qryEntityProps.add("notNullFields");
+        qryEntityProps.add("fieldsScale");
+        qryEntityProps.add("defaultFieldValues");
         metadata.put(QueryEntity.class, new MetadataInfo(qryEntityProps, EMPTY_FIELDS, EMPTY_FIELDS));
 
         Set<String> qryIdxProps = new HashSet<>();
         qryIdxProps.add("name");
         qryIdxProps.add("indexType");
         qryIdxProps.add("fields");
+        qryIdxProps.add("inlineSize");
 
         Set<String> qryIdxPropsExcl = new HashSet<>();
         qryIdxPropsExcl.add("fieldNames");