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 <vsi...@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");