From 3d445cf20029f2e1ea88f3830e08a4a12a6dffd5 Mon Sep 17 00:00:00 2001 From: Mikhaylo Demianenko Date: Wed, 6 Apr 2016 10:31:46 +0200 Subject: [PATCH] Dynamic configuration of record format specific settings Reconfigure record format specific settings as soon as record format selection performed. Remove default values for properties that now are format dependent. Add couple of additional validation checks. --- .../factory/GraphDatabaseSettings.java | 14 +- .../org/neo4j/kernel/NeoStoreDataSource.java | 3 + .../impl/store/AbstractDynamicStore.java | 5 +- .../impl/store/IntStoreHeaderFormat.java | 8 +- .../neo4j/kernel/impl/store/NeoStores.java | 4 + .../neo4j/kernel/impl/store/StoreFactory.java | 11 +- .../RecordFormatPropertyConfigurator.java | 88 ++++++++ .../store/BatchingDynamicRecordAllocator.java | 74 ------- .../kernel/impl/store/NeoStoresTest.java | 29 ++- .../kernel/impl/store/RecordSizesDocTest.java | 5 +- .../kernel/impl/store/TestDynamicStore.java | 29 +-- .../RecordFormatPropertyConfiguratorTest.java | 199 ++++++++++++++++++ 12 files changed, 342 insertions(+), 127 deletions(-) create mode 100644 community/kernel/src/main/java/org/neo4j/kernel/impl/store/format/RecordFormatPropertyConfigurator.java delete mode 100644 community/kernel/src/main/java/org/neo4j/unsafe/impl/batchimport/store/BatchingDynamicRecordAllocator.java create mode 100644 community/kernel/src/test/java/org/neo4j/kernel/impl/store/format/RecordFormatPropertyConfiguratorTest.java diff --git a/community/kernel/src/main/java/org/neo4j/graphdb/factory/GraphDatabaseSettings.java b/community/kernel/src/main/java/org/neo4j/graphdb/factory/GraphDatabaseSettings.java index 5b2d5f95de74a..0957919b02f9f 100644 --- a/community/kernel/src/main/java/org/neo4j/graphdb/factory/GraphDatabaseSettings.java +++ b/community/kernel/src/main/java/org/neo4j/graphdb/factory/GraphDatabaseSettings.java @@ -39,7 +39,6 @@ import org.neo4j.kernel.impl.store.format.lowlimit.DynamicRecordFormat; import org.neo4j.logging.Level; -import static java.lang.String.valueOf; import static org.neo4j.graphdb.factory.GraphDatabaseSettings.BoltConnector.EncryptionLevel.OPTIONAL; import static org.neo4j.kernel.configuration.Settings.ANY; import static org.neo4j.kernel.configuration.Settings.BOOLEAN; @@ -70,6 +69,13 @@ */ public abstract class GraphDatabaseSettings { + /** + * Data block sizes for dynamic array stores. + */ + public static final int DEFAULT_BLOCK_SIZE = 128; + public static final int DEFAULT_LABEL_BLOCK_SIZE = 64; + public static final int MINIMAL_BLOCK_SIZE = 16; + @SuppressWarnings("unused") // accessed by reflection @Migrator private static final ConfigurationMigrator migrator = new GraphDatabaseConfigurationMigrator(); @@ -376,7 +382,7 @@ private static String defaultPageCacheMemory() "than the configured block size" ) @Internal public static final Setting string_block_size = setting("unsupported.dbms.block_size.strings", INTEGER, - valueOf( dynamicRecordDataSizeForAligningWith( 128 ) ), min( dynamicRecordDataSizeForAligningWith( 16 ) ) ); + "0", min( 0 ) ); @Description("Specifies the block size for storing arrays. This parameter is only honored when the store is " + "created, otherwise it is ignored. " + @@ -384,7 +390,7 @@ private static String defaultPageCacheMemory() "than the configured block size" ) @Internal public static final Setting array_block_size = setting("unsupported.dbms.block_size.array_properties", INTEGER, - valueOf( dynamicRecordDataSizeForAligningWith( 128 ) ), min( dynamicRecordDataSizeForAligningWith( 16 ) ) ); + "0", min( 0 ) ); @Description("Specifies the block size for storing labels exceeding in-lined space in node record. " + "This parameter is only honored when the store is created, otherwise it is ignored. " + @@ -392,7 +398,7 @@ private static String defaultPageCacheMemory() "than the configured block size" ) @Internal public static final Setting label_block_size = setting("unsupported.dbms.block_size.labels", INTEGER, - valueOf( dynamicRecordDataSizeForAligningWith( 64 ) ), min( dynamicRecordDataSizeForAligningWith( 16 ) ) ); + "0", min( 0 ) ); @Description("An identifier that uniquely identifies this graph database instance within this JVM. " + "Defaults to an auto-generated number depending on how many instance are started in this JVM.") diff --git a/community/kernel/src/main/java/org/neo4j/kernel/NeoStoreDataSource.java b/community/kernel/src/main/java/org/neo4j/kernel/NeoStoreDataSource.java index 9939906334552..3b6665f75d2e4 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/NeoStoreDataSource.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/NeoStoreDataSource.java @@ -85,6 +85,7 @@ import org.neo4j.kernel.impl.store.MetaDataStore; import org.neo4j.kernel.impl.store.StoreId; import org.neo4j.kernel.impl.store.UnderlyingStorageException; +import org.neo4j.kernel.impl.store.format.RecordFormatPropertyConfigurator; import org.neo4j.kernel.impl.store.format.RecordFormatSelector; import org.neo4j.kernel.impl.store.format.RecordFormats; import org.neo4j.kernel.impl.store.id.IdGeneratorFactory; @@ -364,7 +365,9 @@ public NeoStoreDataSource( this.tracers = tracers; this.procedures = procedures; this.ioLimiter = ioLimiter; + this.formats = RecordFormatSelector.select( config, formats, logService ); + new RecordFormatPropertyConfigurator( this.formats, this.config ).configure(); readOnly = config.get( Configuration.read_only ); msgLog = logProvider.getLog( getClass() ); diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/AbstractDynamicStore.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/AbstractDynamicStore.java index 7266ae8f94915..af63bf9769fb9 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/AbstractDynamicStore.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/AbstractDynamicStore.java @@ -65,7 +65,6 @@ public abstract class AbstractDynamicStore extends CommonAbstractStore implements DynamicRecordAllocator { - public static final byte[] NO_DATA = new byte[0]; public AbstractDynamicStore( File fileName, @@ -234,10 +233,10 @@ private static class DynamicStoreHeaderFormat extends IntStoreHeaderFormat @Override public void writeHeader( PageCursor cursor ) { - if ( defaultValue < 1 || defaultValue > 0xFFFF ) + if ( header < 1 || header > 0xFFFF ) { throw new IllegalArgumentException( - "Illegal block size[" + defaultValue + "], limit is 65535" ); + "Illegal block size[" + header + "], limit is 65535" ); } super.writeHeader( cursor ); } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/IntStoreHeaderFormat.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/IntStoreHeaderFormat.java index cfd2592559df3..7acebe195e3cb 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/IntStoreHeaderFormat.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/IntStoreHeaderFormat.java @@ -23,11 +23,11 @@ public class IntStoreHeaderFormat implements StoreHeaderFormat { - protected final int defaultValue; + protected final int header; - public IntStoreHeaderFormat( int defaultValue ) + public IntStoreHeaderFormat( int header ) { - this.defaultValue = defaultValue; + this.header = header; } @Override @@ -39,7 +39,7 @@ public int numberOfReservedRecords() @Override public void writeHeader( PageCursor cursor ) { - cursor.putInt( defaultValue ); + cursor.putInt( header ); } @Override diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/NeoStores.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/NeoStores.java index 4d14749e62ab9..5daf8a3f06717 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/NeoStores.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/NeoStores.java @@ -493,6 +493,10 @@ CommonAbstractStore createDynamicArrayStore( String storeName, IdType idType, Se CommonAbstractStore createDynamicArrayStore( String storeName, IdType idType, int blockSize ) { + if ( blockSize <= 0 ) + { + throw new IllegalArgumentException( "Block size of dynamic array store should be positive integer." ); + } File storeFile = getStoreFile( storeName ); return initialize( new DynamicArrayStore( storeFile, config, idType, idGeneratorFactory, pageCache, logProvider, blockSize, recordFormats.dynamic(), recordFormats.storeVersion() ) ); diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/StoreFactory.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/StoreFactory.java index cfb514f0f9882..245c8f3c2ec8f 100644 --- a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/StoreFactory.java +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/StoreFactory.java @@ -22,11 +22,10 @@ import java.io.File; import java.io.IOException; -import org.neo4j.graphdb.config.Setting; -import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.io.fs.FileSystemAbstraction; import org.neo4j.io.pagecache.PageCache; import org.neo4j.kernel.configuration.Config; +import org.neo4j.kernel.impl.store.format.RecordFormatPropertyConfigurator; import org.neo4j.kernel.impl.store.format.RecordFormats; import org.neo4j.kernel.impl.store.id.DefaultIdGeneratorFactory; import org.neo4j.kernel.impl.store.id.IdGeneratorFactory; @@ -87,6 +86,8 @@ public StoreFactory( File storeDir, Config config, this.idGeneratorFactory = idGeneratorFactory; this.fileSystemAbstraction = fileSystemAbstraction; this.recordFormats = recordFormats; + new RecordFormatPropertyConfigurator( recordFormats, config ).configure(); + setLogProvider( logProvider ); setStoreDir( storeDir ); this.pageCache = pageCache; @@ -182,10 +183,4 @@ public NeoStores openNeoStores( boolean createStoreIfNotExists, StoreType... sto return new NeoStores( neoStoreFileName, config, idGeneratorFactory, pageCache, logProvider, fileSystemAbstraction, recordFormats, createStoreIfNotExists, storeTypes ); } - - public abstract static class Configuration - { - public static final Setting string_block_size = GraphDatabaseSettings.string_block_size; - public static final Setting array_block_size = GraphDatabaseSettings.array_block_size; - } } diff --git a/community/kernel/src/main/java/org/neo4j/kernel/impl/store/format/RecordFormatPropertyConfigurator.java b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/format/RecordFormatPropertyConfigurator.java new file mode 100644 index 0000000000000..22dd74c0118e0 --- /dev/null +++ b/community/kernel/src/main/java/org/neo4j/kernel/impl/store/format/RecordFormatPropertyConfigurator.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2002-2016 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.kernel.impl.store.format; + +import java.util.Map; + +import org.neo4j.graphdb.config.Setting; +import org.neo4j.helpers.collection.MapUtil; +import org.neo4j.kernel.configuration.Config; + +import static org.neo4j.graphdb.factory.GraphDatabaseSettings.DEFAULT_BLOCK_SIZE; +import static org.neo4j.graphdb.factory.GraphDatabaseSettings.DEFAULT_LABEL_BLOCK_SIZE; +import static org.neo4j.graphdb.factory.GraphDatabaseSettings.MINIMAL_BLOCK_SIZE; +import static org.neo4j.graphdb.factory.GraphDatabaseSettings.array_block_size; +import static org.neo4j.graphdb.factory.GraphDatabaseSettings.label_block_size; +import static org.neo4j.graphdb.factory.GraphDatabaseSettings.string_block_size; + +/** + * There are couple of configuration options that should be adapted for each particular implementation of record format. + * In case if user already set value of those properties we will keep them, otherwise format specific value will be + * evaluated and configuration will be adapted. + */ +public class RecordFormatPropertyConfigurator +{ + private final RecordFormats recordFormats; + private final Config config; + + public RecordFormatPropertyConfigurator( RecordFormats recordFormats, Config config ) + { + this.recordFormats = recordFormats; + this.config = config; + } + + private static void configureIntegerSetting( Config config, Setting setting, + int fullBlockSize, int headerSize, Map formatConfig ) + { + Integer defaultValue = Integer.parseInt( setting.getDefaultValue() ); + int propertyValue = config.get( setting ); + if ( propertyValue == defaultValue ) + { + int updatedBlockSize = fullBlockSize - headerSize; + if ( updatedBlockSize != propertyValue ) + { + if ( updatedBlockSize < MINIMAL_BLOCK_SIZE ) + { + throw new IllegalArgumentException( "Block size should be bigger then " + MINIMAL_BLOCK_SIZE ); + } + addFormatSetting( formatConfig, setting, updatedBlockSize ); + } + } + } + + private static void addFormatSetting( Map configMap, Setting setting, int value ) + { + configMap.put( setting.name(), String.valueOf( value ) ); + } + + public void configure() + { + Map formatConfig = MapUtil.stringMap(); + int headerSize = recordFormats.dynamic().getRecordHeaderSize(); + + configureIntegerSetting( config, string_block_size, DEFAULT_BLOCK_SIZE, headerSize, formatConfig ); + configureIntegerSetting( config, array_block_size, DEFAULT_BLOCK_SIZE, headerSize, formatConfig ); + configureIntegerSetting( config, label_block_size, DEFAULT_LABEL_BLOCK_SIZE, headerSize, formatConfig ); + if ( !formatConfig.isEmpty() ) + { + config.augment( formatConfig ); + } + } +} diff --git a/community/kernel/src/main/java/org/neo4j/unsafe/impl/batchimport/store/BatchingDynamicRecordAllocator.java b/community/kernel/src/main/java/org/neo4j/unsafe/impl/batchimport/store/BatchingDynamicRecordAllocator.java deleted file mode 100644 index b8d5a1b98aeb1..0000000000000 --- a/community/kernel/src/main/java/org/neo4j/unsafe/impl/batchimport/store/BatchingDynamicRecordAllocator.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2002-2016 "Neo Technology," - * Network Engine for Objects in Lund AB [http://neotechnology.com] - * - * This file is part of Neo4j. - * - * Neo4j is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.neo4j.unsafe.impl.batchimport.store; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.neo4j.kernel.impl.store.DynamicRecordAllocator; -import org.neo4j.kernel.impl.store.id.IdSequence; -import org.neo4j.kernel.impl.store.record.DynamicRecord; - -import static java.lang.Integer.parseInt; - -import static org.neo4j.graphdb.factory.GraphDatabaseSettings.string_block_size; -import static org.neo4j.kernel.impl.store.format.lowlimit.DynamicRecordFormat.RECORD_HEADER_SIZE; - -/** - * {@link DynamicRecordAllocator} that allocates records using a {@link BatchingIdSequence} - * and makes available all allocated records. - */ -public class BatchingDynamicRecordAllocator implements DynamicRecordAllocator -{ - private final int dataSize = parseInt( string_block_size.getDefaultValue() ) - RECORD_HEADER_SIZE; - private final IdSequence idSequence; - private final List records = new ArrayList<>(); - - public BatchingDynamicRecordAllocator() - { - this( new BatchingIdSequence() ); - } - - public BatchingDynamicRecordAllocator( IdSequence idSequence ) - { - this.idSequence = idSequence; - } - - @Override - public int getRecordDataSize() - { - return dataSize; - } - - @Override - public DynamicRecord nextUsedRecordOrNew( Iterator recordsToUseFirst ) - { - DynamicRecord record = new DynamicRecord( idSequence.nextId() ); - record.setInUse( true ); - records.add( record ); - return record; - } - - public List records() - { - return records; - } -} diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/store/NeoStoresTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/store/NeoStoresTest.java index 6725ff0cd3249..9dd643bce02d8 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/store/NeoStoresTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/store/NeoStoresTest.java @@ -65,6 +65,7 @@ import org.neo4j.kernel.impl.store.format.lowlimit.DynamicRecordFormat; import org.neo4j.kernel.impl.store.format.lowlimit.LowLimitV3_0; import org.neo4j.kernel.impl.store.id.DefaultIdGeneratorFactory; +import org.neo4j.kernel.impl.store.id.IdType; import org.neo4j.kernel.impl.store.record.PropertyBlock; import org.neo4j.kernel.impl.store.record.PropertyKeyTokenRecord; import org.neo4j.kernel.impl.store.record.PropertyRecord; @@ -102,15 +103,13 @@ public class NeoStoresTest private final PageCacheRule pageCacheRule = new PageCacheRule(); private final ExpectedException exception = ExpectedException.none(); + private EphemeralFileSystemRule fs = new EphemeralFileSystemRule(); + private TargetDirectory.TestDirectory dir = TargetDirectory.testDirForTestWithEphemeralFS( fs.get(), getClass() ); + private NeoStoreDataSourceRule dsRule = new NeoStoreDataSourceRule(); @Rule - public EphemeralFileSystemRule fs = new EphemeralFileSystemRule(); - @Rule - public TargetDirectory.TestDirectory dir = TargetDirectory.testDirForTestWithEphemeralFS( fs.get(), getClass() ); - @Rule - public NeoStoreDataSourceRule dsRule = new NeoStoreDataSourceRule(); - @Rule - public RuleChain ruleChain = RuleChain.outerRule( exception ).around( pageCacheRule ); + public RuleChain ruleChain = RuleChain.outerRule( exception ).around( pageCacheRule ) + .around( fs ).around( dir ).around( dsRule ); private PageCache pageCache; private File storeDir; @@ -150,6 +149,22 @@ public void impossibleToGetStoreFromClosedNeoStoresContainer() neoStores.getMetaDataStore(); } + @Test + public void notAllowCreateDynamicStoreWithNegativeBlockSize() + { + Config config = new Config( new HashMap<>(), GraphDatabaseSettings.class ); + StoreFactory sf = new StoreFactory( storeDir, config, new DefaultIdGeneratorFactory( fs.get() ), pageCache, + fs.get(), LowLimitV3_0.RECORD_FORMATS, NullLogProvider.getInstance() ); + + exception.expect( IllegalArgumentException.class ); + exception.expectMessage( "Block size of dynamic array store should be positive integer." ); + + try (NeoStores neoStores = sf.openNeoStores( true )) + { + neoStores.createDynamicArrayStore( "someStore", IdType.ARRAY_BLOCK, -2 ); + } + } + @Test public void impossibleToGetNotRequestedStore() { diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/store/RecordSizesDocTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/store/RecordSizesDocTest.java index db094c31b611a..ce4538e537f7d 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/store/RecordSizesDocTest.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/store/RecordSizesDocTest.java @@ -30,14 +30,13 @@ import org.neo4j.test.docs.DocsIncludeFile; import static java.util.Arrays.asList; - +import static org.neo4j.graphdb.factory.GraphDatabaseSettings.array_block_size; +import static org.neo4j.graphdb.factory.GraphDatabaseSettings.string_block_size; import static org.neo4j.kernel.impl.store.StoreFactory.NODE_STORE_NAME; import static org.neo4j.kernel.impl.store.StoreFactory.PROPERTY_ARRAYS_STORE_NAME; import static org.neo4j.kernel.impl.store.StoreFactory.PROPERTY_STORE_NAME; import static org.neo4j.kernel.impl.store.StoreFactory.PROPERTY_STRINGS_STORE_NAME; import static org.neo4j.kernel.impl.store.StoreFactory.RELATIONSHIP_STORE_NAME; -import static org.neo4j.kernel.impl.store.StoreFactory.Configuration.array_block_size; -import static org.neo4j.kernel.impl.store.StoreFactory.Configuration.string_block_size; public class RecordSizesDocTest { diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/store/TestDynamicStore.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/store/TestDynamicStore.java index ec0b8b177381e..18aca093355e0 100644 --- a/community/kernel/src/test/java/org/neo4j/kernel/impl/store/TestDynamicStore.java +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/store/TestDynamicStore.java @@ -19,6 +19,11 @@ */ package org.neo4j.kernel.impl.store; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; + import java.io.File; import java.util.ArrayList; import java.util.Collection; @@ -28,13 +33,6 @@ import java.util.Random; import java.util.Set; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; - -import org.neo4j.graphdb.config.InvalidSettingException; -import org.neo4j.graphdb.config.Setting; import org.neo4j.graphdb.factory.GraphDatabaseSettings; import org.neo4j.helpers.collection.Iterables; import org.neo4j.helpers.collection.Iterators; @@ -47,7 +45,6 @@ import org.neo4j.test.EphemeralFileSystemRule; import org.neo4j.test.PageCacheRule; -import static java.util.Collections.singletonMap; import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import static org.neo4j.kernel.impl.store.record.RecordLoad.NORMAL; @@ -83,22 +80,6 @@ public void tearDown() } } - @Test( expected = InvalidSettingException.class ) - public void stringStoreCannotHaveZeroBlockSize() - { - Setting setting = StoreFactory.Configuration.string_block_size; - setting.apply( singletonMap( setting.name(), "0" )::get ); - fail( "Illegal blocksize should throw exception" ); - } - - @Test( expected = InvalidSettingException.class ) - public void arrayStoreCannotHaveZeroBlockSize() throws Exception - { - Setting setting = StoreFactory.Configuration.array_block_size; - setting.apply( singletonMap( setting.name(), "0" )::get ); - fail( "Illegal blocksize should throw exception" ); - } - private DynamicArrayStore createDynamicArrayStore() { neoStores = storeFactory.openAllNeoStores( true ); diff --git a/community/kernel/src/test/java/org/neo4j/kernel/impl/store/format/RecordFormatPropertyConfiguratorTest.java b/community/kernel/src/test/java/org/neo4j/kernel/impl/store/format/RecordFormatPropertyConfiguratorTest.java new file mode 100644 index 0000000000000..87e428997057d --- /dev/null +++ b/community/kernel/src/test/java/org/neo4j/kernel/impl/store/format/RecordFormatPropertyConfiguratorTest.java @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2002-2016 "Neo Technology," + * Network Engine for Objects in Lund AB [http://neotechnology.com] + * + * This file is part of Neo4j. + * + * Neo4j is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.neo4j.kernel.impl.store.format; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import org.neo4j.helpers.collection.MapUtil; +import org.neo4j.kernel.configuration.Config; +import org.neo4j.kernel.impl.store.format.lowlimit.LowLimitV3_0; +import org.neo4j.kernel.impl.store.format.lowlimit.NoRecordFormat; +import org.neo4j.kernel.impl.store.record.DynamicRecord; +import org.neo4j.kernel.impl.store.record.LabelTokenRecord; +import org.neo4j.kernel.impl.store.record.MetaDataRecord; +import org.neo4j.kernel.impl.store.record.NodeRecord; +import org.neo4j.kernel.impl.store.record.PropertyKeyTokenRecord; +import org.neo4j.kernel.impl.store.record.PropertyRecord; +import org.neo4j.kernel.impl.store.record.RelationshipGroupRecord; +import org.neo4j.kernel.impl.store.record.RelationshipRecord; +import org.neo4j.kernel.impl.store.record.RelationshipTypeTokenRecord; + +import static org.junit.Assert.assertEquals; +import static org.neo4j.graphdb.factory.GraphDatabaseSettings.DEFAULT_BLOCK_SIZE; +import static org.neo4j.graphdb.factory.GraphDatabaseSettings.DEFAULT_LABEL_BLOCK_SIZE; +import static org.neo4j.graphdb.factory.GraphDatabaseSettings.MINIMAL_BLOCK_SIZE; +import static org.neo4j.graphdb.factory.GraphDatabaseSettings.array_block_size; +import static org.neo4j.graphdb.factory.GraphDatabaseSettings.label_block_size; +import static org.neo4j.graphdb.factory.GraphDatabaseSettings.string_block_size; + +public class RecordFormatPropertyConfiguratorTest +{ + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Test + public void keepUserDefinedFormatConfig() throws Exception + { + Config config = new Config( MapUtil.stringMap( string_block_size.name(), "36" ) ); + RecordFormats recordFormats = LowLimitV3_0.RECORD_FORMATS; + new RecordFormatPropertyConfigurator( recordFormats, config ).configure(); + assertEquals( "Should keep used specified value", 36, config.get( string_block_size ).intValue() ); + } + + @Test + public void overrideDefaultValuesForCurrentFormat() + { + Config config = Config.empty(); + int testHeaderSize = 17; + ResizableRecordFormats recordFormats = new ResizableRecordFormats( testHeaderSize ); + + new RecordFormatPropertyConfigurator( recordFormats, config ).configure(); + + assertEquals( DEFAULT_BLOCK_SIZE - testHeaderSize, config.get( string_block_size ).intValue() ); + assertEquals( DEFAULT_BLOCK_SIZE - testHeaderSize, config.get( array_block_size ).intValue() ); + assertEquals( DEFAULT_LABEL_BLOCK_SIZE - testHeaderSize, config.get( label_block_size ).intValue() ); + } + + @Test + public void checkForMinimumBlockSize() + { + Config config = Config.empty(); + int testHeaderSize = 60; + ResizableRecordFormats recordFormats = new ResizableRecordFormats( testHeaderSize ); + + expectedException.expect( IllegalArgumentException.class ); + expectedException.expectMessage( "Block size should be bigger then " + MINIMAL_BLOCK_SIZE ); + + new RecordFormatPropertyConfigurator( recordFormats, config ).configure(); + } + + private class ResizableRecordFormats implements RecordFormats + { + + private int dynamicRecordHeaderSize; + + public ResizableRecordFormats(int dynamicRecordHeaderSize) + { + this.dynamicRecordHeaderSize = dynamicRecordHeaderSize; + } + + @Override + public String storeVersion() + { + return null; + } + + @Override + public int generation() + { + return 0; + } + + @Override + public RecordFormat node() + { + return null; + } + + @Override + public RecordFormat relationshipGroup() + { + return null; + } + + @Override + public RecordFormat relationship() + { + return null; + } + + @Override + public RecordFormat property() + { + return null; + } + + @Override + public RecordFormat labelToken() + { + return null; + } + + @Override + public RecordFormat propertyKeyToken() + { + return null; + } + + @Override + public RecordFormat relationshipTypeToken() + { + return null; + } + + @Override + public RecordFormat dynamic() + { + return new ResizableRecordFormat(dynamicRecordHeaderSize); + } + + @Override + public RecordFormat metaData() + { + return null; + } + + @Override + public Capability[] capabilities() + { + return new Capability[0]; + } + + @Override + public boolean hasCapability( Capability capability ) + { + return false; + } + + @Override + public boolean hasSameCapabilities( RecordFormats other, CapabilityType type ) + { + return false; + } + } + + private class ResizableRecordFormat extends NoRecordFormat + { + private int headerSize; + + ResizableRecordFormat( int headerSize ) + { + this.headerSize = headerSize; + } + + @Override + public int getRecordHeaderSize() + { + return headerSize; + } + } +} \ No newline at end of file