| //- |
| 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. |
| |
| include /app/helpers/jade/mixins |
| include /app/configuration/mixins |
| |
| -var form = 'dataStorageConfiguration' |
| -var clusterModel = '$ctrl.clonedCluster' |
| -var model = clusterModel + '.dataStorageConfiguration' |
| -var dfltRegionModel = model + '.defaultDataRegionConfiguration' |
| -var dataRegionConfigurations = model + '.dataRegionConfigurations' |
| |
| mixin data-region-form({modelAt, namePlaceholder, dataRegionsAt}) |
| .pc-form-grid-col-60 |
| +form-field__text({ |
| label: 'Name:', |
| model: `${modelAt}.name`, |
| name: '"name"', |
| placeholder: namePlaceholder, |
| })( |
| ng-model-options='{allowInvalid: true}' |
| |
| pc-not-in-collection='::$ctrl.Clusters.dataRegion.name.invalidValues' |
| ignite-unique=dataRegionsAt |
| ignite-unique-property='name' |
| ignite-unique-skip=`["_id", ${modelAt}]` |
| ) |
| +form-field__error({ error: 'notInCollection', message: '{{::$ctrl.Clusters.dataRegion.name.invalidValues[0]}} is reserved for internal use' }) |
| +form-field__error({ error: 'igniteUnique', message: 'Name should be unique' }) |
| |
| .pc-form-grid-col-30 |
| form-field-size( |
| label='Initial size:' |
| ng-model=`${modelAt}.initialSize` |
| name='initialSize' |
| placeholder='{{ $ctrl.Clusters.dataRegion.initialSize.default / _drISScale.value }}' |
| min='{{ ::$ctrl.Clusters.dataRegion.initialSize.min }}' |
| on-scale-change='_drISScale = $event' |
| ) |
| |
| .pc-form-grid-col-30 |
| form-field-size( |
| ng-model=`${modelAt}.maxSize` |
| ng-model-options='{allowInvalid: true}' |
| name='maxSize' |
| label='Maximum size:' |
| placeholder='{{ ::$ctrl.Clusters.dataRegion.maxSize.default }}' |
| min=`{{ $ctrl.Clusters.dataRegion.maxSize.min(${modelAt}) }}` |
| ) |
| |
| .pc-form-grid-col-60(ng-if=`!${modelAt}.persistenceEnabled || ${modelAt}.swapPath`) |
| +form-field__text({ |
| label: 'Swap file path:', |
| model: `${modelAt}.swapPath`, |
| name: '"swapPath"', |
| placeholder: 'Input swap file path', |
| tip: 'An optional path to a memory mapped file for this data region' |
| }) |
| |
| .pc-form-grid-col-60 |
| +form-field__number({ |
| label: 'Checkpoint page buffer:', |
| model: `${modelAt}.checkpointPageBufferSize`, |
| name: '"checkpointPageBufferSize"', |
| placeholder: '0', |
| min: '0', |
| tip: 'Amount of memory allocated for a checkpoint temporary buffer in bytes' |
| }) |
| |
| .pc-form-grid-col-60 |
| +form-field__dropdown({ |
| label: 'Entry versioning:', |
| model: `${modelAt}.pageEvictionMode`, |
| name: '"pageEvictionMode"', |
| placeholder: 'DISABLED', |
| options: '[\ |
| {value: "DISABLED", label: "DISABLED"},\ |
| {value: "RANDOM_LRU", label: "RANDOM_LRU"},\ |
| {value: "RANDOM_2_LRU", label: "RANDOM_2_LRU"}\ |
| ]', |
| tip: `An algorithm for memory pages eviction |
| <ul> |
| <li>DISABLED - Eviction is disabled</li> |
| <li>RANDOM_LRU - Once a memory region defined by a data region is configured, an off-heap array is allocated to track last usage timestamp for every individual data page</li> |
| <li>RANDOM_2_LRU - Differs from Random - LRU only in a way that two latest access timestamps are stored for every data page</li> |
| </ul>` |
| }) |
| |
| .pc-form-grid-col-30 |
| +form-field__number({ |
| label: 'Eviction threshold:', |
| model: `${modelAt}.evictionThreshold`, |
| name: '"evictionThreshold"', |
| placeholder: '{{ ::$ctrl.Clusters.dataRegion.evictionThreshold.default }}', |
| min: '{{ ::$ctrl.Clusters.dataRegion.evictionThreshold.min }}', |
| max: '{{ ::$ctrl.Clusters.dataRegion.evictionThreshold.max }}', |
| step: '{{ ::$ctrl.Clusters.dataRegion.evictionThreshold.step }}', |
| tip: 'A threshold for memory pages eviction initiation' |
| }) |
| |
| .pc-form-grid-col-30 |
| +form-field__number({ |
| label: 'Empty pages pool size:', |
| model: `${modelAt}.emptyPagesPoolSize`, |
| name: '"emptyPagesPoolSize"', |
| placeholder: '{{ ::$ctrl.Clusters.dataRegion.emptyPagesPoolSize.default }}', |
| min: '{{ ::$ctrl.Clusters.dataRegion.emptyPagesPoolSize.min }}', |
| max: `{{ $ctrl.Clusters.dataRegion.emptyPagesPoolSize.max($ctrl.clonedCluster, ${modelAt}) }}`, |
| tip: 'The minimal number of empty pages to be present in reuse lists for this data region' |
| }) |
| |
| .pc-form-grid-col-30 |
| +form-field__number({ |
| label: 'Metrics sub interval count:', |
| model: `${modelAt}.metricsSubIntervalCount`, |
| name: '"metricsSubIntervalCount"', |
| placeholder: '{{ ::$ctrl.Clusters.dataRegion.metricsSubIntervalCount.default }}', |
| min: '{{ ::$ctrl.Clusters.dataRegion.metricsSubIntervalCount.min }}', |
| step: '{{ ::$ctrl.Clusters.dataRegion.metricsSubIntervalCount.step }}', |
| tip: 'A number of sub-intervals the whole rate time interval will be split into to calculate allocation and eviction rates' |
| }) |
| |
| .pc-form-grid-col-30 |
| form-field-size( |
| ng-model=`${modelAt}.metricsRateTimeInterval` |
| ng-model-options='{allowInvalid: true}' |
| name='metricsRateTimeInterval' |
| size-type='seconds' |
| label='Metrics rate time interval:' |
| placeholder='{{ $ctrl.Clusters.dataRegion.metricsRateTimeInterval.default / _metricsRateTimeIntervalScale.value }}' |
| min=`{{ ::$ctrl.Clusters.dataRegion.metricsRateTimeInterval.min }}` |
| tip='Time interval for allocation rate and eviction rate monitoring purposes' |
| on-scale-change='_metricsRateTimeIntervalScale = $event' |
| size-scale-label='s' |
| ) |
| |
| .pc-form-grid-col-60 |
| +form-field__checkbox({ |
| label: 'Metrics enabled', |
| model: `${modelAt}.metricsEnabled`, |
| name: '"MemoryPolicyMetricsEnabled"', |
| tip: 'Whether memory metrics are enabled by default on node startup' |
| }) |
| |
| .pc-form-grid-col-60(ng-if=`!${modelAt}.swapPath`) |
| +form-field__checkbox({ |
| label: 'Persistence enabled', |
| model: `${modelAt}.persistenceEnabled`, |
| name: '"RegionPersistenceEnabled" + $index', |
| tip: 'Enable Ignite Native Persistence' |
| }) |
| |
| panel-collapsible(ng-show='$ctrl.available("2.3.0")' ng-form=form on-open=`ui.loadPanel('${form}')`) |
| panel-title Data storage configuration |
| panel-description |
| | Page memory is a manageable off-heap based memory architecture that is split into pages of fixed size. |
| | #[a.link-success(href="https://apacheignite.readme.io/docs/distributed-persistent-store" target="_blank") More info] |
| panel-content.pca-form-row(ng-if=`$ctrl.available("2.3.0") && ui.isPanelLoaded('${form}')`) |
| .pca-form-column-6.pc-form-grid-row |
| .pc-form-grid-col-30 |
| +form-field__dropdown({ |
| label: 'Page size:', |
| model: `${model}.pageSize`, |
| name: '"DataStorageConfigurationPageSize"', |
| options: `$ctrl.Clusters.dataStorageConfiguration.pageSize.values`, |
| tip: 'Every memory region is split on pages of fixed size' |
| }) |
| .pc-form-grid-col-30 |
| +form-field__number({ |
| label: 'Concurrency level:', |
| model: model + '.concurrencyLevel', |
| name: '"DataStorageConfigurationConcurrencyLevel"', |
| placeholder: 'availableProcessors', |
| min: '2', |
| tip: 'The number of concurrent segments in Ignite internal page mapping tables' |
| }) |
| .pc-form-grid-col-60.pc-form-group__text-title |
| span System region |
| .pc-form-group.pc-form-grid-row |
| .pc-form-grid-col-30 |
| form-field-size( |
| label='Initial size:' |
| ng-model=`${model}.systemRegionInitialSize` |
| name='DataStorageSystemRegionInitialSize' |
| placeholder='{{ $ctrl.Clusters.dataStorageConfiguration.systemRegionInitialSize.default / systemRegionInitialSizeScale.value }}' |
| min='{{ ::$ctrl.Clusters.dataStorageConfiguration.systemRegionInitialSize.min }}' |
| tip='Initial size of a data region reserved for system cache' |
| on-scale-change='systemRegionInitialSizeScale = $event' |
| ) |
| .pc-form-grid-col-30 |
| form-field-size( |
| label='Max size:' |
| ng-model=`${model}.systemRegionMaxSize` |
| name='DataStorageSystemRegionMaxSize' |
| placeholder='{{ $ctrl.Clusters.dataStorageConfiguration.systemRegionMaxSize.default / systemRegionMaxSizeScale.value }}' |
| min='{{ $ctrl.Clusters.dataStorageConfiguration.systemRegionMaxSize.min($ctrl.clonedCluster) }}' |
| tip='Maximum data region size reserved for system cache' |
| on-scale-change='systemRegionMaxSizeScale = $event' |
| ) |
| .pc-form-grid-col-60.pc-form-group__text-title |
| span Default data region |
| .pc-form-group.pc-form-grid-row |
| +data-region-form({ |
| modelAt: dfltRegionModel, |
| namePlaceholder: '{{ ::$ctrl.Clusters.dataRegion.name.default }}', |
| dataRegionsAt: dataRegionConfigurations |
| }) |
| .pc-form-grid-col-60 |
| .ignite-form-field |
| +form-field__label({ label: 'Data region configurations' }) |
| |
| list-editable.pc-list-editable-with-form-grid( |
| name='dataRegionConfigurations' |
| ng-model=dataRegionConfigurations |
| ) |
| list-editable-item-edit.pc-form-grid-row |
| - form = '$parent.form' |
| +data-region-form({ |
| modelAt: '$item', |
| namePlaceholder: 'Data region name', |
| dataRegionsAt: dataRegionConfigurations |
| }) |
| - form = 'dataStorageConfiguration' |
| list-editable-no-items |
| list-editable-add-item-button( |
| add-item=`$ctrl.Clusters.addDataRegionConfiguration($ctrl.clonedCluster)` |
| label-single='data region configuration' |
| label-multiple='data region configurations' |
| ) |
| |
| .pc-form-grid-col-60 |
| +form-field__text({ |
| label: 'Storage path:', |
| model: `${model}.storagePath`, |
| name: '"DataStoragePath"', |
| placeholder: 'db', |
| tip: 'Directory where index and partition files are stored' |
| }) |
| .pc-form-grid-col-60 |
| +form-field__number({ |
| label: 'Checkpoint frequency:', |
| model: `${model}.checkpointFrequency`, |
| name: '"DataStorageCheckpointFrequency"', |
| placeholder: '180000', |
| min: '1', |
| tip: 'Frequency which is a minimal interval when the dirty pages will be written to the Persistent Store' |
| }) |
| .pc-form-grid-col-60(ng-if='$ctrl.available("2.7.0")') |
| +form-field__number({ |
| label: 'Checkpoint read lock timeout:', |
| model: `${model}.checkpointReadLockTimeout`, |
| name: '"DataStorageCheckpointReadLockTimeout"', |
| placeholder: 'System workers blocked timeout', |
| min: '1', |
| tip: 'Timeout for checkpoint read lock acquisition' |
| }) |
| .pc-form-grid-col-20 |
| +form-field__number({ |
| label: 'Checkpoint threads:', |
| model: `${model}.checkpointThreads`, |
| name: '"DataStorageCheckpointThreads"', |
| placeholder: '4', |
| min: '1', |
| tip: 'A number of threads to use for the checkpoint purposes' |
| }) |
| .pc-form-grid-col-20 |
| +form-field__dropdown({ |
| label: 'Checkpoint write order:', |
| model: `${model}.checkpointWriteOrder`, |
| name: '"DataStorageCheckpointWriteOrder"', |
| placeholder: 'SEQUENTIAL', |
| options: '[\ |
| {value: "RANDOM", label: "RANDOM"},\ |
| {value: "SEQUENTIAL", label: "SEQUENTIAL"}\ |
| ]', |
| tip: 'Order of writing pages to disk storage during checkpoint.\ |
| <ul>\ |
| <li>RANDOM - Pages are written in order provided by checkpoint pages collection iterator</li>\ |
| <li>SEQUENTIAL - All checkpoint pages are collected into single list and sorted by page index</li>\ |
| </ul>' |
| }) |
| .pc-form-grid-col-20 |
| +form-field__dropdown({ |
| label: 'WAL mode:', |
| model: `${model}.walMode`, |
| name: '"DataStorageWalMode"', |
| placeholder: 'DEFAULT', |
| options: '[\ |
| {value: "DEFAULT", label: "DEFAULT"},\ |
| {value: "LOG_ONLY", label: "LOG_ONLY"},\ |
| {value: "BACKGROUND", label: "BACKGROUND"},\ |
| {value: "NONE", label: "NONE"}\ |
| ]', |
| tip: 'Type define behavior wal fsync.\ |
| <ul>\ |
| <li>DEFAULT - full-sync disk writes</li>\ |
| <li>LOG_ONLY - flushes application buffers</li>\ |
| <li>BACKGROUND - does not force application's buffer flush</li>\ |
| <li>NONE - WAL is disabled</li>\ |
| </ul>' |
| }) |
| .pc-form-grid-col-60 |
| +form-field__text({ |
| label: 'WAL path:', |
| model: `${model}.walPath`, |
| name: '"DataStorageWalPath"', |
| placeholder: 'db/wal', |
| tip: 'A path to the directory where WAL is stored' |
| }) |
| .pc-form-grid-col-20 |
| +form-field__number({ |
| label: 'WAL segments:', |
| model: `${model}.walSegments`, |
| name: '"DataStorageWalSegments"', |
| placeholder: '10', |
| min: '1', |
| tip: 'A number of WAL segments to work with' |
| }) |
| .pc-form-grid-col-20 |
| +form-field__number({ |
| label: 'WAL segment size:', |
| model: `${model}.walSegmentSize`, |
| name: '"DataStorageWalSegmentSize"', |
| placeholder: '67108864', |
| min: '0', |
| tip: 'Size of a WAL segment' |
| }) |
| .pc-form-grid-col-20 |
| +form-field__number({ |
| label: 'WAL history size:', |
| model: `${model}.walHistorySize`, |
| name: '"DataStorageWalHistorySize"', |
| placeholder: '20', |
| min: '1', |
| tip: 'A total number of checkpoints to keep in the WAL history' |
| }) |
| .pc-form-grid-col-60 |
| +form-field__text({ |
| label: 'WAL archive path:', |
| model: `${model}.walArchivePath`, |
| name: '"DataStorageWalArchivePath"', |
| placeholder: 'db/wal/archive', |
| tip: 'A path to the WAL archive directory' |
| }) |
| .pc-form-grid-col-60(ng-if='$ctrl.available("2.7.0")') |
| form-field-size( |
| label='Max allowed size of WAL archives:' |
| ng-model=`${model}.maxWalArchiveSize` |
| name='DataStorageMaxWalArchiveSize' |
| placeholder='1' |
| min='1' |
| tip='Max allowed size of WAL archives' |
| size-scale-label='gb' |
| size-type='bytes' |
| ) |
| .pc-form-grid-col-60(ng-if='$ctrl.available("2.7.0")') |
| +form-field__number({ |
| label: 'WAL compaction level:', |
| model: `${model}.walCompactionLevel`, |
| name: '"DataStorageWalCompactionLevel"', |
| placeholder: '1', |
| min: '0', |
| max: '9', |
| tip: 'ZIP level to WAL compaction (0-9)' |
| }) |
| .pc-form-grid-col-60 |
| +form-field__number({ |
| label: 'WAL auto archive after inactivity:', |
| model: `${model}.walAutoArchiveAfterInactivity`, |
| name: '"DataStorageWalAutoArchiveAfterInactivity"', |
| placeholder: '-1', |
| min: '-1', |
| tip: 'Time in millis to run auto archiving segment after last record logging' |
| }) |
| .pc-form-grid-col-60(ng-if='$ctrl.available("2.4.0")') |
| +form-field__number({ |
| label: 'WAL buffer size:', |
| model: `${model}.walBufferSize`, |
| name: '"DataStorageWalBufferSize"', |
| placeholder: 'WAL segment size / 4', |
| min: '1', |
| tip: 'Size of WAL buffer' |
| }) |
| .pc-form-grid-col-30 |
| +form-field__number({ |
| label: 'WAL flush frequency:', |
| model: `${model}.walFlushFrequency`, |
| name: '"DataStorageWalFlushFrequency"', |
| placeholder: '2000', |
| min: '1', |
| tip: 'How often will be fsync, in milliseconds. In background mode, exist thread which do fsync by timeout' |
| }) |
| .pc-form-grid-col-30 |
| +form-field__number({ |
| label: 'WAL fsync delay:', |
| model: `${model}.walFsyncDelayNanos`, |
| name: '"DataStorageWalFsyncDelay"', |
| placeholder: '1000', |
| min: '1', |
| tip: 'WAL fsync delay, in nanoseconds' |
| }) |
| .pc-form-grid-col-60 |
| +form-field__number({ |
| label: 'WAL record iterator buffer size:', |
| model: `${model}.walRecordIteratorBufferSize`, |
| name: '"DataStorageWalRecordIteratorBufferSize"', |
| placeholder: '67108864', |
| min: '1', |
| tip: 'How many bytes iterator read from disk(for one reading), during go ahead WAL' |
| }) |
| .pc-form-grid-col-30 |
| +form-field__number({ |
| label: 'Lock wait time:', |
| model: `${model}.lockWaitTime`, |
| name: '"DataStorageLockWaitTime"', |
| placeholder: '10000', |
| min: '1', |
| tip: 'Time out in milliseconds, while wait and try get file lock for start persist manager' |
| }) |
| .pc-form-grid-col-30 |
| +form-field__number({ |
| label: 'WAL thread local buffer size:', |
| model: `${model}.walThreadLocalBufferSize`, |
| name: '"DataStorageWalThreadLocalBufferSize"', |
| placeholder: '131072', |
| min: '1', |
| tip: 'Define size thread local buffer. Each thread which write to WAL have thread local buffer for serialize recode before write in WAL' |
| }) |
| .pc-form-grid-col-30 |
| +form-field__number({ |
| label: 'Metrics sub interval count:', |
| model: `${model}.metricsSubIntervalCount`, |
| name: '"DataStorageMetricsSubIntervalCount"', |
| placeholder: '5', |
| min: '1', |
| tip: 'Number of sub - intervals the whole rate time interval will be split into to calculate rate - based metrics' |
| }) |
| .pc-form-grid-col-30 |
| +form-field__number({ |
| label: 'Metrics rate time interval:', |
| model: `${model}.metricsRateTimeInterval`, |
| name: '"DataStorageMetricsRateTimeInterval"', |
| placeholder: '60000', |
| min: '1000', |
| tip: 'The length of the time interval for rate - based metrics. This interval defines a window over which hits will be tracked' |
| }) |
| .pc-form-grid-col-60 |
| +form-field__dropdown({ |
| label: 'File IO factory:', |
| model: `${model}.fileIOFactory`, |
| name: '"DataStorageFileIOFactory"', |
| placeholder: 'Default', |
| options: '[\ |
| {value: "RANDOM", label: "RANDOM"},\ |
| {value: "ASYNC", label: "ASYNC"},\ |
| {value: null, label: "Default"},\ |
| ]', |
| tip: 'Order of writing pages to disk storage during checkpoint.\ |
| <ul>\ |
| <li>RANDOM - Pages are written in order provided by checkpoint pages collection iterator</li>\ |
| <li>SEQUENTIAL - All checkpoint pages are collected into single list and sorted by page index</li>\ |
| </ul>' |
| }) |
| .pc-form-grid-col-60 |
| +form-field__checkbox({ |
| label: 'Metrics enabled', |
| model: `${model}.metricsEnabled`, |
| name: '"DataStorageMetricsEnabled"', |
| tip: 'Flag indicating whether persistence metrics collection is enabled' |
| }) |
| .pc-form-grid-col-60 |
| +form-field__checkbox({ |
| label: 'Always write full pages', |
| model: `${model}.alwaysWriteFullPages`, |
| name: '"DataStorageAlwaysWriteFullPages"', |
| tip: 'Flag indicating whether always write full pages' |
| }) |
| .pc-form-grid-col-60 |
| +form-field__checkbox({ |
| label: 'Write throttling enabled', |
| model: `${model}.writeThrottlingEnabled`, |
| name: '"DataStorageWriteThrottlingEnabled"', |
| tip: 'Throttle threads that generate dirty pages too fast during ongoing checkpoint' |
| }) |
| .pc-form-grid-col-60(ng-if='$ctrl.available("2.4.0")') |
| +form-field__checkbox({ |
| label: 'Enable WAL compaction', |
| model: `${model}.walCompactionEnabled`, |
| name: '"DataStorageWalCompactionEnabled"', |
| tip: 'If true, system filters and compresses WAL archive in background' |
| }) |
| .pc-form-grid-col-60(ng-if='$ctrl.available("2.5.0")') |
| +form-field__checkbox({ |
| label: 'Authentication enabled', |
| model: `${clusterModel}.authenticationEnabled`, |
| name: '"authenticationEnabled"', |
| disabled: `!$ctrl.Clusters.persistenceEnabled(${model})`, |
| tip: 'Enable user authentication for cluster with persistence' |
| }) |
| |
| .pca-form-column-6 |
| +preview-xml-java(clusterModel, 'clusterDataStorageConfiguration') |