├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── .gitignore ├── Jenkinsfile ├── src ├── main │ └── java │ │ ├── org │ │ └── terracotta │ │ │ └── offheapstore │ │ │ ├── storage │ │ │ ├── listener │ │ │ │ ├── StorageEngineListener.java │ │ │ │ ├── ListenableStorageEngine.java │ │ │ │ ├── RecoveryStorageEngineListener.java │ │ │ │ └── RuntimeStorageEngineListener.java │ │ │ ├── portability │ │ │ │ ├── WriteContext.java │ │ │ │ ├── WriteBackPortability.java │ │ │ │ ├── BooleanPortability.java │ │ │ │ ├── Portability.java │ │ │ │ ├── StringPortability.java │ │ │ │ └── ByteArrayPortability.java │ │ │ ├── PointerSize.java │ │ │ ├── allocator │ │ │ │ └── Allocator.java │ │ │ ├── BinaryStorageEngine.java │ │ │ ├── StringStorageEngine.java │ │ │ ├── SerializableStorageEngine.java │ │ │ ├── BooleanHalfStorageEngine.java │ │ │ ├── PortabilityBasedHalfStorageEngine.java │ │ │ └── IntegerStorageEngine.java │ │ │ ├── Metadata.java │ │ │ ├── pinning │ │ │ ├── PinnableSegment.java │ │ │ └── PinnableCache.java │ │ │ ├── disk │ │ │ ├── persistent │ │ │ │ ├── PersistentPortability.java │ │ │ │ ├── PersistentStorageEngine.java │ │ │ │ ├── PersistentHalfStorageEngine.java │ │ │ │ ├── Persistent.java │ │ │ │ ├── PersistentReadWriteLockedOffHeapClockCache.java │ │ │ │ ├── PersistentReadWriteLockedOffHeapHashMap.java │ │ │ │ ├── PersistentConcurrentOffHeapHashMap.java │ │ │ │ └── PersistentConcurrentOffHeapClockCache.java │ │ │ ├── paging │ │ │ │ └── MappedPage.java │ │ │ └── storage │ │ │ │ ├── portability │ │ │ │ └── PersistentByteArrayPortability.java │ │ │ │ ├── PersistentIntegerStorageEngine.java │ │ │ │ └── PersistentSplitStorageEngine.java │ │ │ ├── concurrent │ │ │ ├── ConcurrentMapInternals.java │ │ │ └── ConcurrentWriteLockedOffHeapHashMap.java │ │ │ ├── util │ │ │ ├── Factory.java │ │ │ ├── FindbugsSuppressWarnings.java │ │ │ ├── Validation.java │ │ │ ├── ByteBufferUtils.java │ │ │ ├── NoOpLock.java │ │ │ ├── MemoryUnit.java │ │ │ ├── DebuggingUtils.java │ │ │ └── ByteBufferInputStream.java │ │ │ ├── buffersource │ │ │ ├── HeapBufferSource.java │ │ │ ├── BufferSource.java │ │ │ └── OffHeapBufferSource.java │ │ │ ├── HashingMap.java │ │ │ ├── MapInternals.java │ │ │ ├── exceptions │ │ │ └── OversizeMappingException.java │ │ │ ├── eviction │ │ │ ├── EvictionListener.java │ │ │ ├── EvictionListeningWriteLockedOffHeapClockCache.java │ │ │ └── EvictionListeningReadWriteLockedOffHeapClockCache.java │ │ │ ├── paging │ │ │ ├── UnlimitedPageSource.java │ │ │ ├── PageSource.java │ │ │ └── Page.java │ │ │ ├── MetadataTuple.java │ │ │ ├── WriteLockedOffHeapHashMap.java │ │ │ ├── ReadWriteLockedOffHeapHashMap.java │ │ │ ├── set │ │ │ └── OffHeapHashSet.java │ │ │ ├── ReadWriteLockedOffHeapClockCache.java │ │ │ └── WriteLockedOffHeapClockCache.java │ │ └── com │ │ └── terracottatech │ │ └── offheapstore │ │ ├── storage │ │ └── restartable │ │ │ ├── LinkedNode.java │ │ │ ├── DetachedLinkedNode.java │ │ │ └── PersistentRestartableStorageEngine.java │ │ └── filesystem │ │ ├── SeekableOutputStream.java │ │ ├── Directory.java │ │ └── SeekableInputStream.java └── test │ ├── resources │ └── logback-test.xml │ └── java │ ├── org │ └── terracotta │ │ └── offheapstore │ │ ├── disk │ │ ├── AbstractDiskTest.java │ │ ├── storage │ │ │ └── portability │ │ │ │ └── PersistentSerializablePortabilityTest.java │ │ └── OffHeapDiskMapClearingIT.java │ │ ├── util │ │ ├── ParallelParameterized.java │ │ ├── ValidationTest.java │ │ ├── PointerSizeParameterizedTest.java │ │ └── RetryAssert.java │ │ ├── buffersource │ │ ├── HeapBufferSourceTest.java │ │ └── OffHeapBufferSourceTest.java │ │ ├── storage │ │ ├── listener │ │ │ ├── OffHeapBufferStorageEngineListenerIT.java │ │ │ └── FileBackedStorageEngineListenerIT.java │ │ ├── portability │ │ │ ├── ByteArrayPortabilityTest.java │ │ │ ├── StringPortabilityTest.java │ │ │ └── serializable │ │ │ │ └── ArrayPackageScopeTest.java │ │ └── SerializableStorageEngineIT.java │ │ ├── OffHeapHashMapTableResizeIT.java │ │ ├── CapacityLimitedIntegerStorageEngineFactory.java │ │ ├── pinning │ │ ├── ConcurrentPinningIT.java │ │ ├── WriteLockedPinningIT.java │ │ ├── ConcurrentWriteLockedPinningIT.java │ │ └── ReadWriteLockedPinningIT.java │ │ ├── WriteLockedOffHeapHashMapIT.java │ │ ├── ReadWriteLockedOffHeapHashMapIT.java │ │ ├── TimeoutTest.java │ │ └── paging │ │ └── OffHeapStorageAreaLimitIT.java │ └── com │ └── terracottatech │ └── offheapstore │ ├── util │ ├── ParallelParameterized.java │ └── PointerSizeParameterizedTest.java │ └── storage │ ├── restartable │ ├── RestartabilityTestUtilities.java │ ├── RestartableOffHeapBufferStorageEngineIT.java │ ├── partial │ │ ├── KeysOnlyRestartableStorageEngineIT.java │ │ ├── PartialRestartableStorageEngineIT.java │ │ ├── MinimalCacheRestartabilityIT.java │ │ ├── PartialCacheRestartabilityIT.java │ │ └── KeysOnlyCacheRestartabilityIT.java │ └── RestartableFileBackedStorageEngineIT.java │ └── portability │ └── serializable │ └── ArrayPackageScopeTest.java ├── .editorconfig ├── azure-pipelines.yml └── README.adoc /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Terracotta-OSS/offheap-store/HEAD/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Maven exclusions 2 | target/ 3 | 4 | # IntelliJ exclusions 5 | /.idea/ 6 | *.iml 7 | 8 | # Eclipse exclusions 9 | .settings/ 10 | .classpath/ 11 | 12 | # Netbeans exclusions 13 | nb-configuration.xml 14 | -------------------------------------------------------------------------------- /Jenkinsfile: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright IBM Corp. 2024, 2025 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | //See Jenkins wiki pages for info 18 | mavenBuildOSS() 19 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/storage/listener/StorageEngineListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.storage.listener; 18 | 19 | /** 20 | * 21 | * @author cdennis 22 | */ 23 | public interface StorageEngineListener { 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/storage/portability/WriteContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.storage.portability; 18 | 19 | public interface WriteContext { 20 | 21 | void setLong(int offset, long value); 22 | 23 | void flush(); 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/Metadata.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore; 18 | 19 | public final class Metadata { 20 | 21 | public static final int PINNED = 1 << (Integer.SIZE - 2); 22 | 23 | private Metadata() { 24 | //static class 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/pinning/PinnableSegment.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.pinning; 18 | 19 | import org.terracotta.offheapstore.Segment; 20 | 21 | public interface PinnableSegment extends Segment, PinnableCache { 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/storage/listener/ListenableStorageEngine.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.storage.listener; 18 | 19 | public interface ListenableStorageEngine { 20 | 21 | void registerListener(StorageEngineListener listener); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/storage/portability/WriteBackPortability.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.storage.portability; 18 | 19 | import java.nio.ByteBuffer; 20 | 21 | public interface WriteBackPortability extends Portability { 22 | 23 | T decode(ByteBuffer buffer, WriteContext context); 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/disk/persistent/PersistentPortability.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.disk.persistent; 18 | 19 | import org.terracotta.offheapstore.storage.portability.Portability; 20 | 21 | /** 22 | * 23 | * @author Chris Dennis 24 | */ 25 | public interface PersistentPortability extends Portability, Persistent { 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/disk/persistent/PersistentStorageEngine.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.disk.persistent; 18 | 19 | import org.terracotta.offheapstore.storage.StorageEngine; 20 | 21 | /** 22 | * 23 | * @author Chris Dennis 24 | */ 25 | public interface PersistentStorageEngine extends StorageEngine, Persistent { 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/disk/persistent/PersistentHalfStorageEngine.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.disk.persistent; 18 | 19 | import org.terracotta.offheapstore.storage.HalfStorageEngine; 20 | 21 | /** 22 | * 23 | * @author cdennis 24 | */ 25 | public interface PersistentHalfStorageEngine extends HalfStorageEngine, Persistent { 26 | 27 | } 28 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 18 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar 19 | -------------------------------------------------------------------------------- /src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 19 | 20 | 21 | 22 | 23 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/concurrent/ConcurrentMapInternals.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.concurrent; 18 | 19 | import org.terracotta.offheapstore.MapInternals; 20 | 21 | import java.util.List; 22 | 23 | /** 24 | * 25 | * @author Chris Dennis 26 | */ 27 | public interface ConcurrentMapInternals extends MapInternals { 28 | 29 | List getSegmentInternals(); 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/util/Factory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.util; 18 | 19 | /** 20 | * A generic instance factory. 21 | * 22 | * @param type constructed by the factory 23 | * 24 | * @author Chris Dennis 25 | */ 26 | public interface Factory { 27 | 28 | /** 29 | * Create a new instance. 30 | * 31 | * @return a new instance 32 | */ 33 | T newInstance(); 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/pinning/PinnableCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.pinning; 18 | 19 | import java.util.concurrent.ConcurrentMap; 20 | 21 | public interface PinnableCache extends ConcurrentMap { 22 | 23 | boolean isPinned(Object key); 24 | 25 | void setPinning(K key, boolean pinned); 26 | 27 | V putPinned(final K key, final V value); 28 | 29 | V getAndPin(final K key); 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/storage/PointerSize.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.storage; 18 | 19 | public enum PointerSize { 20 | 21 | INT(Integer.SIZE), LONG(Long.SIZE); 22 | 23 | private final int size; 24 | 25 | PointerSize(int size) { 26 | this.size = size; 27 | } 28 | 29 | public int bitSize() { 30 | return size; 31 | } 32 | 33 | public int byteSize() { 34 | return size / Byte.SIZE; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/terracottatech/offheapstore/storage/restartable/LinkedNode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.terracottatech.offheapstore.storage.restartable; 18 | 19 | 20 | public interface LinkedNode { 21 | 22 | long getLsn(); 23 | 24 | void setLsn(long lsn); 25 | 26 | long getNext(); 27 | long getPrevious(); 28 | 29 | void setNext(long encoding); 30 | void setPrevious(long encoding); 31 | 32 | T getValue(); 33 | 34 | void flush(); 35 | 36 | int getMetadata(); 37 | } 38 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2016-2023 Terracotta, Inc., a Software AG company. 3 | # Copyright IBM Corp. 2024, 2025 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | 18 | # EditorConfig helps developers define and maintain consistent 19 | # coding styles between different editors and IDEs 20 | # editorconfig.org 21 | 22 | root = true 23 | 24 | [*] 25 | 26 | # Change these settings to your own preference 27 | indent_style = space 28 | indent_size = 2 29 | 30 | # We recommend you to keep these unchanged 31 | end_of_line = lf 32 | charset = utf-8 33 | trim_trailing_whitespace = true 34 | insert_final_newline = true 35 | 36 | [*.{md,adoc}] 37 | trim_trailing_whitespace = false 38 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/buffersource/HeapBufferSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.buffersource; 18 | 19 | import java.nio.ByteBuffer; 20 | 21 | /** 22 | * 23 | * @author cdennis 24 | */ 25 | public class HeapBufferSource implements BufferSource { 26 | 27 | @Override 28 | public ByteBuffer allocateBuffer(int size) { 29 | return ByteBuffer.allocate(size); 30 | } 31 | 32 | @Override 33 | public String toString() { 34 | return "On-Heap Buffer Source"; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/HashingMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore; 18 | 19 | import java.util.Map; 20 | 21 | /** 22 | * Interface of all map implementations based on hash-coding. 23 | */ 24 | public interface HashingMap extends Map { 25 | 26 | /** 27 | * Remove all keys having a specific hashcode. 28 | * @param keyHash the hashcode of the keys to be removed. 29 | * @return a {@link Map} containing the removed mappings. 30 | */ 31 | Map removeAllWithHash(int keyHash); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/disk/paging/MappedPage.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.disk.paging; 18 | 19 | import java.nio.MappedByteBuffer; 20 | 21 | import org.terracotta.offheapstore.paging.Page; 22 | 23 | /** 24 | * 25 | * @author cdennis 26 | */ 27 | public class MappedPage extends Page { 28 | 29 | public MappedPage(MappedByteBuffer buffer) { 30 | super(buffer, null); 31 | } 32 | 33 | @Override 34 | public MappedByteBuffer asByteBuffer() { 35 | return (MappedByteBuffer) super.asByteBuffer(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/disk/persistent/Persistent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.disk.persistent; 18 | 19 | import java.io.IOException; 20 | import java.io.ObjectInput; 21 | import java.io.ObjectOutput; 22 | 23 | /** 24 | * 25 | * @author Chris Dennis 26 | */ 27 | public interface Persistent { 28 | 29 | void flush() throws IOException; 30 | 31 | void close() throws IOException; 32 | 33 | void persist(ObjectOutput output) throws IOException; 34 | 35 | void bootstrap(ObjectInput input) throws IOException; 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/storage/listener/RecoveryStorageEngineListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.storage.listener; 18 | 19 | import java.nio.ByteBuffer; 20 | import java.util.concurrent.Callable; 21 | 22 | /** 23 | * 24 | * @author cdennis 25 | */ 26 | public interface RecoveryStorageEngineListener extends StorageEngineListener { 27 | 28 | void recovered(Callable key, Callable value, ByteBuffer binaryKey, ByteBuffer binaryValue, int hash, int metadata, long encoding); 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/storage/allocator/Allocator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.storage.allocator; 18 | 19 | public interface Allocator extends Iterable { 20 | 21 | long allocate(long size); 22 | 23 | void free(long address); 24 | 25 | void clear(); 26 | 27 | void expand(long size); 28 | 29 | long occupied(); 30 | 31 | void validateAllocator(); 32 | 33 | long getLastUsedAddress(); 34 | 35 | long getLastUsedPointer(); 36 | 37 | int getMinimalSize(); 38 | 39 | long getMaximumAddress(); 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/storage/listener/RuntimeStorageEngineListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.storage.listener; 18 | 19 | import java.nio.ByteBuffer; 20 | 21 | 22 | public interface RuntimeStorageEngineListener extends StorageEngineListener { 23 | 24 | void written(K key, V value, ByteBuffer binaryKey, ByteBuffer binaryValue, int hash, int metadata, long encoding); 25 | 26 | void freed(long encoding, int hash, ByteBuffer binaryKey, boolean removed); 27 | 28 | void cleared(); 29 | 30 | void copied(int hash, long oldEncoding, long newEncoding, int metadata); 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/util/FindbugsSuppressWarnings.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.util; 18 | 19 | import java.lang.annotation.ElementType; 20 | import java.lang.annotation.Retention; 21 | import java.lang.annotation.RetentionPolicy; 22 | import java.lang.annotation.Target; 23 | 24 | @Target(value = {ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.CONSTRUCTOR, ElementType.LOCAL_VARIABLE, ElementType.PACKAGE}) 25 | @Retention(value = RetentionPolicy.CLASS) 26 | public @interface FindbugsSuppressWarnings { 27 | 28 | String[] value() default {}; 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/org/terracotta/offheapstore/disk/AbstractDiskTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.disk; 18 | 19 | import java.io.File; 20 | import java.io.IOException; 21 | 22 | import org.junit.After; 23 | import org.junit.Before; 24 | 25 | /** 26 | * 27 | * @author Chris Dennis 28 | */ 29 | public abstract class AbstractDiskTest { 30 | 31 | protected File dataFile; 32 | 33 | @Before 34 | public void createDataFile() throws IOException { 35 | dataFile = File.createTempFile(getClass().getSimpleName(), ".data"); 36 | dataFile.deleteOnExit(); 37 | } 38 | 39 | @After 40 | public void destroyDataFile() { 41 | dataFile.delete(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/MapInternals.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore; 18 | 19 | /** 20 | * 21 | * @author Chris Dennis 22 | */ 23 | public interface MapInternals { 24 | 25 | /* Map oriented statistics */ 26 | 27 | long getSize(); 28 | 29 | long getTableCapacity(); 30 | 31 | long getUsedSlotCount(); 32 | 33 | long getRemovedSlotCount(); 34 | 35 | int getReprobeLength(); 36 | 37 | long getAllocatedMemory(); 38 | 39 | long getOccupiedMemory(); 40 | 41 | long getVitalMemory(); 42 | 43 | long getDataAllocatedMemory(); 44 | 45 | long getDataOccupiedMemory(); 46 | 47 | long getDataVitalMemory(); 48 | 49 | long getDataSize(); 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/storage/BinaryStorageEngine.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.storage; 18 | 19 | import java.nio.ByteBuffer; 20 | 21 | /** 22 | * 23 | * @author cdennis 24 | */ 25 | public interface BinaryStorageEngine { 26 | 27 | int readKeyHash(long encoding); 28 | 29 | ByteBuffer readBinaryKey(long encoding); 30 | 31 | ByteBuffer readBinaryValue(long encoding); 32 | 33 | boolean equalsBinaryKey(ByteBuffer probeKey, long encoding); 34 | 35 | Long writeBinaryMapping(ByteBuffer binaryKey, ByteBuffer binaryValue, int pojoHash, int metadata); 36 | 37 | Long writeBinaryMapping(ByteBuffer[] binaryKey, ByteBuffer[] binaryValue, int pojoHash, int metadata); 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/buffersource/BufferSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.buffersource; 18 | 19 | import java.nio.ByteBuffer; 20 | 21 | /** 22 | * A source of NIO buffers of some type. 23 | * 24 | * @author Chris Dennis 25 | */ 26 | public interface BufferSource { 27 | 28 | /** 29 | * Allocates a buffer of the given size. 30 | *

31 | * If a suitable buffer cannot be allocated then {@code null} should be 32 | * returned. Implementations may place restrictions on the valid size value 33 | * they will accept. 34 | * 35 | * @param size required buffer size 36 | * @return a buffer of the required size 37 | */ 38 | ByteBuffer allocateBuffer(int size); 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/exceptions/OversizeMappingException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.exceptions; 18 | 19 | /** 20 | * 21 | * @author Chris Dennis 22 | */ 23 | public class OversizeMappingException extends IllegalArgumentException { 24 | 25 | private static final long serialVersionUID = 3918022751469816074L; 26 | 27 | public OversizeMappingException() { 28 | super(); 29 | } 30 | 31 | public OversizeMappingException(String s) { 32 | super(s); 33 | } 34 | 35 | public OversizeMappingException(String message, Throwable cause) { 36 | super(message, cause); 37 | } 38 | 39 | public OversizeMappingException(Throwable cause) { 40 | super(cause); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/test/java/org/terracotta/offheapstore/util/ParallelParameterized.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.util; 18 | 19 | import org.junit.runner.Runner; 20 | import org.junit.runners.Parameterized; 21 | import org.junit.runners.ParentRunner; 22 | import org.junit.runners.model.RunnerScheduler; 23 | 24 | public class ParallelParameterized extends Parameterized { 25 | 26 | public ParallelParameterized(Class klass) throws Throwable { 27 | super(klass); 28 | } 29 | 30 | @Override 31 | public void setScheduler(RunnerScheduler scheduler) { 32 | for (Runner child : getChildren()) { 33 | if (child instanceof ParentRunner) { 34 | ((ParentRunner) child).setScheduler(scheduler); 35 | } 36 | } 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/test/java/com/terracottatech/offheapstore/util/ParallelParameterized.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.terracottatech.offheapstore.util; 18 | 19 | import org.junit.runner.Runner; 20 | import org.junit.runners.Parameterized; 21 | import org.junit.runners.ParentRunner; 22 | import org.junit.runners.model.RunnerScheduler; 23 | 24 | public class ParallelParameterized extends Parameterized { 25 | 26 | public ParallelParameterized(Class klass) throws Throwable { 27 | super(klass); 28 | } 29 | 30 | @Override 31 | public void setScheduler(RunnerScheduler scheduler) { 32 | for (Runner child : getChildren()) { 33 | if (child instanceof ParentRunner) { 34 | ((ParentRunner) child).setScheduler(scheduler); 35 | } 36 | } 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/test/java/org/terracotta/offheapstore/util/ValidationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.util; 18 | 19 | import org.terracotta.offheapstore.util.Validation; 20 | import org.junit.Assert; 21 | import org.junit.Test; 22 | 23 | /** 24 | * 25 | * @author cdennis 26 | */ 27 | public class ValidationTest { 28 | 29 | @Test 30 | public void testValidatingInTests() { 31 | Assert.assertTrue(Validation.shouldValidate(Validation.class)); 32 | Assert.assertTrue(Validation.shouldValidate(null)); 33 | } 34 | 35 | @Test 36 | public void testValidations() { 37 | Validation.validate(true); 38 | try { 39 | Validation.validate(false); 40 | Assert.fail(); 41 | } catch (AssertionError e) { 42 | //expected 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/eviction/EvictionListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.eviction; 18 | 19 | import java.util.Map.Entry; 20 | import java.util.concurrent.Callable; 21 | 22 | /** 23 | * Listener interface used to monitor eviction in off-heap caches. 24 | * 25 | * @author Chris Dennis 26 | */ 27 | public interface EvictionListener { 28 | 29 | /** 30 | * Called prior to the eviction of a cache mapping. 31 | *

32 | * Implementors must be careful to not expose the callable outside the scope 33 | * of this method. The behavior of the callable becomes undefined on return 34 | * from this method. 35 | * 36 | * @param callable callable for retrieving the evictee 37 | */ 38 | void evicting(Callable> callable); 39 | } 40 | -------------------------------------------------------------------------------- /src/test/java/org/terracotta/offheapstore/buffersource/HeapBufferSourceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.buffersource; 18 | 19 | import org.terracotta.offheapstore.buffersource.HeapBufferSource; 20 | import java.nio.ByteBuffer; 21 | import java.util.Random; 22 | 23 | import org.junit.Assert; 24 | import org.junit.Test; 25 | 26 | /** 27 | * 28 | * @author Chris Dennis 29 | */ 30 | public class HeapBufferSourceTest { 31 | 32 | @Test 33 | public void testAllocatedBufferProperties() { 34 | Random rndm = new Random(); 35 | 36 | int size = rndm.nextInt(1024); 37 | ByteBuffer buffer = new HeapBufferSource().allocateBuffer(size); 38 | 39 | Assert.assertFalse(buffer.isDirect()); 40 | Assert.assertEquals(size, buffer.capacity()); 41 | Assert.assertEquals(size, buffer.remaining()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/org/terracotta/offheapstore/buffersource/OffHeapBufferSourceTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.buffersource; 18 | 19 | import org.terracotta.offheapstore.buffersource.HeapBufferSource; 20 | import java.nio.ByteBuffer; 21 | import java.util.Random; 22 | 23 | import org.junit.Assert; 24 | import org.junit.Test; 25 | 26 | /** 27 | * 28 | * @author cdennis 29 | */ 30 | public class OffHeapBufferSourceTest { 31 | 32 | @Test 33 | public void testAllocatedBufferProperties() { 34 | Random rndm = new Random(); 35 | 36 | int size = rndm.nextInt(1024); 37 | ByteBuffer buffer = new HeapBufferSource().allocateBuffer(size); 38 | 39 | Assert.assertFalse(buffer.isDirect()); 40 | Assert.assertEquals(size, buffer.capacity()); 41 | Assert.assertEquals(size, buffer.remaining()); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/util/Validation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.util; 18 | 19 | /** 20 | * 21 | * @author Chris Dennis 22 | */ 23 | public final class Validation { 24 | 25 | private static final boolean VALIDATE_ALL; 26 | static { 27 | boolean validate; 28 | try { 29 | Class.forName("org.terracotta.offheapstore.util.ValidationTest"); 30 | validate = true; 31 | } catch (Throwable t) { 32 | validate = false; 33 | } 34 | VALIDATE_ALL = validate; 35 | } 36 | 37 | public static boolean shouldValidate(Class klazz) { 38 | return VALIDATE_ALL || Boolean.getBoolean(klazz.getName() + ".VALIDATE"); 39 | } 40 | 41 | public static void validate(boolean assertion) { 42 | if (!assertion) { 43 | throw new AssertionError(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/paging/UnlimitedPageSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.paging; 18 | 19 | import java.nio.ByteBuffer; 20 | 21 | import org.terracotta.offheapstore.buffersource.BufferSource; 22 | 23 | /** 24 | * 25 | * @author cdennis 26 | */ 27 | public class UnlimitedPageSource implements PageSource { 28 | 29 | private final BufferSource source; 30 | 31 | public UnlimitedPageSource(BufferSource source) { 32 | this.source = source; 33 | } 34 | 35 | @Override 36 | public Page allocate(final int size, boolean thief, boolean victim, OffHeapStorageArea owner) { 37 | ByteBuffer buffer = source.allocateBuffer(size); 38 | if (buffer == null) { 39 | return null; 40 | } else { 41 | return new Page(buffer, owner); 42 | } 43 | } 44 | 45 | @Override 46 | public void free(Page page) { 47 | //no-op 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/util/ByteBufferUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.util; 18 | 19 | import java.nio.ByteBuffer; 20 | 21 | /** 22 | * 23 | * @author cdennis 24 | */ 25 | public final class ByteBufferUtils { 26 | 27 | private ByteBufferUtils() { 28 | //no instances 29 | } 30 | 31 | public static int totalLength(ByteBuffer[] buffers) { 32 | int total = 0; 33 | for (ByteBuffer buffer : buffers) { 34 | total += buffer.remaining(); 35 | } 36 | return total; 37 | } 38 | 39 | public static ByteBuffer aggregate(ByteBuffer[] buffers) { 40 | if (buffers.length == 1) { 41 | return buffers[0]; 42 | } else { 43 | ByteBuffer aggregate = ByteBuffer.allocate(totalLength(buffers)); 44 | for (ByteBuffer element : buffers) { 45 | aggregate.put(element); 46 | } 47 | return (ByteBuffer) aggregate.flip(); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/buffersource/OffHeapBufferSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.buffersource; 18 | 19 | import java.nio.ByteBuffer; 20 | 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | /** 25 | * An unlimited direct byte buffer source. 26 | * 27 | * @author Chris Dennis 28 | */ 29 | public class OffHeapBufferSource implements BufferSource { 30 | 31 | private static final Logger LOGGER = LoggerFactory.getLogger(OffHeapBufferSource.class); 32 | 33 | 34 | @Override 35 | public ByteBuffer allocateBuffer(int size) { 36 | try { 37 | return ByteBuffer.allocateDirect(size); 38 | } catch (OutOfMemoryError e) { 39 | LOGGER.debug("Failed to allocate " + size + " byte offheap buffer", e); 40 | return null; 41 | } 42 | } 43 | 44 | @Override 45 | public String toString() { 46 | return "Off-Heap Buffer Source"; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/test/java/org/terracotta/offheapstore/storage/listener/OffHeapBufferStorageEngineListenerIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.storage.listener; 18 | 19 | import org.terracotta.offheapstore.storage.listener.ListenableStorageEngine; 20 | import org.terracotta.offheapstore.buffersource.HeapBufferSource; 21 | import org.terracotta.offheapstore.paging.UnlimitedPageSource; 22 | import org.terracotta.offheapstore.storage.OffHeapBufferStorageEngine; 23 | import org.terracotta.offheapstore.storage.PointerSize; 24 | import org.terracotta.offheapstore.storage.portability.StringPortability; 25 | 26 | public class OffHeapBufferStorageEngineListenerIT extends AbstractListenerIT { 27 | 28 | @Override 29 | protected ListenableStorageEngine createStorageEngine() { 30 | return new OffHeapBufferStorageEngine<>(PointerSize.INT, new UnlimitedPageSource(new HeapBufferSource()), 1024, StringPortability.INSTANCE, StringPortability.INSTANCE); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/org/terracotta/offheapstore/util/PointerSizeParameterizedTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.util; 18 | 19 | import org.terracotta.offheapstore.storage.PointerSize; 20 | 21 | import java.util.ArrayList; 22 | import java.util.Collection; 23 | 24 | import org.junit.runner.RunWith; 25 | 26 | /** 27 | * 28 | * @author cdennis 29 | */ 30 | @RunWith(ParallelParameterized.class) 31 | public abstract class PointerSizeParameterizedTest { 32 | 33 | @ParallelParameterized.Parameters(name = "pointer-size={0}") 34 | public static Collection data() { 35 | Collection widths = new ArrayList<>(); 36 | for (PointerSize width : PointerSize.values()) { 37 | widths.add(new Object[] {width}); 38 | } 39 | return widths; 40 | } 41 | 42 | @ParallelParameterized.Parameter(0) 43 | public volatile PointerSize pointerSize; 44 | 45 | protected PointerSize getPointerSize() { 46 | return pointerSize; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/MetadataTuple.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2016-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore; 18 | 19 | public final class MetadataTuple { 20 | 21 | private final V value; 22 | private final int metadata; 23 | 24 | private MetadataTuple(V value, int metadata) { 25 | this.value = value; 26 | this.metadata = metadata; 27 | } 28 | 29 | public V value() { 30 | return value; 31 | } 32 | 33 | public int metadata() { 34 | return metadata; 35 | } 36 | 37 | @Override 38 | public boolean equals(Object o) { 39 | if (o instanceof MetadataTuple) { 40 | MetadataTuple other = (MetadataTuple) o; 41 | return value().equals(other.value()) && metadata() == other.metadata(); 42 | } else { 43 | return false; 44 | } 45 | } 46 | 47 | @Override 48 | public int hashCode() { 49 | return value.hashCode() ^ metadata; 50 | } 51 | 52 | 53 | public static MetadataTuple metadataTuple(T value, int metadata) { 54 | return new MetadataTuple<>(value, metadata); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/storage/StringStorageEngine.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.storage; 18 | 19 | import org.terracotta.offheapstore.paging.PageSource; 20 | import org.terracotta.offheapstore.storage.portability.Portability; 21 | import org.terracotta.offheapstore.storage.portability.StringPortability; 22 | import org.terracotta.offheapstore.util.Factory; 23 | 24 | /** 25 | * A {@code } storage engine. 26 | * 27 | * @author Chris Dennis 28 | */ 29 | public class StringStorageEngine extends OffHeapBufferStorageEngine { 30 | 31 | public static Factory createFactory(final PointerSize width, final PageSource source, final int pageSize) { 32 | return () -> new StringStorageEngine(width, source, pageSize); 33 | } 34 | 35 | private static final Portability PORTABILITY = StringPortability.INSTANCE; 36 | 37 | public StringStorageEngine(PointerSize width, PageSource source, int pageSize) { 38 | super(width, source, pageSize, PORTABILITY, PORTABILITY); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/com/terracottatech/offheapstore/storage/restartable/RestartabilityTestUtilities.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.terracottatech.offheapstore.storage.restartable; 18 | 19 | import com.terracottatech.frs.object.RegisterableObjectManager; 20 | import org.junit.Assert; 21 | 22 | import java.io.File; 23 | import java.io.IOException; 24 | import java.nio.ByteBuffer; 25 | 26 | public final class RestartabilityTestUtilities { 27 | 28 | private RestartabilityTestUtilities() { 29 | //static util class 30 | } 31 | 32 | public static RegisterableObjectManager createObjectManager() { 33 | return new RegisterableObjectManager(); 34 | } 35 | 36 | public static File createTempDirectory(String prefix) throws IOException { 37 | File storage = File.createTempFile(prefix, ""); 38 | Assert.assertTrue(storage.delete()); 39 | Assert.assertTrue(storage.mkdirs()); 40 | Assert.assertTrue(storage.isDirectory()); 41 | storage.deleteOnExit(); 42 | return storage; 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/test/java/com/terracottatech/offheapstore/util/PointerSizeParameterizedTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | /* 18 | * To change this template, choose Tools | Templates 19 | * and open the template in the editor. 20 | */ 21 | package com.terracottatech.offheapstore.util; 22 | 23 | import org.terracotta.offheapstore.storage.PointerSize; 24 | 25 | import java.util.ArrayList; 26 | import java.util.Collection; 27 | 28 | import org.junit.runner.RunWith; 29 | 30 | /** 31 | * 32 | * @author cdennis 33 | */ 34 | @RunWith(ParallelParameterized.class) 35 | public abstract class PointerSizeParameterizedTest { 36 | 37 | @ParallelParameterized.Parameters(name = "pointer-size={0}") 38 | public static Collection data() { 39 | Collection widths = new ArrayList(); 40 | for (PointerSize width : PointerSize.values()) { 41 | widths.add(new Object[] {width}); 42 | } 43 | return widths; 44 | } 45 | 46 | @ParallelParameterized.Parameter(0) 47 | public volatile PointerSize pointerSize; 48 | 49 | protected PointerSize getPointerSize() { 50 | return pointerSize; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/paging/PageSource.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.paging; 18 | 19 | /** 20 | * 21 | * @author cdennis 22 | */ 23 | public interface PageSource { 24 | 25 | /** 26 | * Attempt to allocate a page of the given size. 27 | *

28 | * Allocations identified as thieves will if necessary 'steal' space from 29 | * previous allocations identified as 'victims' in order to fulfill the 30 | * allocation request. owner is the area from which the 31 | * returned page can subsequently be stolen or recovered. This is most likely 32 | * to be the calling instance. 33 | * 34 | * @param size size of page to allocate 35 | * @param thief {@code true} if the allocation can steal space from victims 36 | * @param victim {@code true} if the allocated page should be eligible for stealing 37 | * @param owner owner from which subsequent steal should occur 38 | * @return an allocated page, or {@code null} in the case of failure 39 | */ 40 | Page allocate(int size, boolean thief, boolean victim, OffHeapStorageArea owner); 41 | 42 | void free(Page page); 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/storage/portability/BooleanPortability.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.storage.portability; 18 | 19 | import java.nio.ByteBuffer; 20 | 21 | public class BooleanPortability implements Portability { 22 | 23 | public static final BooleanPortability INSTANCE = new BooleanPortability(); 24 | 25 | private static final ByteBuffer TRUE = ByteBuffer.allocateDirect(1); 26 | private static final ByteBuffer FALSE = ByteBuffer.allocateDirect(1); 27 | static { 28 | TRUE.put((byte) 1).flip(); 29 | FALSE.put((byte) 0).flip(); 30 | } 31 | 32 | private BooleanPortability() { 33 | //singleton 34 | } 35 | 36 | @Override 37 | public ByteBuffer encode(Boolean object) { 38 | return object ? TRUE.duplicate() : FALSE.duplicate(); 39 | } 40 | 41 | @Override 42 | public Boolean decode(ByteBuffer buffer) { 43 | if (buffer.get(0) > 0) { 44 | return Boolean.TRUE; 45 | } else { 46 | return Boolean.FALSE; 47 | } 48 | } 49 | 50 | @Override 51 | public boolean equals(Object object, ByteBuffer buffer) { 52 | return object.equals(decode(buffer)); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/storage/portability/Portability.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.storage.portability; 18 | 19 | import java.nio.ByteBuffer; 20 | 21 | /** 22 | * An object to ByteBuffer converter. 23 | * 24 | * @param type handled by this converter 25 | * 26 | * @author Chris Dennis 27 | */ 28 | public interface Portability { 29 | 30 | /** 31 | * Encodes an object of type {@code T} as a {@code ByteBuffer}. 32 | * 33 | * @param object object to be encoded 34 | * @return the encoded object 35 | */ 36 | ByteBuffer encode(T object); 37 | 38 | /** 39 | * Decodes a {@code ByteBuffer} to an object of type {@code T}. 40 | * 41 | * @param buffer bytes to decode 42 | * @return the decoded object 43 | */ 44 | T decode(ByteBuffer buffer); 45 | 46 | /** 47 | * Returns true if the encoded object once decoded would be 48 | * {@code Object.equals(Object)} to the supplied object. 49 | * 50 | * @param object object to compare to 51 | * @param buffer buffer containing encoded object 52 | * @return {@code true} if the two parameters are "equal" 53 | */ 54 | boolean equals(Object object, ByteBuffer buffer); 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/disk/storage/portability/PersistentByteArrayPortability.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.disk.storage.portability; 18 | 19 | import java.io.IOException; 20 | import java.io.ObjectInput; 21 | import java.io.ObjectOutput; 22 | 23 | import org.terracotta.offheapstore.disk.persistent.PersistentPortability; 24 | import org.terracotta.offheapstore.storage.portability.ByteArrayPortability; 25 | 26 | /** 27 | * 28 | * @author Chris Dennis 29 | */ 30 | public class PersistentByteArrayPortability extends ByteArrayPortability implements PersistentPortability { 31 | 32 | public static final PersistentByteArrayPortability INSTANCE = new PersistentByteArrayPortability(); 33 | 34 | private PersistentByteArrayPortability() { 35 | //singleton 36 | } 37 | 38 | @Override 39 | public void flush() throws IOException { 40 | //no-op 41 | } 42 | 43 | @Override 44 | public void close() throws IOException { 45 | //no-op 46 | } 47 | 48 | @Override 49 | public void persist(ObjectOutput output) throws IOException { 50 | //no-op 51 | } 52 | 53 | @Override 54 | public void bootstrap(ObjectInput input) throws IOException { 55 | //no-op 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/test/java/org/terracotta/offheapstore/storage/portability/ByteArrayPortabilityTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.storage.portability; 18 | 19 | import org.terracotta.offheapstore.storage.portability.ByteArrayPortability; 20 | import java.nio.ByteBuffer; 21 | import java.util.Random; 22 | 23 | import org.junit.Assert; 24 | import org.junit.Test; 25 | 26 | /** 27 | * 28 | * @author cdennis 29 | */ 30 | public class ByteArrayPortabilityTest { 31 | 32 | @Test 33 | public void testZeroLengthArray() { 34 | ByteArrayPortability test = ByteArrayPortability.INSTANCE; 35 | 36 | ByteBuffer b = test.encode(new byte[0]); 37 | 38 | byte[] read = test.decode(b); 39 | 40 | Assert.assertNotNull(read); 41 | Assert.assertEquals(0, read.length); 42 | } 43 | 44 | @Test 45 | public void testPopulatedArray() { 46 | ByteArrayPortability test = ByteArrayPortability.INSTANCE; 47 | 48 | Random rndm = new Random(); 49 | 50 | byte[] before = new byte[rndm.nextInt(1024)]; 51 | rndm.nextBytes(before); 52 | 53 | ByteBuffer b = test.encode(before); 54 | byte[] after = test.decode(b); 55 | 56 | Assert.assertNotNull(after); 57 | Assert.assertNotSame(before, after); 58 | Assert.assertArrayEquals(before, after); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/util/NoOpLock.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.util; 18 | 19 | import java.util.concurrent.TimeUnit; 20 | import java.util.concurrent.locks.Condition; 21 | import java.util.concurrent.locks.Lock; 22 | 23 | /** 24 | * 25 | * @author cdennis 26 | */ 27 | public final class NoOpLock implements Lock { 28 | 29 | public static final NoOpLock INSTANCE = new NoOpLock(); 30 | 31 | private NoOpLock() { 32 | //not instantiable 33 | } 34 | 35 | @Override 36 | public void lock() { 37 | //no-op 38 | } 39 | 40 | @Override 41 | public void lockInterruptibly() throws InterruptedException { 42 | if (Thread.interrupted()) { 43 | throw new InterruptedException(); 44 | } 45 | } 46 | 47 | @Override 48 | public boolean tryLock() { 49 | return true; 50 | } 51 | 52 | @Override 53 | public boolean tryLock(long l, TimeUnit tu) throws InterruptedException { 54 | if (Thread.interrupted()) { 55 | throw new InterruptedException(); 56 | } else { 57 | return true; 58 | } 59 | } 60 | 61 | @Override 62 | public void unlock() { 63 | //no-op 64 | } 65 | 66 | @Override 67 | public Condition newCondition() { 68 | throw new UnsupportedOperationException(); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/terracottatech/offheapstore/storage/restartable/DetachedLinkedNode.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.terracottatech.offheapstore.storage.restartable; 18 | 19 | 20 | public class DetachedLinkedNode implements LinkedNode { 21 | 22 | private final T value; 23 | 24 | public DetachedLinkedNode(T value) { 25 | this.value = value; 26 | } 27 | 28 | @Override 29 | public long getLsn() { 30 | return -1L; 31 | } 32 | 33 | @Override 34 | public void setLsn(long lsn) { 35 | throw new UnsupportedOperationException(); 36 | } 37 | 38 | @Override 39 | public long getNext() { 40 | return RestartableStorageEngine.NULL_ENCODING; 41 | } 42 | 43 | @Override 44 | public long getPrevious() { 45 | return RestartableStorageEngine.NULL_ENCODING; 46 | } 47 | 48 | @Override 49 | public void setNext(long encoding) { 50 | throw new UnsupportedOperationException(); 51 | } 52 | 53 | @Override 54 | public void setPrevious(long encoding) { 55 | throw new UnsupportedOperationException(); 56 | } 57 | 58 | @Override 59 | public void flush() { 60 | throw new UnsupportedOperationException(); 61 | } 62 | 63 | @Override 64 | public T getValue() { 65 | return value; 66 | } 67 | 68 | @Override 69 | public int getMetadata() { 70 | throw new UnsupportedOperationException(); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/test/java/org/terracotta/offheapstore/storage/listener/FileBackedStorageEngineListenerIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.storage.listener; 18 | 19 | import java.io.File; 20 | import java.io.IOException; 21 | 22 | import org.junit.After; 23 | import org.junit.Before; 24 | 25 | import org.terracotta.offheapstore.disk.paging.MappedPageSource; 26 | import org.terracotta.offheapstore.disk.storage.FileBackedStorageEngine; 27 | import org.terracotta.offheapstore.storage.portability.StringPortability; 28 | import org.terracotta.offheapstore.util.MemoryUnit; 29 | 30 | public class FileBackedStorageEngineListenerIT extends AbstractListenerIT { 31 | 32 | protected File dataFile; 33 | 34 | @Before 35 | public void createDataFile() throws IOException { 36 | dataFile = File.createTempFile(getClass().getSimpleName(), ".data"); 37 | dataFile.deleteOnExit(); 38 | } 39 | 40 | @After 41 | public void destroyDataFile() { 42 | dataFile.delete(); 43 | } 44 | 45 | @Override 46 | protected ListenableStorageEngine createStorageEngine() { 47 | try { 48 | return new FileBackedStorageEngine<>(new MappedPageSource(dataFile), Long.MAX_VALUE, MemoryUnit.BYTES, StringPortability.INSTANCE, StringPortability.INSTANCE); 49 | } catch (IOException e) { 50 | throw new AssertionError(e); 51 | } 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/disk/persistent/PersistentReadWriteLockedOffHeapClockCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.disk.persistent; 18 | 19 | 20 | import java.util.concurrent.locks.Lock; 21 | import java.util.concurrent.locks.ReentrantReadWriteLock; 22 | 23 | import org.terracotta.offheapstore.disk.paging.MappedPageSource; 24 | 25 | /** 26 | * @author Chris Dennis 27 | */ 28 | public class PersistentReadWriteLockedOffHeapClockCache extends AbstractPersistentOffHeapCache { 29 | 30 | private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); 31 | 32 | public PersistentReadWriteLockedOffHeapClockCache(MappedPageSource source, PersistentStorageEngine storageEngine, boolean bootstrap) { 33 | super(source, storageEngine, bootstrap); 34 | } 35 | 36 | public PersistentReadWriteLockedOffHeapClockCache(MappedPageSource source, PersistentStorageEngine storageEngine, int tableSize, boolean bootstrap) { 37 | super(source, storageEngine, tableSize, bootstrap); 38 | } 39 | 40 | @Override 41 | public Lock readLock() { 42 | return lock.readLock(); 43 | } 44 | 45 | @Override 46 | public Lock writeLock() { 47 | return lock.writeLock(); 48 | } 49 | 50 | @Override 51 | public ReentrantReadWriteLock getLock() { 52 | return lock; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/disk/persistent/PersistentReadWriteLockedOffHeapHashMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.disk.persistent; 18 | 19 | import java.util.concurrent.locks.Lock; 20 | import java.util.concurrent.locks.ReentrantReadWriteLock; 21 | 22 | import org.terracotta.offheapstore.disk.paging.MappedPageSource; 23 | 24 | /** 25 | * 26 | * @author Chris Dennis 27 | */ 28 | public class PersistentReadWriteLockedOffHeapHashMap extends AbstractPersistentLockedOffHeapHashMap { 29 | 30 | private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); 31 | 32 | public PersistentReadWriteLockedOffHeapHashMap(MappedPageSource tableSource, PersistentStorageEngine storageEngine, boolean bootstrap) { 33 | super(tableSource, storageEngine, bootstrap); 34 | } 35 | 36 | public PersistentReadWriteLockedOffHeapHashMap(MappedPageSource tableSource, PersistentStorageEngine storageEngine, int tableSize, boolean bootstrap) { 37 | super(tableSource, storageEngine, tableSize, bootstrap); 38 | } 39 | 40 | @Override 41 | public Lock readLock() { 42 | return lock.readLock(); 43 | } 44 | 45 | @Override 46 | public Lock writeLock() { 47 | return lock.writeLock(); 48 | } 49 | 50 | @Override 51 | public ReentrantReadWriteLock getLock() { 52 | return lock; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/eviction/EvictionListeningWriteLockedOffHeapClockCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.eviction; 18 | 19 | import org.terracotta.offheapstore.WriteLockedOffHeapClockCache; 20 | import org.terracotta.offheapstore.paging.PageSource; 21 | import org.terracotta.offheapstore.storage.StorageEngine; 22 | 23 | /** 24 | * 25 | * @author Chris Dennis 26 | */ 27 | public class EvictionListeningWriteLockedOffHeapClockCache extends WriteLockedOffHeapClockCache { 28 | 29 | private final EvictionListener listener; 30 | 31 | public EvictionListeningWriteLockedOffHeapClockCache(EvictionListener listener, PageSource source, StorageEngine storageEngine) { 32 | super(source, storageEngine); 33 | this.listener = listener; 34 | } 35 | 36 | public EvictionListeningWriteLockedOffHeapClockCache(EvictionListener listener, PageSource source, StorageEngine storageEngine, int tableSize) { 37 | super(source, storageEngine, tableSize); 38 | this.listener = listener; 39 | } 40 | 41 | @Override 42 | public boolean evict(final int index, boolean shrink) { 43 | boolean evicted; 44 | try { 45 | listener.evicting(() -> getEntryAtTableOffset(index)); 46 | } finally { 47 | evicted = super.evict(index, shrink); 48 | } 49 | return evicted; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/org/terracotta/offheapstore/disk/storage/portability/PersistentSerializablePortabilityTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.disk.storage.portability; 18 | 19 | import org.terracotta.offheapstore.disk.storage.portability.PersistentSerializablePortability; 20 | import java.io.ByteArrayInputStream; 21 | import java.io.ByteArrayOutputStream; 22 | import java.io.IOException; 23 | import java.io.ObjectInputStream; 24 | import java.io.ObjectOutputStream; 25 | import org.junit.Test; 26 | 27 | /** 28 | * 29 | * @author Chris Dennis 30 | */ 31 | public class PersistentSerializablePortabilityTest { 32 | 33 | @Test 34 | public void testAddingMappingsToRecoveredPortability() throws IOException { 35 | PersistentSerializablePortability portability = new PersistentSerializablePortability(); 36 | portability.encode(0); 37 | ByteArrayOutputStream bout = new ByteArrayOutputStream(); 38 | try (ObjectOutputStream oout = new ObjectOutputStream(bout)) { 39 | portability.persist(oout); 40 | } 41 | byte[] persisted = bout.toByteArray(); 42 | 43 | PersistentSerializablePortability recovered = new PersistentSerializablePortability(); 44 | ByteArrayInputStream bin = new ByteArrayInputStream(persisted); 45 | try (ObjectInputStream oin = new ObjectInputStream(bin)) { 46 | recovered.bootstrap(oin); 47 | } 48 | 49 | recovered.encode(0L); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/com/terracottatech/offheapstore/storage/restartable/RestartableOffHeapBufferStorageEngineIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.terracottatech.offheapstore.storage.restartable; 18 | 19 | import java.nio.ByteBuffer; 20 | 21 | import org.terracotta.offheapstore.buffersource.OffHeapBufferSource; 22 | import org.terracotta.offheapstore.paging.PageSource; 23 | import org.terracotta.offheapstore.paging.UpfrontAllocatingPageSource; 24 | import org.terracotta.offheapstore.storage.OffHeapBufferStorageEngine; 25 | import org.terracotta.offheapstore.storage.portability.StringPortability; 26 | import org.terracotta.offheapstore.util.MemoryUnit; 27 | 28 | public class RestartableOffHeapBufferStorageEngineIT extends RestartableStorageEngineIT { 29 | 30 | @Override 31 | protected RestartableStorageEngine createEngine() { 32 | PageSource source = new UpfrontAllocatingPageSource(new OffHeapBufferSource(), MemoryUnit.MEGABYTES.toBytes(4), MemoryUnit.KILOBYTES.toBytes(4)); 33 | OffHeapBufferStorageEngine> delegate = create(source, MemoryUnit.KILOBYTES.toBytes(1), StringPortability.INSTANCE, new LinkedNodePortability(StringPortability.INSTANCE)); 34 | return new RestartableStorageEngine>, String, String, String>("id", new NoOpRestartStore(), delegate, true); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/com/terracottatech/offheapstore/storage/restartable/partial/KeysOnlyRestartableStorageEngineIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | /* 18 | * To change this template, choose Tools | Templates 19 | * and open the template in the editor. 20 | */ 21 | package com.terracottatech.offheapstore.storage.restartable.partial; 22 | 23 | import com.terracottatech.frs.RestartStore; 24 | import org.terracotta.offheapstore.buffersource.OffHeapBufferSource; 25 | import org.terracotta.offheapstore.paging.PageSource; 26 | import org.terracotta.offheapstore.paging.UpfrontAllocatingPageSource; 27 | import org.terracotta.offheapstore.storage.portability.StringPortability; 28 | import org.terracotta.offheapstore.util.MemoryUnit; 29 | 30 | import java.nio.ByteBuffer; 31 | 32 | /** 33 | * 34 | * @author cdennis 35 | */ 36 | public class KeysOnlyRestartableStorageEngineIT extends MinimalRestartableStorageEngineIT { 37 | 38 | @Override 39 | protected RestartableMinimalStorageEngine createEngine(RestartStore frs) { 40 | PageSource source = new UpfrontAllocatingPageSource(new OffHeapBufferSource(), MemoryUnit.MEGABYTES.toBytes(1), MemoryUnit.MEGABYTES.toBytes(1)); 41 | return new RestartableKeysOnlyStorageEngine("id", frs, true, getPointerSize(), source, MemoryUnit.KILOBYTES.toBytes(1), StringPortability.INSTANCE, StringPortability.INSTANCE, 0.0f); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/test/java/com/terracottatech/offheapstore/storage/restartable/partial/PartialRestartableStorageEngineIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | /* 18 | * To change this template, choose Tools | Templates 19 | * and open the template in the editor. 20 | */ 21 | package com.terracottatech.offheapstore.storage.restartable.partial; 22 | 23 | import com.terracottatech.frs.RestartStore; 24 | import org.terracotta.offheapstore.buffersource.OffHeapBufferSource; 25 | import org.terracotta.offheapstore.paging.PageSource; 26 | import org.terracotta.offheapstore.paging.UpfrontAllocatingPageSource; 27 | import org.terracotta.offheapstore.storage.portability.StringPortability; 28 | import org.terracotta.offheapstore.util.MemoryUnit; 29 | 30 | import java.nio.ByteBuffer; 31 | 32 | /** 33 | * 34 | * @author cdennis 35 | */ 36 | public class PartialRestartableStorageEngineIT extends MinimalRestartableStorageEngineIT { 37 | 38 | @Override 39 | protected RestartableMinimalStorageEngine createEngine(RestartStore frs) { 40 | PageSource source = new UpfrontAllocatingPageSource(new OffHeapBufferSource(), MemoryUnit.MEGABYTES.toBytes(1), MemoryUnit.MEGABYTES.toBytes(1)); 41 | return new RestartablePartialStorageEngine("id", frs, true, getPointerSize(), source, MemoryUnit.KILOBYTES.toBytes(1), StringPortability.INSTANCE, StringPortability.INSTANCE, 0.0f); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/disk/storage/PersistentIntegerStorageEngine.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.disk.storage; 18 | 19 | import java.io.IOException; 20 | import java.io.ObjectInput; 21 | import java.io.ObjectOutput; 22 | 23 | import org.terracotta.offheapstore.disk.persistent.PersistentHalfStorageEngine; 24 | import org.terracotta.offheapstore.storage.IntegerStorageEngine; 25 | import org.terracotta.offheapstore.util.Factory; 26 | 27 | /** 28 | * 29 | * @author Chris Dennis 30 | */ 31 | public class PersistentIntegerStorageEngine extends IntegerStorageEngine implements PersistentHalfStorageEngine { 32 | 33 | private static final PersistentIntegerStorageEngine SINGLETON = new PersistentIntegerStorageEngine(); 34 | private static final Factory FACTORY = () -> SINGLETON; 35 | 36 | public static Factory createPersistentFactory() { 37 | return FACTORY; 38 | } 39 | 40 | @Override 41 | public void flush() throws IOException { 42 | //no-op 43 | } 44 | 45 | @Override 46 | public void close() throws IOException { 47 | //no-op 48 | } 49 | 50 | @Override 51 | public void persist(ObjectOutput output) throws IOException { 52 | //no-op 53 | } 54 | 55 | @Override 56 | public void bootstrap(ObjectInput input) throws IOException { 57 | //no-op 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/eviction/EvictionListeningReadWriteLockedOffHeapClockCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.eviction; 18 | 19 | import org.terracotta.offheapstore.ReadWriteLockedOffHeapClockCache; 20 | import org.terracotta.offheapstore.paging.PageSource; 21 | import org.terracotta.offheapstore.storage.StorageEngine; 22 | 23 | /** 24 | * 25 | * @author Chris Dennis 26 | */ 27 | public class EvictionListeningReadWriteLockedOffHeapClockCache extends ReadWriteLockedOffHeapClockCache{ 28 | 29 | private final EvictionListener listener; 30 | 31 | public EvictionListeningReadWriteLockedOffHeapClockCache(EvictionListener listener, PageSource source, StorageEngine storageEngine) { 32 | super(source, storageEngine); 33 | this.listener = listener; 34 | } 35 | 36 | public EvictionListeningReadWriteLockedOffHeapClockCache(EvictionListener listener, PageSource source, StorageEngine storageEngine, int tableSize) { 37 | super(source, storageEngine, tableSize); 38 | this.listener = listener; 39 | } 40 | 41 | @Override 42 | public boolean evict(final int index, boolean shrink) { 43 | boolean evicted; 44 | try { 45 | listener.evicting(() -> getEntryAtTableOffset(index)); 46 | } finally { 47 | evicted = super.evict(index, shrink); 48 | } 49 | return evicted; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/test/java/org/terracotta/offheapstore/storage/portability/StringPortabilityTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.storage.portability; 18 | 19 | import org.terracotta.offheapstore.storage.portability.StringPortability; 20 | import org.junit.Assert; 21 | import org.junit.Test; 22 | 23 | /** 24 | * 25 | * @author cdennis 26 | */ 27 | public class StringPortabilityTest { 28 | 29 | @Test 30 | public void testEmptyString() { 31 | StringPortability test = StringPortability.INSTANCE; 32 | 33 | String input = ""; 34 | String result = test.decode(test.encode(input)); 35 | Assert.assertNotNull(result); 36 | Assert.assertNotSame(input, result); 37 | Assert.assertEquals(input, result); 38 | } 39 | 40 | @Test 41 | public void testNormalString() { 42 | StringPortability test = StringPortability.INSTANCE; 43 | 44 | String input = "hello"; 45 | String result = test.decode(test.encode(input)); 46 | Assert.assertNotNull(result); 47 | Assert.assertNotSame(input, result); 48 | Assert.assertEquals(input, result); 49 | } 50 | 51 | @Test 52 | public void testInvalidUTFSequence() { 53 | StringPortability test = StringPortability.INSTANCE; 54 | 55 | String input = new String(new char[] {0xfdd0, 0xfdd1}); 56 | String result = test.decode(test.encode(input)); 57 | Assert.assertNotNull(result); 58 | Assert.assertNotSame(input, result); 59 | Assert.assertEquals(input, result); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/storage/portability/StringPortability.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.storage.portability; 18 | 19 | import java.io.IOException; 20 | import java.io.ObjectInput; 21 | import java.io.ObjectOutput; 22 | import java.nio.ByteBuffer; 23 | 24 | import org.terracotta.offheapstore.disk.persistent.PersistentPortability; 25 | 26 | public class StringPortability implements PersistentPortability { 27 | 28 | public static final StringPortability INSTANCE = new StringPortability(); 29 | 30 | private StringPortability() { 31 | //singleton 32 | } 33 | 34 | @Override 35 | public ByteBuffer encode(String object) { 36 | ByteBuffer buffer = ByteBuffer.allocate(object.length() * 2); 37 | buffer.asCharBuffer().put(object).clear(); 38 | return buffer; 39 | } 40 | 41 | @Override 42 | public String decode(ByteBuffer buffer) { 43 | return buffer.asCharBuffer().toString(); 44 | } 45 | 46 | @Override 47 | public boolean equals(Object value, ByteBuffer readBuffer) { 48 | return value.equals(decode(readBuffer)); 49 | } 50 | 51 | @Override 52 | public void flush() throws IOException { 53 | //no-op 54 | } 55 | 56 | @Override 57 | public void close() throws IOException { 58 | //no-op 59 | } 60 | 61 | @Override 62 | public void persist(ObjectOutput output) throws IOException { 63 | //no-op 64 | } 65 | 66 | @Override 67 | public void bootstrap(ObjectInput input) throws IOException { 68 | //no-op 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/test/java/org/terracotta/offheapstore/OffHeapHashMapTableResizeIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore; 18 | 19 | import java.util.Map; 20 | 21 | import org.junit.Test; 22 | 23 | import ch.qos.logback.classic.Level; 24 | import ch.qos.logback.classic.Logger; 25 | 26 | import org.slf4j.LoggerFactory; 27 | import org.terracotta.offheapstore.buffersource.OffHeapBufferSource; 28 | import org.terracotta.offheapstore.paging.UpfrontAllocatingPageSource; 29 | import org.terracotta.offheapstore.storage.IntegerStorageEngine; 30 | import org.terracotta.offheapstore.storage.SplitStorageEngine; 31 | 32 | import org.junit.Ignore; 33 | 34 | /** 35 | * 36 | * @author cdennis 37 | */ 38 | @Ignore("not asserting anything") 39 | public class OffHeapHashMapTableResizeIT { 40 | 41 | @Test 42 | public void testLargeTableResizes() { 43 | Logger logger = (Logger)LoggerFactory.getLogger(OffHeapHashMap.class); 44 | Level oldLevel = logger.getLevel(); 45 | logger.setLevel(Level.ALL); 46 | try { 47 | Map map = new OffHeapHashMap<>(new UpfrontAllocatingPageSource(new OffHeapBufferSource(), 32 * 1024 * 1024, 32 * 1024 * 1024), new SplitStorageEngine<>(new IntegerStorageEngine(), new IntegerStorageEngine()), 1); 48 | 49 | for (int i = 0; i < 500000; i++) { 50 | map.put(i, i); 51 | } 52 | } finally { 53 | logger.setLevel(oldLevel); 54 | } 55 | } 56 | 57 | public static void main(String[] args) { 58 | new OffHeapHashMapTableResizeIT().testLargeTableResizes(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/WriteLockedOffHeapHashMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore; 18 | 19 | import java.util.concurrent.locks.Lock; 20 | import java.util.concurrent.locks.ReentrantLock; 21 | import java.util.concurrent.locks.ReentrantReadWriteLock; 22 | 23 | import org.terracotta.offheapstore.paging.PageSource; 24 | import org.terracotta.offheapstore.storage.StorageEngine; 25 | 26 | /** 27 | * An exclusive-read/write off-heap hash-map. 28 | *

29 | * This map uses a regular {@code ReentrantLock} to provide exclusive read and 30 | * write operations. 31 | * 32 | * @param the type of keys maintained by this map 33 | * @param the type of mapped values 34 | * 35 | * @author Chris Dennis 36 | */ 37 | public class WriteLockedOffHeapHashMap extends AbstractLockedOffHeapHashMap{ 38 | 39 | private final Lock lock = new ReentrantLock(); 40 | 41 | public WriteLockedOffHeapHashMap(PageSource tableSource, StorageEngine storageEngine) { 42 | super(tableSource, storageEngine); 43 | } 44 | 45 | public WriteLockedOffHeapHashMap(PageSource tableSource, StorageEngine storageEngine, int tableSize) { 46 | super(tableSource, storageEngine, tableSize); 47 | } 48 | 49 | @Override 50 | public Lock readLock() { 51 | return lock; 52 | } 53 | 54 | @Override 55 | public Lock writeLock() { 56 | return lock; 57 | } 58 | 59 | @Override 60 | public ReentrantReadWriteLock getLock() { 61 | throw new UnsupportedOperationException(); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/storage/portability/ByteArrayPortability.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.storage.portability; 18 | 19 | import java.nio.ByteBuffer; 20 | 21 | /** 22 | * A simple {@code byte[]} portability. 23 | * 24 | * @author Chris Dennis 25 | */ 26 | public class ByteArrayPortability implements Portability { 27 | 28 | public static final ByteArrayPortability INSTANCE = new ByteArrayPortability(); 29 | 30 | protected ByteArrayPortability() { 31 | //singleton 32 | } 33 | 34 | @Override 35 | public ByteBuffer encode(byte[] object) { 36 | return ByteBuffer.wrap(object); 37 | } 38 | 39 | @Override 40 | public byte[] decode(ByteBuffer buffer) { 41 | byte[] data = new byte[buffer.remaining()]; 42 | buffer.get(data); 43 | return data; 44 | } 45 | 46 | /** 47 | * Byte arrays do not have a content-based equals method so this throws 48 | * {@code UnsupportedOperationException}. 49 | *

50 | * The lack of any implementation only prevents this portability being used as 51 | * a key portability. Using byte arrays as keys in map would be extremely 52 | * questionable in any case. If necessary this portability could be 53 | * sub-classed to do deep array comparison. 54 | */ 55 | @Override 56 | public boolean equals(Object value, ByteBuffer readBuffer) throws UnsupportedOperationException { 57 | throw new UnsupportedOperationException("Byte arrays cannot be compared in their serialized forms - byte array eqaulity is identity based."); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/test/java/org/terracotta/offheapstore/CapacityLimitedIntegerStorageEngineFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore; 18 | 19 | import org.terracotta.offheapstore.CapacityLimitedIntegerStorageEngineFactory.CapacityLimitedIntegerStorageEngine; 20 | import org.terracotta.offheapstore.storage.IntegerStorageEngine; 21 | import org.terracotta.offheapstore.storage.SplitStorageEngine; 22 | import org.terracotta.offheapstore.util.Factory; 23 | 24 | public class CapacityLimitedIntegerStorageEngineFactory implements Factory { 25 | 26 | private int used; 27 | private int capacity; 28 | 29 | public void setCapacity(int capacity) { 30 | this.capacity = capacity; 31 | } 32 | 33 | @Override 34 | public CapacityLimitedIntegerStorageEngine newInstance() { 35 | return new CapacityLimitedIntegerStorageEngine(); 36 | } 37 | 38 | public class CapacityLimitedIntegerStorageEngine extends SplitStorageEngine { 39 | 40 | public CapacityLimitedIntegerStorageEngine() { 41 | super(new IntegerStorageEngine(), new IntegerStorageEngine()); 42 | } 43 | 44 | @Override 45 | public Long writeMapping(Integer key, Integer value, int hash, int metadata) { 46 | if (used < capacity) { 47 | used++; 48 | return super.writeMapping(key, value, hash, metadata); 49 | } else { 50 | return null; 51 | } 52 | } 53 | 54 | @Override 55 | public void freeMapping(long encoding, int hash, boolean removal) { 56 | used--; 57 | super.freeMapping(encoding, hash, removal); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/storage/SerializableStorageEngine.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.storage; 18 | 19 | import java.io.Serializable; 20 | 21 | import org.terracotta.offheapstore.paging.PageSource; 22 | import org.terracotta.offheapstore.storage.portability.Portability; 23 | import org.terracotta.offheapstore.storage.portability.SerializablePortability; 24 | import org.terracotta.offheapstore.util.Factory; 25 | 26 | /** 27 | * A {@code OffHeapBufferStorageEngine} subclass using Java serialization for 28 | * portability. 29 | * 30 | * @author Chris Dennis 31 | */ 32 | public class SerializableStorageEngine extends OffHeapBufferStorageEngine { 33 | 34 | public static Factory createFactory(final PointerSize width, final PageSource source, final int pageSize) { 35 | return () -> new SerializableStorageEngine(width, source, pageSize); 36 | } 37 | 38 | public static Factory createFactory(final PointerSize width, final PageSource source, final int pageSize, final Portability portability) { 39 | return () -> new SerializableStorageEngine(width, source, pageSize, portability); 40 | } 41 | 42 | public SerializableStorageEngine(PointerSize width, PageSource source, int pageSize) { 43 | super(width, source, pageSize, new SerializablePortability(), new SerializablePortability()); 44 | } 45 | 46 | protected SerializableStorageEngine(PointerSize width, PageSource source, int pageSize, Portability portability) { 47 | super(width, source, pageSize, portability, portability); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/paging/Page.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.paging; 18 | 19 | import java.nio.ByteBuffer; 20 | import java.nio.IntBuffer; 21 | 22 | /** 23 | * 24 | * @author Chris Dennis 25 | */ 26 | public class Page { 27 | 28 | private final ByteBuffer buffer; 29 | 30 | private final OffHeapStorageArea binding; 31 | 32 | private final int index; 33 | private final int address; 34 | private boolean freeable; 35 | 36 | public Page(ByteBuffer buffer, OffHeapStorageArea binding) { 37 | this.buffer = buffer; 38 | this.binding = binding; 39 | this.index = -1; 40 | this.address = -1; 41 | this.freeable = false; 42 | } 43 | 44 | public Page(ByteBuffer buffer, int index, int address, OffHeapStorageArea binding) { 45 | this.buffer = buffer; 46 | this.binding = binding; 47 | this.index = index; 48 | this.address = address; 49 | this.freeable = true; 50 | } 51 | 52 | public ByteBuffer asByteBuffer() { 53 | return buffer; 54 | } 55 | 56 | public IntBuffer asIntBuffer() { 57 | return buffer.asIntBuffer(); 58 | } 59 | 60 | public int size() { 61 | if (buffer == null) { 62 | return 0; 63 | } else { 64 | return buffer.capacity(); 65 | } 66 | } 67 | 68 | public int index() { 69 | return index; 70 | } 71 | 72 | public int address() { 73 | return address; 74 | } 75 | 76 | public OffHeapStorageArea binding() { 77 | return binding; 78 | } 79 | 80 | synchronized boolean isFreeable() { 81 | if (freeable) { 82 | freeable = false; 83 | return true; 84 | } else { 85 | return false; 86 | } 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/storage/BooleanHalfStorageEngine.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.storage; 18 | 19 | import org.terracotta.offheapstore.storage.StorageEngine.Owner; 20 | 21 | /** 22 | * 23 | * @author cdennis 24 | */ 25 | public final class BooleanHalfStorageEngine implements HalfStorageEngine { 26 | 27 | public static final BooleanHalfStorageEngine INSTANCE = new BooleanHalfStorageEngine(); 28 | 29 | private BooleanHalfStorageEngine() { 30 | //singleton 31 | } 32 | 33 | @Override 34 | public Integer write(Boolean object, int hash) { 35 | return object ? 1 : 0; 36 | } 37 | 38 | @Override 39 | public void free(int encoding) { 40 | //no-op 41 | } 42 | 43 | @Override 44 | public Boolean read(int encoding) { 45 | return encoding == 1; 46 | } 47 | 48 | @Override 49 | public boolean equals(Object object, int encoding) { 50 | return object instanceof Boolean && write((Boolean) object, 0) == encoding; 51 | } 52 | 53 | @Override 54 | public void clear() { 55 | //no-op 56 | } 57 | 58 | @Override 59 | public long getAllocatedMemory() { 60 | return 0L; 61 | } 62 | 63 | @Override 64 | public long getOccupiedMemory() { 65 | return 0L; 66 | } 67 | 68 | @Override 69 | public long getVitalMemory() { 70 | return 0L; 71 | } 72 | 73 | @Override 74 | public long getDataSize() { 75 | return 0; 76 | } 77 | 78 | @Override 79 | public void invalidateCache() { 80 | //no-op 81 | } 82 | 83 | @Override 84 | public void bind(Owner owner, long mask) { 85 | //no-op 86 | } 87 | 88 | @Override 89 | public void destroy() { 90 | //no-op 91 | } 92 | 93 | @Override 94 | public boolean shrink() { 95 | return false; 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /src/test/java/org/terracotta/offheapstore/util/RetryAssert.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.util; 18 | 19 | import org.hamcrest.Matcher; 20 | import org.junit.Assert; 21 | 22 | import java.util.concurrent.Callable; 23 | import java.util.concurrent.TimeUnit; 24 | 25 | public class RetryAssert { 26 | 27 | protected RetryAssert() { 28 | // static only class 29 | } 30 | 31 | public static void assertBy(long time, TimeUnit unit, Callable value, Matcher matcher) { 32 | boolean interrupted = Thread.interrupted(); 33 | try { 34 | long end = System.nanoTime() + unit.toNanos(time); 35 | for (long sleep = 10; ; sleep <<= 1L) { 36 | try { 37 | Assert.assertThat(value.call(), matcher); 38 | return; 39 | } catch (Throwable t) { 40 | //ignore - wait for timeout 41 | } 42 | 43 | long remaining = end - System.nanoTime(); 44 | if (remaining <= 0) { 45 | break; 46 | } else { 47 | try { 48 | Thread.sleep(Math.min(sleep, TimeUnit.NANOSECONDS.toMillis(remaining) + 1)); 49 | } catch (InterruptedException e) { 50 | interrupted = true; 51 | } 52 | } 53 | } 54 | } finally { 55 | if (interrupted) { 56 | Thread.currentThread().interrupt(); 57 | } 58 | } 59 | try { 60 | Assert.assertThat(value.call(), matcher); 61 | } catch (RuntimeException e) { 62 | throw e; 63 | } catch (Exception e) { 64 | throw new AssertionError(e); 65 | } 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/disk/persistent/PersistentConcurrentOffHeapHashMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.disk.persistent; 18 | 19 | import java.io.IOException; 20 | import java.io.ObjectInput; 21 | 22 | import org.terracotta.offheapstore.disk.paging.MappedPageSource; 23 | import org.terracotta.offheapstore.util.Factory; 24 | 25 | /** 26 | * 27 | * @author Chris Dennis 28 | */ 29 | public class PersistentConcurrentOffHeapHashMap extends AbstractPersistentConcurrentOffHeapMap { 30 | 31 | public PersistentConcurrentOffHeapHashMap(MappedPageSource tableSource, Factory> storageEngineFactory) { 32 | super(new PersistentReadWriteLockedOffHeapHashMapFactory<>(tableSource, storageEngineFactory)); 33 | } 34 | 35 | public PersistentConcurrentOffHeapHashMap(ObjectInput input, MappedPageSource tableSource, Factory> storageEngineFactory) throws IOException { 36 | super(new PersistentReadWriteLockedOffHeapHashMapFactory<>(tableSource, storageEngineFactory, false), readSegmentCount(input)); 37 | } 38 | 39 | public PersistentConcurrentOffHeapHashMap(MappedPageSource tableSource, Factory> storageEngineFactory, long tableSize, int concurrency) { 40 | super(new PersistentReadWriteLockedOffHeapHashMapFactory<>(tableSource, storageEngineFactory, (int) (tableSize / concurrency)), concurrency); 41 | } 42 | 43 | public PersistentConcurrentOffHeapHashMap(ObjectInput input, MappedPageSource tableSource, Factory> storageEngineFactory, long tableSize, int concurrency) throws IOException { 44 | super(new PersistentReadWriteLockedOffHeapHashMapFactory<>(tableSource, storageEngineFactory, (int) (tableSize / concurrency), false), readSegmentCount(input)); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/com/terracottatech/offheapstore/storage/restartable/RestartableFileBackedStorageEngineIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.terracottatech.offheapstore.storage.restartable; 18 | 19 | import java.io.File; 20 | import java.io.IOException; 21 | import java.nio.ByteBuffer; 22 | 23 | import org.junit.After; 24 | import org.junit.Before; 25 | import org.junit.runner.RunWith; 26 | import org.junit.runners.BlockJUnit4ClassRunner; 27 | 28 | import org.terracotta.offheapstore.disk.paging.MappedPageSource; 29 | import org.terracotta.offheapstore.disk.storage.FileBackedStorageEngine; 30 | import org.terracotta.offheapstore.storage.portability.StringPortability; 31 | 32 | import static org.terracotta.offheapstore.util.MemoryUnit.BYTES; 33 | 34 | @RunWith(BlockJUnit4ClassRunner.class) 35 | public class RestartableFileBackedStorageEngineIT extends RestartableStorageEngineIT { 36 | 37 | private File testFile; 38 | 39 | @Before 40 | public void createFile() throws IOException { 41 | testFile = File.createTempFile("RestartableFileBackedStorageEngineTest", ".data"); 42 | testFile.deleteOnExit(); 43 | } 44 | 45 | @After 46 | public void deleteFile() { 47 | testFile.delete(); 48 | } 49 | 50 | @Override 51 | protected RestartableStorageEngine createEngine() { 52 | try { 53 | MappedPageSource source = new MappedPageSource(testFile); 54 | FileBackedStorageEngine> delegate = new FileBackedStorageEngine>(source, 55 | Long.MAX_VALUE, BYTES, StringPortability.INSTANCE, new LinkedNodePortability(StringPortability.INSTANCE)); 56 | return new RestartableStorageEngine>, String, String, String>("id", new NoOpRestartStore(), delegate, true); 57 | } catch (IOException e) { 58 | throw new AssertionError(e); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/disk/persistent/PersistentConcurrentOffHeapClockCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.disk.persistent; 18 | 19 | import java.io.IOException; 20 | import java.io.ObjectInput; 21 | 22 | import org.terracotta.offheapstore.disk.paging.MappedPageSource; 23 | import org.terracotta.offheapstore.util.Factory; 24 | 25 | /** 26 | * 27 | * @author Chris Dennis 28 | */ 29 | public class PersistentConcurrentOffHeapClockCache extends AbstractPersistentConcurrentOffHeapCache { 30 | 31 | public PersistentConcurrentOffHeapClockCache(MappedPageSource tableSource, Factory> storageEngineFactory) { 32 | super(new PersistentReadWriteLockedOffHeapClockCacheFactory<>(tableSource, storageEngineFactory)); 33 | } 34 | 35 | public PersistentConcurrentOffHeapClockCache(ObjectInput input, MappedPageSource tableSource, Factory> storageEngineFactory) throws IOException { 36 | super(new PersistentReadWriteLockedOffHeapClockCacheFactory<>(tableSource, storageEngineFactory, false), readSegmentCount(input)); 37 | } 38 | 39 | public PersistentConcurrentOffHeapClockCache(MappedPageSource tableSource, Factory> storageEngineFactory, long tableSize, int concurrency) { 40 | super(new PersistentReadWriteLockedOffHeapClockCacheFactory<>(tableSource, storageEngineFactory, (int) (tableSize / concurrency)), concurrency); 41 | } 42 | 43 | public PersistentConcurrentOffHeapClockCache(ObjectInput input, MappedPageSource tableSource, Factory> storageEngineFactory, long tableSize, int concurrency) throws IOException { 44 | super(new PersistentReadWriteLockedOffHeapClockCacheFactory<>(tableSource, storageEngineFactory, (int) (tableSize / concurrency), false), readSegmentCount(input)); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/util/MemoryUnit.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.util; 18 | 19 | public enum MemoryUnit { 20 | 21 | BITS(-3), NIBBLES(-1), BYTES(0), KILOBYTES(10), MEGABYTES(20), GIGABYTES(30), TERABYTES(40); 22 | 23 | /** the index of this unit */ 24 | private final int index; 25 | 26 | /** Internal constructor */ 27 | MemoryUnit(int index) { 28 | this.index = index; 29 | } 30 | 31 | public long convert(long duration, MemoryUnit unit) { 32 | return doConvert(unit.index - index, duration); 33 | } 34 | 35 | public long toBits(long amount) { 36 | return doConvert(index - BITS.index, amount); 37 | } 38 | 39 | public int toBits(int amount) { 40 | return doConvert(index - BITS.index, amount); 41 | } 42 | 43 | public long toBytes(long amount) { 44 | return doConvert(index - BYTES.index, amount); 45 | } 46 | 47 | public int toBytes(int amount) { 48 | return doConvert(index - BYTES.index, amount); 49 | } 50 | 51 | private static long doConvert(int delta, long amount) { 52 | if (amount >= 0L) { 53 | if (delta == 0) { 54 | return amount; 55 | } else if (delta < 0) { 56 | return amount >>> -delta; 57 | } else if (delta >= Long.numberOfLeadingZeros(amount)) { 58 | return Long.MAX_VALUE; 59 | } else { 60 | return amount << delta; 61 | } 62 | } else { 63 | throw new IllegalArgumentException(); 64 | } 65 | } 66 | 67 | private static int doConvert(int delta, int amount) { 68 | if (amount >= 0) { 69 | if (delta == 0) { 70 | return amount; 71 | } else if (delta < 0) { 72 | return amount >>> -delta; 73 | } else if (delta >= Integer.numberOfLeadingZeros(amount)) { 74 | return Integer.MAX_VALUE; 75 | } else { 76 | return amount << delta; 77 | } 78 | } else { 79 | throw new IllegalArgumentException(); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/util/DebuggingUtils.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.util; 18 | 19 | /** 20 | * 21 | * @author Chris Dennis 22 | */ 23 | public final class DebuggingUtils { 24 | 25 | private static final String[] BASE_10_SUFFIXES = new String[] { "", "k", "M", "G", "T", "P", "E" }; 26 | //Also use the non i syntax to refer to base 2 as generally accepted. See http://en.wikipedia.org/wiki/Gigabyte 27 | private static final String[] BASE_2_SUFFIXES = new String[] { "", "K", "M", "G", "T", "P", "E" }; 28 | 29 | private static final long[] BASE_10_DIVISORS = new long[BASE_10_SUFFIXES.length]; 30 | static { 31 | for (int i = 0; i < BASE_10_DIVISORS.length; i++) { 32 | long n = 1; 33 | for (int j = 0; j < i; j++) { 34 | n *= 1000; 35 | } 36 | BASE_10_DIVISORS[i] = n; 37 | } 38 | } 39 | 40 | public static String toBase2SuffixedString(long n) { 41 | if (n > 0 && Long.bitCount(n) == 1) { 42 | int i = Long.numberOfTrailingZeros(Math.abs(n)) / 10; 43 | return (n >> (i * 10)) + BASE_2_SUFFIXES[i]; 44 | } else { 45 | int i = (63 - Long.numberOfLeadingZeros(n)) / 10; 46 | 47 | long factor = 1L << (i * 10); 48 | long leading = n / factor; 49 | long decimalFactor = factor / 10; 50 | if (decimalFactor == 0) { 51 | return leading + BASE_2_SUFFIXES[i]; 52 | } else { 53 | long decimal = (n - (leading * factor)) / (factor / 10); 54 | return leading + "." + decimal + BASE_2_SUFFIXES[i]; 55 | } 56 | } 57 | } 58 | 59 | public static String toBase10SuffixedString(long n) { 60 | for (int i = 0; i < BASE_10_SUFFIXES.length; i++) { 61 | long d = (n / 1000) / BASE_10_DIVISORS[i]; 62 | 63 | if (d == 0) { 64 | return (n / BASE_10_DIVISORS[i]) + BASE_10_SUFFIXES[i]; 65 | } 66 | } 67 | 68 | throw new AssertionError(); 69 | } 70 | 71 | private DebuggingUtils() { 72 | // 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/test/java/org/terracotta/offheapstore/storage/portability/serializable/ArrayPackageScopeTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.storage.portability.serializable; 18 | 19 | import org.terracotta.offheapstore.storage.portability.Portability; 20 | import org.terracotta.offheapstore.storage.portability.SerializablePortability; 21 | 22 | import java.io.Serializable; 23 | import java.lang.reflect.Array; 24 | import java.nio.ByteBuffer; 25 | 26 | import org.junit.Assert; 27 | import org.junit.Test; 28 | 29 | import static org.terracotta.offheapstore.storage.portability.serializable.SerializablePortabilityTestUtilities.createClassNameRewritingLoader; 30 | import static org.terracotta.offheapstore.storage.portability.serializable.SerializablePortabilityTestUtilities.newClassName; 31 | import static org.terracotta.offheapstore.storage.portability.serializable.SerializablePortabilityTestUtilities.popTccl; 32 | import static org.terracotta.offheapstore.storage.portability.serializable.SerializablePortabilityTestUtilities.pushTccl; 33 | 34 | /** 35 | * 36 | * @author cdennis 37 | */ 38 | public class ArrayPackageScopeTest { 39 | 40 | @Test 41 | public void testArrayPackageScope() throws Exception { 42 | Portability p = new SerializablePortability(); 43 | 44 | ClassLoader loaderA = createClassNameRewritingLoader(Foo_A.class); 45 | 46 | Serializable a = (Serializable) Array.newInstance(loaderA.loadClass(newClassName(Foo_A.class)), 0); 47 | ByteBuffer encodedA = p.encode(a); 48 | 49 | pushTccl(createClassNameRewritingLoader(Foo_B.class)); 50 | try { 51 | Serializable b = p.decode(encodedA); 52 | Assert.assertTrue(b.getClass().isArray()); 53 | } finally { 54 | popTccl(); 55 | } 56 | } 57 | 58 | public static class Foo_A implements java.io.Serializable { 59 | private static final long serialVersionUID = 0L; 60 | } 61 | 62 | static class Foo_B { 63 | private static final long serialVersionUID = 0L; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/test/java/org/terracotta/offheapstore/disk/OffHeapDiskMapClearingIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.disk; 18 | 19 | import org.terracotta.offheapstore.OffHeapHashMap; 20 | import org.terracotta.offheapstore.disk.paging.MappedPageSource; 21 | import org.terracotta.offheapstore.paging.OffHeapStorageArea; 22 | import org.terracotta.offheapstore.paging.Page; 23 | import org.terracotta.offheapstore.paging.PageSource; 24 | import org.terracotta.offheapstore.storage.IntegerStorageEngine; 25 | import org.terracotta.offheapstore.storage.SplitStorageEngine; 26 | 27 | import java.io.IOException; 28 | import java.util.Map; 29 | import java.util.concurrent.atomic.AtomicInteger; 30 | 31 | import org.hamcrest.core.Is; 32 | import org.junit.Assert; 33 | import org.junit.Test; 34 | 35 | /** 36 | * 37 | * @author cdennis 38 | */ 39 | public class OffHeapDiskMapClearingIT extends AbstractDiskTest { 40 | 41 | @Test 42 | public void testFrequentClearing() throws IOException { 43 | CountingPageSource source = new CountingPageSource(new MappedPageSource(dataFile)); 44 | Map map = new OffHeapHashMap<>(source, new SplitStorageEngine<>(IntegerStorageEngine 45 | .instance(), IntegerStorageEngine.instance())); 46 | 47 | for (int i = 0; i < 100000; i++) { 48 | map.clear(); 49 | } 50 | Assert.assertThat(source.allocations.get(), Is.is(1)); 51 | } 52 | 53 | static class CountingPageSource implements PageSource { 54 | 55 | private final AtomicInteger allocations = new AtomicInteger(); 56 | private final PageSource delegate; 57 | 58 | public CountingPageSource(PageSource delegate) { 59 | this.delegate = delegate; 60 | } 61 | 62 | @Override 63 | public Page allocate(int size, boolean thief, boolean victim, OffHeapStorageArea owner) { 64 | allocations.incrementAndGet(); 65 | return delegate.allocate(size, thief, victim, owner); 66 | } 67 | 68 | @Override 69 | public void free(Page page) { 70 | delegate.free(page); 71 | } 72 | 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/ReadWriteLockedOffHeapHashMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore; 18 | 19 | import java.util.concurrent.locks.Lock; 20 | import java.util.concurrent.locks.ReentrantReadWriteLock; 21 | 22 | import org.terracotta.offheapstore.paging.PageSource; 23 | import org.terracotta.offheapstore.storage.StorageEngine; 24 | 25 | /** 26 | * A concurrent-read, exclusive-write off-heap hash-map. 27 | *

28 | * This map uses a regular {@code ReentrantReadWriteLock} to provide read/write 29 | * exclusion/sharing properties. 30 | * 31 | * @param the type of keys maintained by this map 32 | * @param the type of mapped values 33 | * 34 | * @author Chris Dennis 35 | */ 36 | public class ReadWriteLockedOffHeapHashMap extends AbstractLockedOffHeapHashMap { 37 | 38 | private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); 39 | 40 | public ReadWriteLockedOffHeapHashMap(PageSource tableSource, StorageEngine storageEngine) { 41 | super(tableSource, storageEngine); 42 | } 43 | 44 | public ReadWriteLockedOffHeapHashMap(PageSource tableSource, boolean tableAllocationsSteal, StorageEngine storageEngine) { 45 | super(tableSource, tableAllocationsSteal, storageEngine); 46 | } 47 | 48 | public ReadWriteLockedOffHeapHashMap(PageSource tableSource, StorageEngine storageEngine, int tableSize) { 49 | super(tableSource, storageEngine, tableSize); 50 | } 51 | 52 | public ReadWriteLockedOffHeapHashMap(PageSource tableSource, boolean tableAllocationsSteal, StorageEngine storageEngine, int tableSize) { 53 | super(tableSource, tableAllocationsSteal, storageEngine, tableSize); 54 | } 55 | 56 | @Override 57 | public Lock readLock() { 58 | return lock.readLock(); 59 | } 60 | 61 | @Override 62 | public Lock writeLock() { 63 | return lock.writeLock(); 64 | } 65 | 66 | @Override 67 | public ReentrantReadWriteLock getLock() { 68 | return lock; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/set/OffHeapHashSet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.set; 18 | 19 | import java.util.AbstractSet; 20 | import java.util.Collection; 21 | import java.util.Iterator; 22 | 23 | import org.terracotta.offheapstore.OffHeapHashMap; 24 | import org.terracotta.offheapstore.paging.PageSource; 25 | import org.terracotta.offheapstore.storage.StorageEngine; 26 | 27 | /** 28 | * 29 | * @author cdennis 30 | */ 31 | public class OffHeapHashSet extends AbstractSet { 32 | 33 | private final OffHeapHashMap map; 34 | 35 | public OffHeapHashSet(PageSource source, boolean tableSteals, StorageEngine engine, int capacity) { 36 | this(new OffHeapHashMap<>(source, tableSteals, engine, capacity)); 37 | } 38 | 39 | public OffHeapHashSet(OffHeapHashMap map) { 40 | this.map = map; 41 | } 42 | 43 | @Override 44 | public int size() { 45 | return map.size(); 46 | } 47 | 48 | @Override 49 | public boolean isEmpty() { 50 | return map.isEmpty(); 51 | } 52 | 53 | @Override 54 | public boolean contains(Object o) { 55 | return map.containsKey(o); 56 | } 57 | 58 | @Override 59 | public Iterator iterator() { 60 | return map.keySet().iterator(); 61 | } 62 | 63 | @Override 64 | public Object[] toArray() { 65 | return map.keySet().toArray(); 66 | } 67 | 68 | @Override 69 | public T[] toArray(T[] ts) { 70 | return map.keySet().toArray(ts); 71 | } 72 | 73 | @Override 74 | public boolean add(E e) { 75 | return map.put(e, Boolean.TRUE) == null; 76 | } 77 | 78 | @Override 79 | public boolean remove(Object o) { 80 | return map.remove(o) != null; 81 | } 82 | 83 | @Override 84 | public boolean containsAll(Collection clctn) { 85 | return map.keySet().containsAll(clctn); 86 | } 87 | 88 | @Override 89 | public void clear() { 90 | map.clear(); 91 | } 92 | 93 | public StorageEngine getStorageEngine() { 94 | return map.getStorageEngine(); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/test/java/com/terracottatech/offheapstore/storage/portability/serializable/ArrayPackageScopeTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | /* 18 | * To change this template, choose Tools | Templates 19 | * and open the template in the editor. 20 | */ 21 | package com.terracottatech.offheapstore.storage.portability.serializable; 22 | 23 | import org.terracotta.offheapstore.storage.portability.Portability; 24 | 25 | import java.io.Serializable; 26 | import java.lang.reflect.Array; 27 | import java.nio.ByteBuffer; 28 | 29 | import org.junit.Assert; 30 | import org.junit.Test; 31 | 32 | import static com.terracottatech.offheapstore.storage.portability.serializable.SerializablePortabilityTestUtilities.createClassNameRewritingLoader; 33 | import static com.terracottatech.offheapstore.storage.portability.serializable.SerializablePortabilityTestUtilities.newClassName; 34 | import static com.terracottatech.offheapstore.storage.portability.serializable.SerializablePortabilityTestUtilities.popTccl; 35 | import static com.terracottatech.offheapstore.storage.portability.serializable.SerializablePortabilityTestUtilities.pushTccl; 36 | 37 | /** 38 | * 39 | * @author cdennis 40 | */ 41 | public class ArrayPackageScopeTest extends AbstractSerializablePortabilityTest { 42 | 43 | @Test 44 | public void testArrayPackageScope() throws Exception { 45 | Portability p = createPortability(); 46 | 47 | ClassLoader loaderA = createClassNameRewritingLoader(Foo_A.class); 48 | 49 | Serializable a = (Serializable) Array.newInstance(loaderA.loadClass(newClassName(Foo_A.class)), 0); 50 | ByteBuffer encodedA = p.encode(a); 51 | 52 | pushTccl(createClassNameRewritingLoader(Foo_B.class)); 53 | try { 54 | Serializable b = p.decode(encodedA); 55 | Assert.assertTrue(b.getClass().isArray()); 56 | } finally { 57 | popTccl(); 58 | } 59 | } 60 | 61 | public static class Foo_A implements java.io.Serializable { 62 | private static final long serialVersionUID = 0L; 63 | } 64 | 65 | static class Foo_B { 66 | private static final long serialVersionUID = 0L; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright 2018-2023 Terracotta, Inc., a Software AG company. 3 | # Copyright IBM Corp. 2024, 2025 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | 18 | # See shared code location for steps and parameters: 19 | # https://dev.azure.com/TerracottaCI/_git/terracotta 20 | 21 | resources: 22 | repositories: 23 | - repository: templates 24 | type: git 25 | name: terracotta/terracotta 26 | 27 | jobs: 28 | - template: build-templates/maven-common.yml@templates 29 | parameters: 30 | jobName: Linux_Java_8 31 | timeoutInMinutes: 180 32 | options: -B -Djava.test.version=1.8 33 | mavenGoals: 'clean verify' 34 | fetchDepth: 0 # need unlimited for license plugin 35 | - template: build-templates/maven-common.yml@templates 36 | parameters: 37 | jobName: Linux_Java_11 38 | timeoutInMinutes: 180 39 | options: -B -Djava.test.version=1.11 40 | mavenGoals: 'clean verify' 41 | fetchDepth: 0 # need unlimited for license plugin 42 | - template: build-templates/maven-common.yml@templates 43 | parameters: 44 | jobName: Linux_Java_17 45 | timeoutInMinutes: 180 46 | options: -B -Djava.test.version=1.17 47 | mavenGoals: 'clean verify' 48 | fetchDepth: 0 # need unlimited for license plugin 49 | - template: build-templates/maven-common.yml@templates 50 | parameters: 51 | jobName: Windows_Java_8 52 | timeoutInMinutes: 180 53 | vmImage: 'windows-latest' 54 | options: -B -Djava.test.version=1.8 55 | mavenGoals: 'clean verify' 56 | fetchDepth: 0 # need unlimited for license plugin 57 | - template: build-templates/maven-common.yml@templates 58 | parameters: 59 | jobName: Windows_Java_11 60 | timeoutInMinutes: 180 61 | vmImage: 'windows-latest' 62 | options: -B -Djava.test.version=1.11 63 | mavenGoals: 'clean verify' 64 | fetchDepth: 0 # need unlimited for license plugin 65 | - template: build-templates/maven-common.yml@templates 66 | parameters: 67 | jobName: Windows_Java_17 68 | timeoutInMinutes: 180 69 | vmImage: 'windows-latest' 70 | options: -B -Djava.test.version=1.17 71 | mavenGoals: 'clean verify' 72 | fetchDepth: 0 # need unlimited for license plugin 73 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/disk/storage/PersistentSplitStorageEngine.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.disk.storage; 18 | 19 | import java.io.IOException; 20 | import java.io.ObjectInput; 21 | import java.io.ObjectOutput; 22 | 23 | import org.terracotta.offheapstore.disk.persistent.Persistent; 24 | import org.terracotta.offheapstore.disk.persistent.PersistentHalfStorageEngine; 25 | import org.terracotta.offheapstore.disk.persistent.PersistentStorageEngine; 26 | import org.terracotta.offheapstore.storage.SplitStorageEngine; 27 | import org.terracotta.offheapstore.util.Factory; 28 | 29 | /** 30 | * 31 | * @author Chris Dennis 32 | */ 33 | public class PersistentSplitStorageEngine extends SplitStorageEngine implements PersistentStorageEngine { 34 | 35 | public static Factory> createPersistentFactory(final Factory> keyFactory, final Factory> valueFactory) { 36 | return () -> new PersistentSplitStorageEngine<>(keyFactory.newInstance(), valueFactory.newInstance()); 37 | } 38 | 39 | public PersistentSplitStorageEngine(PersistentHalfStorageEngine keyStorageEngine, PersistentHalfStorageEngine valueStorageEngine) { 40 | super(keyStorageEngine, valueStorageEngine); 41 | } 42 | 43 | @Override 44 | public void flush() throws IOException { 45 | ((Persistent) keyStorageEngine).flush(); 46 | ((Persistent) valueStorageEngine).flush(); 47 | } 48 | 49 | @Override 50 | public void close() throws IOException { 51 | ((Persistent) keyStorageEngine).close(); 52 | ((Persistent) valueStorageEngine).close(); 53 | } 54 | 55 | @Override 56 | public void persist(ObjectOutput output) throws IOException { 57 | ((Persistent) keyStorageEngine).persist(output); 58 | ((Persistent) valueStorageEngine).persist(output); 59 | } 60 | 61 | @Override 62 | public void bootstrap(ObjectInput input) throws IOException { 63 | ((Persistent) keyStorageEngine).bootstrap(input); 64 | ((Persistent) valueStorageEngine).bootstrap(input); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/concurrent/ConcurrentWriteLockedOffHeapHashMap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.concurrent; 18 | 19 | import org.terracotta.offheapstore.WriteLockedOffHeapHashMap; 20 | import org.terracotta.offheapstore.paging.PageSource; 21 | import org.terracotta.offheapstore.storage.StorageEngine; 22 | import org.terracotta.offheapstore.util.Factory; 23 | 24 | /** 25 | * A striped exclusive-read/write map. 26 | *

27 | * This implementation uses instances of {@link WriteLockedOffHeapHashMap} 28 | * for its segments. 29 | * 30 | * @param the type of keys maintained by this map 31 | * @param the type of mapped values 32 | * 33 | * @author Chris Dennis 34 | * @see WriteLockedOffHeapHashMap 35 | */ 36 | public class ConcurrentWriteLockedOffHeapHashMap extends AbstractConcurrentOffHeapMap{ 37 | 38 | /** 39 | * Creates a map using the given table buffer source and storage engine 40 | * factory. 41 | * 42 | * @param tableSource buffer source from which hash tables are allocated 43 | * @param storageEngineFactory factory for the segment storage engines 44 | */ 45 | public ConcurrentWriteLockedOffHeapHashMap(PageSource tableSource, Factory> storageEngineFactory) { 46 | super(new WriteLockedOffHeapHashMapFactory<>(tableSource, storageEngineFactory)); 47 | } 48 | 49 | /** 50 | * Creates a map using the given table buffer source, storage engine 51 | * factory, initial table size, and concurrency. 52 | * 53 | * @param tableSource buffer source from which hash tables are allocated 54 | * @param storageEngineFactory factory for the segment storage engines 55 | * @param tableSize initial table size (summed across all segments) 56 | * @param concurrency number of segments 57 | */ 58 | public ConcurrentWriteLockedOffHeapHashMap(PageSource tableSource, Factory> storageEngineFactory, long tableSize, 59 | int concurrency) { 60 | super(new WriteLockedOffHeapHashMapFactory<>(tableSource, storageEngineFactory, (int) (tableSize / concurrency)), concurrency); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/storage/PortabilityBasedHalfStorageEngine.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.storage; 18 | 19 | import java.nio.ByteBuffer; 20 | 21 | import org.terracotta.offheapstore.storage.portability.Portability; 22 | 23 | /** 24 | * 25 | * @author cdennis 26 | */ 27 | public abstract class PortabilityBasedHalfStorageEngine implements HalfStorageEngine { 28 | 29 | private final Portability portability; 30 | 31 | private CachedEncode lastObject; 32 | 33 | public PortabilityBasedHalfStorageEngine(Portability portability) { 34 | this.portability = portability; 35 | } 36 | 37 | @Override 38 | public Integer write(T object, int hash) { 39 | if (lastObject != null && lastObject.get() == object) { 40 | return writeBuffer(lastObject.getEncoded(), hash); 41 | } else { 42 | ByteBuffer buffer = portability.encode(object); 43 | Integer result = writeBuffer(buffer, hash); 44 | if (result == null) { 45 | lastObject = new CachedEncode<>(object, buffer.duplicate()); 46 | } 47 | return result; 48 | } 49 | } 50 | 51 | @Override 52 | public abstract void free(int encoding); 53 | 54 | @SuppressWarnings("unchecked") 55 | @Override 56 | public T read(int encoding) { 57 | return (T) portability.decode(readBuffer(encoding)); 58 | } 59 | 60 | @Override 61 | public boolean equals(Object value, int encoding) { 62 | return portability.equals(value, readBuffer(encoding)); 63 | } 64 | 65 | protected abstract ByteBuffer readBuffer(int encoding); 66 | 67 | protected abstract Integer writeBuffer(ByteBuffer buffer, int hash); 68 | 69 | @Override 70 | public void invalidateCache() { 71 | lastObject = null; 72 | } 73 | 74 | static class CachedEncode { 75 | private final T object; 76 | 77 | private final ByteBuffer buffer; 78 | 79 | public CachedEncode(T object, ByteBuffer buffer) { 80 | this.object = object; 81 | this.buffer = buffer; 82 | } 83 | 84 | final T get() { 85 | return object; 86 | } 87 | 88 | final ByteBuffer getEncoded() { 89 | return buffer.duplicate(); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/com/terracottatech/offheapstore/filesystem/SeekableOutputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.terracottatech.offheapstore.filesystem; 18 | 19 | import java.io.IOException; 20 | import java.io.OutputStream; 21 | 22 | /** 23 | * This interface provides for writing bytes to an OffHeap file. For all the methods in this interface that write bytes, 24 | * it is generally true that if a byte cannot be written for any reason, an IOException is thrown. 25 | * 26 | * @author dkumar 27 | */ 28 | public abstract class SeekableOutputStream extends OutputStream { 29 | 30 | /** 31 | * {@inheritDoc} 32 | */ 33 | @Override 34 | public abstract void write(int b) throws IOException; 35 | 36 | /** 37 | * Returns the current offset in this file. 38 | * 39 | * @return the offset from the beginning of the file, in bytes, at which the next read occurs. 40 | * @throws IOException if an I/O error occurs. 41 | */ 42 | public abstract long getFilePointer() throws IOException; 43 | 44 | /** 45 | * Sets the file-pointer offset, measured from the beginning of this file, at which the next write occurs. The offset 46 | * may be set beyond the end of the file. Setting the offset beyond the end of the file does not change the file 47 | * length. The file length will change only by writing after the offset has been set beyond the end of the file. 48 | * 49 | * @param pos - the offset position, measured in bytes from the beginning of the file, at which to set the file 50 | * pointer. 51 | * @throws IOException if pos is less than 0 or if an I/O error occurs. 52 | */ 53 | public abstract void seek(long pos) throws IOException; 54 | 55 | /** 56 | * Clears the stream. Calling flush after a reset will clear the contents of the file. 57 | * 58 | * @throws IOException 59 | */ 60 | public abstract void reset() throws IOException; 61 | 62 | /** 63 | * Returns the length of the stream. This method flushes the buffers to the file before calculating the length. 64 | * 65 | * @return length of the stream in bytes 66 | * @throws IOException 67 | */ 68 | public abstract long length() throws IOException; 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/test/java/org/terracotta/offheapstore/pinning/ConcurrentPinningIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.pinning; 18 | 19 | import static org.terracotta.offheapstore.util.MemoryUnit.KILOBYTES; 20 | 21 | import org.junit.AssumptionViolatedException; 22 | import org.terracotta.offheapstore.concurrent.ConcurrentOffHeapClockCache; 23 | import org.terracotta.offheapstore.paging.PageSource; 24 | import org.terracotta.offheapstore.storage.IntegerStorageEngine; 25 | import org.terracotta.offheapstore.storage.OffHeapBufferStorageEngine; 26 | import org.terracotta.offheapstore.storage.PointerSize; 27 | import org.terracotta.offheapstore.storage.SplitStorageEngine; 28 | import org.terracotta.offheapstore.storage.StorageEngine; 29 | import org.terracotta.offheapstore.storage.portability.ByteArrayPortability; 30 | import org.terracotta.offheapstore.storage.portability.SerializablePortability; 31 | import org.terracotta.offheapstore.util.Factory; 32 | 33 | import org.hamcrest.core.Is; 34 | import org.junit.Assume; 35 | 36 | public class ConcurrentPinningIT extends AbstractPinningIT { 37 | 38 | @Override 39 | protected PinnableCache createPinnedIntegerCache(PageSource source) { 40 | Assume.assumeThat(getPointerSize(), Is.is(PointerSize.INT)); 41 | Factory> storageEngineFactory = SplitStorageEngine.createFactory(IntegerStorageEngine.createFactory(), IntegerStorageEngine.createFactory()); 42 | return new ConcurrentOffHeapClockCache<>(source, storageEngineFactory); 43 | } 44 | 45 | @Override 46 | protected PinnableCache createPinnedByteArrayCache(PageSource source) { 47 | Factory> storageEngineFactory = OffHeapBufferStorageEngine.createFactory(getPointerSize(), source, KILOBYTES.toBytes(1), new SerializablePortability(), ByteArrayPortability.INSTANCE, false, false); 48 | return new ConcurrentOffHeapClockCache<>(source, storageEngineFactory); 49 | } 50 | 51 | @Override 52 | protected PinnableCache createSharingPinnedByteArrayCache(PageSource source) { 53 | throw new AssumptionViolatedException("Cannot create sharing concurrent cache"); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/util/ByteBufferInputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.util; 18 | 19 | import java.io.IOException; 20 | import java.io.InputStream; 21 | import java.nio.ByteBuffer; 22 | import java.nio.InvalidMarkException; 23 | 24 | /** 25 | * 26 | * @author Chris Dennis 27 | */ 28 | public class ByteBufferInputStream extends InputStream { 29 | 30 | private final ByteBuffer buffer; 31 | 32 | public ByteBufferInputStream(ByteBuffer buffer) { 33 | this.buffer = buffer; 34 | } 35 | 36 | @Override 37 | public int read() throws IOException { 38 | if (buffer.hasRemaining()) { 39 | return buffer.get() & 0xff; 40 | } else { 41 | return -1; 42 | } 43 | } 44 | 45 | @Override 46 | public int read(byte b[], int off, int len) throws IOException { 47 | if (b == null) { 48 | throw new NullPointerException(); 49 | } else if (off < 0 || len < 0 || len > b.length - off) { 50 | throw new IndexOutOfBoundsException(); 51 | } else if (len == 0) { 52 | return 0; 53 | } 54 | 55 | int size = Math.min(len, buffer.remaining()); 56 | if (size <= 0) { 57 | return -1; 58 | } 59 | 60 | buffer.get(b, off, size); 61 | 62 | return size; 63 | } 64 | 65 | @Override 66 | public long skip(long n) throws IOException { 67 | if (n < 0) { 68 | return 0; 69 | } else { 70 | long skip = Math.min(n, buffer.remaining()); 71 | buffer.position((int) (buffer.position() + skip)); 72 | return skip; 73 | } 74 | } 75 | 76 | @Override 77 | public int available() throws IOException { 78 | return buffer.remaining(); 79 | } 80 | 81 | @Override 82 | public synchronized void mark(int readlimit) { 83 | buffer.mark(); 84 | } 85 | 86 | @Override 87 | public synchronized void reset() throws IOException { 88 | try { 89 | buffer.reset(); 90 | } catch (InvalidMarkException e) { 91 | throw (IOException) (new IOException().initCause(e)); 92 | } 93 | } 94 | 95 | @Override 96 | public boolean markSupported() { 97 | return true; 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/com/terracottatech/offheapstore/filesystem/Directory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.terracottatech.offheapstore.filesystem; 18 | 19 | import java.io.FileNotFoundException; 20 | import java.io.IOException; 21 | import java.util.Set; 22 | 23 | /** 24 | * This interface facilitates creation of random access files in the OffHeap file system. It provides methods for 25 | * querying the properties of the files, checking for their existence, deleting them, getting their length etc. 26 | * 27 | * @author dkumar 28 | */ 29 | public interface Directory { 30 | 31 | /** 32 | * Creates a new, empty file or returns a reference to the named file if it already exists. 33 | * 34 | * @param name name of the File to be created 35 | * @return reference to the new or existing file 36 | * @throws IOException if an error occurred while processing the request. 37 | */ 38 | File getOrCreateFile(String name) throws IOException; 39 | 40 | /** 41 | * Deletes a File. This method will block until all the streams associated with the file have been closed. 42 | * 43 | * @param name of the file to be deleted. 44 | * @throws IOException if an I/O error occurs. 45 | * @throws FileNotFoundException if the file is not found. 46 | */ 47 | void deleteFile(String name) throws IOException, FileNotFoundException; 48 | 49 | /** 50 | * Checks if a File exists in the directory 51 | * 52 | * @param name name of the file to be checked for existence. 53 | * @return true if the file exists in the directory, false otherwise. 54 | */ 55 | boolean fileExists(String name); 56 | 57 | /** 58 | * Retrieves the names of files present in the directory 59 | * 60 | * @return set containing names of the files. 61 | * @throws IOException if an error occurs while processing the request. 62 | */ 63 | Set listFiles() throws IOException; 64 | 65 | /** 66 | * Reports the total size of the directory 67 | * 68 | * @return sum of sizes of files in bytes. 69 | */ 70 | long getSizeInBytes(); 71 | 72 | /** 73 | * Deletes all files present under this directory 74 | * 75 | * @throws IOException if an I/O error occurs 76 | */ 77 | public void deleteAllFiles() throws IOException; 78 | 79 | } 80 | -------------------------------------------------------------------------------- /src/test/java/org/terracotta/offheapstore/pinning/WriteLockedPinningIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.pinning; 18 | 19 | import org.terracotta.offheapstore.pinning.PinnableCache; 20 | import static org.terracotta.offheapstore.util.MemoryUnit.KILOBYTES; 21 | 22 | import org.terracotta.offheapstore.WriteLockedOffHeapClockCache; 23 | import org.terracotta.offheapstore.paging.PageSource; 24 | import org.terracotta.offheapstore.storage.IntegerStorageEngine; 25 | import org.terracotta.offheapstore.storage.OffHeapBufferStorageEngine; 26 | import org.terracotta.offheapstore.storage.PointerSize; 27 | import org.terracotta.offheapstore.storage.SplitStorageEngine; 28 | import org.terracotta.offheapstore.storage.StorageEngine; 29 | import org.terracotta.offheapstore.storage.portability.ByteArrayPortability; 30 | import org.terracotta.offheapstore.storage.portability.SerializablePortability; 31 | 32 | import org.hamcrest.core.Is; 33 | import org.junit.Assume; 34 | 35 | public class WriteLockedPinningIT extends AbstractPinningIT { 36 | 37 | @Override 38 | protected PinnableCache createPinnedIntegerCache(PageSource source) { 39 | Assume.assumeThat(getPointerSize(), Is.is(PointerSize.INT)); 40 | StorageEngine storageEngine = new SplitStorageEngine<>(new IntegerStorageEngine(), new IntegerStorageEngine()); 41 | return new WriteLockedOffHeapClockCache<>(source, storageEngine); 42 | } 43 | 44 | @Override 45 | protected PinnableCache createPinnedByteArrayCache(PageSource source) { 46 | StorageEngine storageEngine = new OffHeapBufferStorageEngine<>(getPointerSize(), source, KILOBYTES.toBytes(1), new SerializablePortability(), ByteArrayPortability.INSTANCE); 47 | return new WriteLockedOffHeapClockCache<>(source, storageEngine); 48 | } 49 | 50 | @Override 51 | protected PinnableCache createSharingPinnedByteArrayCache(PageSource source) { 52 | StorageEngine storageEngine = new OffHeapBufferStorageEngine<>(getPointerSize(), source, KILOBYTES.toBytes(1), new SerializablePortability(), ByteArrayPortability.INSTANCE, true, true); 53 | return new WriteLockedOffHeapClockCache<>(source, true, storageEngine); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/terracottatech/offheapstore/filesystem/SeekableInputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.terracottatech.offheapstore.filesystem; 18 | 19 | import java.io.EOFException; 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | 23 | /** 24 | *

25 | * This interface provides for reading bytes from an OffHeap File. 26 | *

27 | * It is generally true of all the reading routines in this interface that if end of file is reached before the desired 28 | * number of bytes has been read, an EOFException (which is a kind of IOException) is thrown. If any byte cannot be read 29 | * for any reason other than end of file, an IOException other than EOFException is thrown. In particular, an 30 | * IOException may be thrown if the input stream has been closed. 31 | * 32 | * @author dkumar 33 | */ 34 | public abstract class SeekableInputStream extends InputStream { 35 | 36 | /** 37 | * {@inheritDoc} 38 | */ 39 | @Override 40 | public abstract int read() throws IOException; 41 | 42 | /** 43 | * {@inheritDoc} 44 | */ 45 | public abstract void readBytes(byte[] b, int offset, int len) throws IOException; 46 | 47 | /** 48 | * Returns the current offset in this file. 49 | * 50 | * @return the offset from the beginning of the file, in bytes, at which the next read occurs. 51 | * @throws IOException if an I/O error occurs. 52 | */ 53 | public abstract long getFilePointer() throws IOException; 54 | 55 | /** 56 | *

57 | * Closes this stream and releases any system resources associated with the stream. 58 | * 59 | * @throws IOException if an I/O error occurs. 60 | */ 61 | @Override 62 | public abstract void close() throws IOException; 63 | 64 | /** 65 | * Sets the file-pointer offset, measured from the beginning of this file, at which the next read occurs. 66 | * 67 | * @param pos - the offset position, measured in bytes from the beginning of the file, at which to set the file 68 | * pointer. 69 | * @throws IOException if pos is less than 0 or if an I/O error occurs. 70 | * @throws EOFException if pos beyond end of file 71 | */ 72 | public abstract void seek(long pos) throws IOException, EOFException; 73 | 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/terracottatech/offheapstore/storage/restartable/PersistentRestartableStorageEngine.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.terracottatech.offheapstore.storage.restartable; 18 | 19 | import java.io.IOException; 20 | import java.io.ObjectInput; 21 | import java.io.ObjectOutput; 22 | import java.nio.ByteBuffer; 23 | 24 | import com.terracottatech.frs.RestartStore; 25 | import org.terracotta.offheapstore.disk.persistent.PersistentStorageEngine; 26 | import org.terracotta.offheapstore.storage.BinaryStorageEngine; 27 | import org.terracotta.offheapstore.util.Factory; 28 | 29 | public class PersistentRestartableStorageEngine> & BinaryStorageEngine, I, K, V> extends RestartableStorageEngine implements PersistentStorageEngine { 30 | 31 | public static > & BinaryStorageEngine, I, K, V> Factory> createPersistentFactory(final I identifier, final RestartStore transactionSource, final Factory delegateFactory, final boolean synchronous) { 32 | return new Factory>() { 33 | 34 | @Override 35 | public PersistentRestartableStorageEngine newInstance() { 36 | return new PersistentRestartableStorageEngine(identifier, transactionSource, delegateFactory.newInstance(), synchronous); 37 | } 38 | }; 39 | } 40 | 41 | public PersistentRestartableStorageEngine(I identifier, RestartStore transactionSource, T storageEngine, boolean synchronous) { 42 | super(identifier, transactionSource, storageEngine, synchronous); 43 | } 44 | 45 | @Override 46 | public void flush() throws IOException { 47 | delegateStorageEngine.flush(); 48 | } 49 | 50 | @Override 51 | public void close() throws IOException { 52 | delegateStorageEngine.close(); 53 | } 54 | 55 | @Override 56 | public void persist(ObjectOutput output) throws IOException { 57 | delegateStorageEngine.persist(output); 58 | } 59 | 60 | @Override 61 | public void bootstrap(ObjectInput input) throws IOException { 62 | delegateStorageEngine.bootstrap(input); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/test/java/org/terracotta/offheapstore/pinning/ConcurrentWriteLockedPinningIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.pinning; 18 | 19 | import static org.terracotta.offheapstore.util.MemoryUnit.KILOBYTES; 20 | 21 | import org.junit.AssumptionViolatedException; 22 | import org.terracotta.offheapstore.concurrent.ConcurrentWriteLockedOffHeapClockCache; 23 | import org.terracotta.offheapstore.paging.PageSource; 24 | import org.terracotta.offheapstore.storage.IntegerStorageEngine; 25 | import org.terracotta.offheapstore.storage.OffHeapBufferStorageEngine; 26 | import org.terracotta.offheapstore.storage.PointerSize; 27 | import org.terracotta.offheapstore.storage.SplitStorageEngine; 28 | import org.terracotta.offheapstore.storage.StorageEngine; 29 | import org.terracotta.offheapstore.storage.portability.ByteArrayPortability; 30 | import org.terracotta.offheapstore.storage.portability.SerializablePortability; 31 | import org.terracotta.offheapstore.util.Factory; 32 | 33 | import org.hamcrest.core.Is; 34 | import org.junit.Assume; 35 | 36 | public class ConcurrentWriteLockedPinningIT extends AbstractPinningIT { 37 | 38 | @Override 39 | protected PinnableCache createPinnedIntegerCache(PageSource source) { 40 | Assume.assumeThat(getPointerSize(), Is.is(PointerSize.INT)); 41 | Factory> storageEngineFactory = SplitStorageEngine.createFactory(IntegerStorageEngine.createFactory(), IntegerStorageEngine.createFactory()); 42 | return new ConcurrentWriteLockedOffHeapClockCache<>(source, storageEngineFactory); 43 | } 44 | 45 | @Override 46 | protected PinnableCache createPinnedByteArrayCache(PageSource source) { 47 | Factory> storageEngineFactory = OffHeapBufferStorageEngine.createFactory(getPointerSize(), source, KILOBYTES.toBytes(1), new SerializablePortability(), ByteArrayPortability.INSTANCE, false, false); 48 | return new ConcurrentWriteLockedOffHeapClockCache<>(source, storageEngineFactory); 49 | } 50 | 51 | @Override 52 | protected PinnableCache createSharingPinnedByteArrayCache(PageSource source) { 53 | throw new AssumptionViolatedException("Cannot create sharing concurrent cache"); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/test/java/org/terracotta/offheapstore/pinning/ReadWriteLockedPinningIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.pinning; 18 | 19 | import org.terracotta.offheapstore.pinning.PinnableCache; 20 | import static org.terracotta.offheapstore.util.MemoryUnit.KILOBYTES; 21 | 22 | import org.terracotta.offheapstore.ReadWriteLockedOffHeapClockCache; 23 | import org.terracotta.offheapstore.paging.PageSource; 24 | import org.terracotta.offheapstore.storage.IntegerStorageEngine; 25 | import org.terracotta.offheapstore.storage.OffHeapBufferStorageEngine; 26 | import org.terracotta.offheapstore.storage.PointerSize; 27 | import org.terracotta.offheapstore.storage.SplitStorageEngine; 28 | import org.terracotta.offheapstore.storage.StorageEngine; 29 | import org.terracotta.offheapstore.storage.portability.ByteArrayPortability; 30 | import org.terracotta.offheapstore.storage.portability.SerializablePortability; 31 | 32 | import org.hamcrest.core.Is; 33 | import org.junit.Assume; 34 | 35 | public class ReadWriteLockedPinningIT extends AbstractPinningIT { 36 | 37 | @Override 38 | protected PinnableCache createPinnedIntegerCache(PageSource source) { 39 | Assume.assumeThat(getPointerSize(), Is.is(PointerSize.INT)); 40 | StorageEngine storageEngine = new SplitStorageEngine<>(new IntegerStorageEngine(), new IntegerStorageEngine()); 41 | return new ReadWriteLockedOffHeapClockCache<>(source, storageEngine); 42 | } 43 | 44 | @Override 45 | protected PinnableCache createPinnedByteArrayCache(PageSource source) { 46 | StorageEngine storageEngine = new OffHeapBufferStorageEngine<>(getPointerSize(), source, KILOBYTES.toBytes(1), new SerializablePortability(), ByteArrayPortability.INSTANCE); 47 | return new ReadWriteLockedOffHeapClockCache<>(source, storageEngine); 48 | } 49 | 50 | @Override 51 | protected PinnableCache createSharingPinnedByteArrayCache(PageSource source) { 52 | StorageEngine storageEngine = new OffHeapBufferStorageEngine<>(getPointerSize(), source, KILOBYTES.toBytes(1), new SerializablePortability(), ByteArrayPortability.INSTANCE, true, true); 53 | return new ReadWriteLockedOffHeapClockCache<>(source, true, storageEngine); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /README.adoc: -------------------------------------------------------------------------------- 1 | //// 2 | // Copyright 2015-2024 Terracotta, Inc., a Software AG company. 3 | // Copyright IBM Corp. 2024, 2025 4 | // 5 | // Licensed under the Apache License, Version 2.0 (the "License"); 6 | // you may not use this file except in compliance with the License. 7 | // You may obtain a copy of the License at 8 | // 9 | // http://www.apache.org/licenses/LICENSE-2.0 10 | // 11 | // Unless required by applicable law or agreed to in writing, software 12 | // distributed under the License is distributed on an "AS IS" BASIS, 13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | // See the License for the specific language governing permissions and 15 | // limitations under the License. 16 | //// 17 | 18 | = OffHeap Store 19 | 20 | OffHeap Store is a library that provides a set of map and cache implementations 21 | that store data outside of the normal Java heap. Additionally it provides a 22 | bunch of interesting things to support these functions that might be interesting 23 | in isolation to some people. 24 | 25 | Licensed under the Apache License, Version 2.0 + 26 | (C) Terracotta, Inc., a Software AG company + 27 | (C) IBM Corp. 2024, 2025 + 28 | 29 | http://www.terracotta.org 30 | 31 | See also: http://www.github.com/ehcache/ehcache3 32 | 33 | image::https://dev.azure.com/TerracottaCI/terracotta/_apis/build/status/Terracotta-OSS.offheap-store?branchName=master[Build Status] 34 | 35 | == What's Available 36 | On the surface OffHeap Store contains implementations of: 37 | 38 | * Map (non thread-safe) 39 | * ConcurrentMap (single stripe or segmented; read-write locked or exclusively locked) 40 | * Set (but use +Collections.newSetFromMap(Map)+ instead) 41 | * Clock Cache (single stripe or segmented; read-write locked or exclusively locked) 42 | 43 | Additional functionality includes: 44 | 45 | * Cache Entry Pinning 46 | * Eviction Listeners 47 | * _Non-fault tolerant_ disk backend 48 | 49 | Things that might be interesting to some: 50 | 51 | * Per entry metadata (very basic API) 52 | * Serialization optimization (redundant ObjectStreamClass descriptor compression) 53 | * Native heap-alike implementation (+OffHeapStorageArea+) 54 | * A (crude) weak identity hash map (because the world needed one more) 55 | 56 | == Structure 57 | 58 | Like all software OffHeap Store is just a big stack of abstractions, rough structure starting at 59 | the bottom and working up. 60 | 61 | [horizontal] 62 | +BufferSource+:: +ByteBuffer+ factories [+org.terracotta.offheapstore.buffersource+] 63 | +PageSource+:: +Page+ factories, that uses ByteBuffers) [+org.terracotta.offheapstore.paging+] 64 | +OffHeapStorageArea+:: native heap-alike that uses pages) 65 | +StorageEngine+:: provide storage for POJOs, some use +OffHeapStorageArea+) 66 | +OffHeapHashMap+:: core map implementation, uses storage engine for K/V storage and a page for the hashtable. 67 | a million subclasses:: all the map derivatives: concurrent, evicting (caches), et al. 68 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/storage/IntegerStorageEngine.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.storage; 18 | 19 | import org.terracotta.offheapstore.storage.StorageEngine.Owner; 20 | import org.terracotta.offheapstore.util.Factory; 21 | 22 | /** 23 | * A symmetric {@code Integer} storage engine. 24 | *

25 | * This engine stores the keys and values directly as their primitive 26 | * representations, and therefore uses no additional data structure. 27 | * 28 | * @author Chris Dennis 29 | */ 30 | public class IntegerStorageEngine implements HalfStorageEngine { 31 | 32 | private static final IntegerStorageEngine SINGLETON = new IntegerStorageEngine(); 33 | private static final Factory FACTORY = () -> SINGLETON; 34 | 35 | public static IntegerStorageEngine instance() { 36 | return SINGLETON; 37 | } 38 | 39 | public static Factory createFactory() { 40 | return FACTORY; 41 | } 42 | 43 | @Override 44 | public Integer read(int address) { 45 | return address; 46 | } 47 | 48 | @Override 49 | public Integer write(Integer value, int hash) { 50 | return value; 51 | } 52 | 53 | @Override 54 | public void free(int address) { 55 | //no-op 56 | } 57 | 58 | @Override 59 | public boolean equals(Object key, int address) { 60 | return key instanceof Integer && ((Integer) key) == address; 61 | } 62 | 63 | @Override 64 | public void clear() { 65 | //no-op 66 | } 67 | 68 | @Override 69 | public long getAllocatedMemory() { 70 | return 0; 71 | } 72 | 73 | @Override 74 | public long getOccupiedMemory() { 75 | return 0; 76 | } 77 | 78 | @Override 79 | public long getVitalMemory() { 80 | return 0; 81 | } 82 | 83 | @Override 84 | public long getDataSize() { 85 | return 0; 86 | } 87 | 88 | @Override 89 | public void invalidateCache() { 90 | //no-op 91 | } 92 | 93 | @Override 94 | public void bind(Owner owner, long mask) { 95 | //no-op 96 | } 97 | 98 | @Override 99 | public void destroy() { 100 | //no-op 101 | } 102 | 103 | @Override 104 | public boolean shrink() { 105 | return false; 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /src/test/java/org/terracotta/offheapstore/WriteLockedOffHeapHashMapIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore; 18 | 19 | import org.terracotta.offheapstore.WriteLockedOffHeapHashMap; 20 | import java.util.concurrent.ConcurrentMap; 21 | 22 | import org.terracotta.offheapstore.buffersource.OffHeapBufferSource; 23 | import org.terracotta.offheapstore.paging.PageSource; 24 | import org.terracotta.offheapstore.paging.UnlimitedPageSource; 25 | import org.terracotta.offheapstore.storage.IntegerStorageEngine; 26 | import org.terracotta.offheapstore.storage.OffHeapBufferHalfStorageEngine; 27 | import org.terracotta.offheapstore.storage.SplitStorageEngine; 28 | import org.terracotta.offheapstore.storage.portability.ByteArrayPortability; 29 | import org.terracotta.offheapstore.util.Generator; 30 | import static org.terracotta.offheapstore.util.Generator.BAD_GENERATOR; 31 | import static org.terracotta.offheapstore.util.Generator.GOOD_GENERATOR; 32 | import org.terracotta.offheapstore.util.Generator.SpecialInteger; 33 | import org.terracotta.offheapstore.util.ParallelParameterized; 34 | import java.util.Arrays; 35 | import java.util.Collection; 36 | import static org.hamcrest.core.Is.is; 37 | import static org.junit.Assume.assumeThat; 38 | import org.junit.runner.RunWith; 39 | 40 | @RunWith(ParallelParameterized.class) 41 | public class WriteLockedOffHeapHashMapIT extends AbstractConcurrentOffHeapMapIT { 42 | 43 | @ParallelParameterized.Parameters(name = "generator={0}") 44 | public static Collection data() { 45 | return Arrays.asList(new Object[] {GOOD_GENERATOR}, new Object[] {BAD_GENERATOR}); 46 | } 47 | 48 | public WriteLockedOffHeapHashMapIT(Generator generator) { 49 | super(generator); 50 | } 51 | 52 | @Override 53 | protected ConcurrentMap createMap(Generator generator) { 54 | return new WriteLockedOffHeapHashMap<>(new UnlimitedPageSource(new OffHeapBufferSource()), generator.engine(), 1); 55 | } 56 | 57 | @Override 58 | protected ConcurrentMap createOffHeapBufferMap(PageSource source) { 59 | assumeThat(generator, is(GOOD_GENERATOR)); 60 | return new WriteLockedOffHeapHashMap<>(source, new SplitStorageEngine<>(new IntegerStorageEngine(), new OffHeapBufferHalfStorageEngine<>(source, 1024, ByteArrayPortability.INSTANCE))); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/test/java/org/terracotta/offheapstore/storage/SerializableStorageEngineIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.storage; 18 | 19 | import org.terracotta.offheapstore.storage.SerializableStorageEngine; 20 | import java.util.Collections; 21 | import java.util.Map; 22 | 23 | import org.junit.Assert; 24 | import org.junit.Test; 25 | 26 | import org.terracotta.offheapstore.OffHeapHashMap; 27 | import org.terracotta.offheapstore.buffersource.OffHeapBufferSource; 28 | import org.terracotta.offheapstore.paging.UnlimitedPageSource; 29 | import org.terracotta.offheapstore.util.PointerSizeParameterizedTest; 30 | 31 | public class SerializableStorageEngineIT extends PointerSizeParameterizedTest { 32 | 33 | @Test 34 | public void tableResizeTest() { 35 | Map map = new OffHeapHashMap<>(new UnlimitedPageSource(new OffHeapBufferSource()), new SerializableStorageEngine(getPointerSize(), new UnlimitedPageSource(new OffHeapBufferSource()), 1)); 36 | 37 | for (int i = 0; i < 100; i++) { 38 | map.put(Integer.toString(i), Integer.toString(i)); 39 | 40 | for (int j = 0; j <= i; j++) { 41 | Assert.assertEquals(Integer.toString(j), map.get(Integer.toString(j))); 42 | } 43 | } 44 | 45 | Assert.assertEquals(100, map.size()); 46 | Assert.assertFalse(map.isEmpty()); 47 | 48 | for (int i = 0; i < 100; i++) { 49 | Assert.assertEquals(Integer.toString(i), map.remove(Integer.toString(i))); 50 | 51 | for (int j = i + 1; j < 100; j++) { 52 | Assert.assertEquals(Integer.toString(j), map.get(Integer.toString(j))); 53 | } 54 | } 55 | 56 | Assert.assertTrue(map.isEmpty()); 57 | } 58 | 59 | @Test 60 | public void putAllClearTest() { 61 | Map map = new OffHeapHashMap<>(new UnlimitedPageSource(new OffHeapBufferSource()), new SerializableStorageEngine(getPointerSize(), new UnlimitedPageSource(new OffHeapBufferSource()), 1)); 62 | 63 | map.putAll(Collections.singletonMap("1", "1")); 64 | 65 | Assert.assertEquals(1, map.size()); 66 | Assert.assertFalse(map.isEmpty()); 67 | Assert.assertEquals(Collections.singletonMap("1", "1"), map); 68 | 69 | map.clear(); 70 | 71 | Assert.assertEquals(0, map.size()); 72 | Assert.assertTrue(map.isEmpty()); 73 | Assert.assertEquals(Collections.emptyMap(), map); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/test/java/org/terracotta/offheapstore/ReadWriteLockedOffHeapHashMapIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore; 18 | 19 | import org.terracotta.offheapstore.ReadWriteLockedOffHeapHashMap; 20 | import java.util.concurrent.ConcurrentMap; 21 | 22 | import org.terracotta.offheapstore.buffersource.OffHeapBufferSource; 23 | import org.terracotta.offheapstore.paging.PageSource; 24 | import org.terracotta.offheapstore.paging.UnlimitedPageSource; 25 | import org.terracotta.offheapstore.storage.IntegerStorageEngine; 26 | import org.terracotta.offheapstore.storage.OffHeapBufferHalfStorageEngine; 27 | import org.terracotta.offheapstore.storage.SplitStorageEngine; 28 | import org.terracotta.offheapstore.storage.portability.ByteArrayPortability; 29 | import org.terracotta.offheapstore.util.Generator; 30 | import static org.terracotta.offheapstore.util.Generator.BAD_GENERATOR; 31 | import static org.terracotta.offheapstore.util.Generator.GOOD_GENERATOR; 32 | import org.terracotta.offheapstore.util.Generator.SpecialInteger; 33 | import org.terracotta.offheapstore.util.ParallelParameterized; 34 | import java.util.Arrays; 35 | import java.util.Collection; 36 | import static org.hamcrest.core.Is.is; 37 | import static org.junit.Assume.assumeThat; 38 | import org.junit.runner.RunWith; 39 | 40 | @RunWith(ParallelParameterized.class) 41 | public class ReadWriteLockedOffHeapHashMapIT extends AbstractConcurrentOffHeapMapIT { 42 | 43 | @ParallelParameterized.Parameters(name = "generator={0}") 44 | public static Collection data() { 45 | return Arrays.asList(new Object[] {GOOD_GENERATOR}, new Object[] {BAD_GENERATOR}); 46 | } 47 | 48 | public ReadWriteLockedOffHeapHashMapIT(Generator generator) { 49 | super(generator); 50 | } 51 | 52 | @Override 53 | protected ConcurrentMap createMap(Generator generator) { 54 | return new ReadWriteLockedOffHeapHashMap<>(new UnlimitedPageSource(new OffHeapBufferSource()), generator.engine(), 1); 55 | } 56 | 57 | @Override 58 | protected ConcurrentMap createOffHeapBufferMap(PageSource source) { 59 | assumeThat(generator, is(GOOD_GENERATOR)); 60 | return new ReadWriteLockedOffHeapHashMap<>(source, new SplitStorageEngine<>(new IntegerStorageEngine(), new OffHeapBufferHalfStorageEngine<>(source, 1024, ByteArrayPortability.INSTANCE))); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/test/java/org/terracotta/offheapstore/TimeoutTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2017-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore; 18 | 19 | import org.junit.Test; 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | import org.terracotta.offheapstore.buffersource.OffHeapBufferSource; 23 | import org.terracotta.offheapstore.paging.UpfrontAllocatingPageSource; 24 | 25 | import java.util.concurrent.ExecutionException; 26 | import java.util.concurrent.ExecutorService; 27 | import java.util.concurrent.Executors; 28 | import java.util.concurrent.Future; 29 | 30 | /** 31 | * @author Henri Tremblay 32 | */ 33 | public class TimeoutTest { 34 | 35 | private static final Logger LOGGER = LoggerFactory.getLogger(TimeoutTest.class); 36 | 37 | @Test 38 | public void test() throws ExecutionException { 39 | ExecutorService service = Executors.newSingleThreadExecutor(); 40 | Future future = service.submit(() -> { 41 | try { 42 | Thread.sleep(2000); 43 | } catch (InterruptedException e) { 44 | 45 | } 46 | }); 47 | while (true) { 48 | try { 49 | future.get(); 50 | break; 51 | } catch (InterruptedException e) { 52 | Thread.currentThread().interrupt(); 53 | } 54 | } 55 | } 56 | 57 | public static void main(String[] args) { 58 | long toAllocate = 2L * 1024 * 1024 * 1024; 59 | long allocated = 1024 * 1024 * 1024; 60 | int maxChunk = 1024 * 1024 * 1024; 61 | System.out.println(toAllocate); 62 | System.out.println((int) toAllocate); 63 | System.out.println((int)toAllocate / maxChunk + 1); 64 | System.out.println((int)(toAllocate / maxChunk + 1)); 65 | System.out.println((100 * allocated) / toAllocate); 66 | if(args.length != 1) { 67 | System.err.println("Usage: TimeoutTest size_to_allocate_in_gb"); 68 | System.exit(1); 69 | return; 70 | } 71 | 72 | long size = Long.parseLong(args[0]); 73 | long start = System.currentTimeMillis(); 74 | 75 | OffHeapBufferSource source = new OffHeapBufferSource(); 76 | UpfrontAllocatingPageSource pageSource = new UpfrontAllocatingPageSource(source, size * 1024 * 1024 * 1024, 1024 * 1024 * 1024); 77 | 78 | long end = System.currentTimeMillis(); 79 | 80 | System.out.println(pageSource.getAllocatedSize()); 81 | 82 | System.out.println("Elapsed: " + (end - start)); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/ReadWriteLockedOffHeapClockCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore; 18 | 19 | import java.util.concurrent.locks.Lock; 20 | import java.util.concurrent.locks.ReentrantReadWriteLock; 21 | 22 | import org.terracotta.offheapstore.paging.PageSource; 23 | import org.terracotta.offheapstore.storage.StorageEngine; 24 | 25 | /** 26 | * A concurrent-read, exclusive-write off-heap clock cache. 27 | *

28 | * This cache uses one of the unused bits in the off-heap entry's status value to 29 | * store the clock data. This clock data is racily to updated during read 30 | * operations. Since clock eviction data resides in the hash-map's table, it is 31 | * correctly copied across during table resize operations. 32 | *

33 | * The cache uses a regular {@code ReentrantReadWriteLock} to provide read/write 34 | * exclusion/sharing properties. 35 | * 36 | * @param the type of keys maintained by this map 37 | * @param the type of mapped values 38 | * 39 | * @author Chris Dennis 40 | */ 41 | public class ReadWriteLockedOffHeapClockCache extends AbstractOffHeapClockCache { 42 | 43 | private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(true); 44 | 45 | public ReadWriteLockedOffHeapClockCache(PageSource source, StorageEngine storageEngine) { 46 | super(source, storageEngine); 47 | } 48 | 49 | public ReadWriteLockedOffHeapClockCache(PageSource source, boolean tableAllocationsSteal, StorageEngine storageEngine) { 50 | super(source, tableAllocationsSteal, storageEngine); 51 | } 52 | 53 | public ReadWriteLockedOffHeapClockCache(PageSource source, StorageEngine storageEngine, int tableSize) { 54 | super(source, storageEngine, tableSize); 55 | } 56 | 57 | public ReadWriteLockedOffHeapClockCache(PageSource source, boolean tableAllocationsSteal, StorageEngine storageEngine, int tableSize) { 58 | super(source, tableAllocationsSteal, storageEngine, tableSize); 59 | } 60 | 61 | @Override 62 | public Lock readLock() { 63 | return lock.readLock(); 64 | } 65 | 66 | @Override 67 | public Lock writeLock() { 68 | return lock.writeLock(); 69 | } 70 | 71 | @Override 72 | public ReentrantReadWriteLock getLock() { 73 | return lock; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/test/java/org/terracotta/offheapstore/paging/OffHeapStorageAreaLimitIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore.paging; 18 | 19 | import org.terracotta.offheapstore.paging.OffHeapStorageArea; 20 | import org.terracotta.offheapstore.disk.paging.MappedPageSource; 21 | import org.terracotta.offheapstore.util.PointerSizeParameterizedTest; 22 | import static org.terracotta.offheapstore.util.MemoryUnit.MEGABYTES; 23 | import java.io.File; 24 | import java.io.IOException; 25 | import org.junit.Ignore; 26 | import org.junit.Test; 27 | 28 | /** 29 | * 30 | * @author Chris Dennis 31 | */ 32 | @Ignore 33 | public class OffHeapStorageAreaLimitIT extends PointerSizeParameterizedTest { 34 | 35 | @Test 36 | public void testFixedPageSizes() throws IOException { 37 | File temp = new File("target/OffHeapStorageAreaLimitTest.temp"); 38 | OffHeapStorageArea storage = new OffHeapStorageArea(getPointerSize(), null, new MappedPageSource(temp), MEGABYTES.toBytes(1), false, false); 39 | try { 40 | while (true) { 41 | if (storage.allocate(MEGABYTES.toBytes(1)) < 0) { 42 | System.err.println(storage); 43 | break; 44 | } 45 | } 46 | } finally { 47 | storage.destroy(); 48 | } 49 | } 50 | 51 | @Test 52 | public void testVariablePageSizes() throws IOException { 53 | File temp = new File("target/OffHeapStorageAreaLimitTest.temp"); 54 | OffHeapStorageArea storage = new OffHeapStorageArea(getPointerSize(), null, new MappedPageSource(temp), 1, Integer.MAX_VALUE,false, false); 55 | try { 56 | while (true) { 57 | if (storage.allocate(MEGABYTES.toBytes(1)) < 0) { 58 | System.err.println(storage); 59 | break; 60 | } 61 | } 62 | } finally { 63 | storage.destroy(); 64 | } 65 | } 66 | 67 | @Test 68 | public void testCappedVariablePageSizes() throws IOException { 69 | File temp = new File("target/OffHeapStorageAreaLimitTest.temp"); 70 | OffHeapStorageArea storage = new OffHeapStorageArea(getPointerSize(), null, new MappedPageSource(temp), 1, MEGABYTES.toBytes(8),false, false); 71 | try { 72 | while (true) { 73 | if (storage.allocate(MEGABYTES.toBytes(1)) < 0) { 74 | System.err.println(storage); 75 | break; 76 | } 77 | } 78 | } finally { 79 | storage.destroy(); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/test/java/com/terracottatech/offheapstore/storage/restartable/partial/MinimalCacheRestartabilityIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.terracottatech.offheapstore.storage.restartable.partial; 18 | 19 | import java.nio.ByteBuffer; 20 | import java.util.Map; 21 | 22 | import com.terracottatech.frs.RestartStore; 23 | import com.terracottatech.frs.object.RegisterableObjectManager; 24 | import org.terracotta.offheapstore.ReadWriteLockedOffHeapClockCache; 25 | import org.terracotta.offheapstore.buffersource.OffHeapBufferSource; 26 | import org.terracotta.offheapstore.paging.PageSource; 27 | import org.terracotta.offheapstore.paging.UnlimitedPageSource; 28 | import org.terracotta.offheapstore.paging.UpfrontAllocatingPageSource; 29 | import org.terracotta.offheapstore.storage.portability.Portability; 30 | import com.terracottatech.offheapstore.storage.restartable.AbstractRestartabilityCacheIT; 31 | import com.terracottatech.offheapstore.storage.restartable.OffHeapObjectManagerStripe; 32 | import org.terracotta.offheapstore.util.MemoryUnit; 33 | 34 | public class MinimalCacheRestartabilityIT extends AbstractRestartabilityCacheIT { 35 | 36 | @Override 37 | protected Map createRestartableMap(long size, MemoryUnit unit, ByteBuffer id, 38 | RestartStore persistence, 39 | RegisterableObjectManager objectMgr, 40 | Portability keyPortability, 41 | Portability valuePortability, 42 | boolean synchronous) { 43 | PageSource source = new UpfrontAllocatingPageSource(new OffHeapBufferSource(), unit.toBytes(size), MemoryUnit.MEGABYTES.toBytes(1)); 44 | RestartableMinimalStorageEngine storageEngine = new RestartableMinimalStorageEngine(id, persistence, synchronous, getPointerSize(), source, MemoryUnit.KILOBYTES.toBytes(1), keyPortability, valuePortability, 0.75f); 45 | ReadWriteLockedOffHeapClockCache map = new ReadWriteLockedOffHeapClockCache(new UnlimitedPageSource(new OffHeapBufferSource()), storageEngine); 46 | objectMgr.registerObject(new OffHeapObjectManagerStripe(id, map)); 47 | return map; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/com/terracottatech/offheapstore/storage/restartable/partial/PartialCacheRestartabilityIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.terracottatech.offheapstore.storage.restartable.partial; 18 | 19 | import java.nio.ByteBuffer; 20 | import java.util.Map; 21 | 22 | import com.terracottatech.frs.RestartStore; 23 | import com.terracottatech.frs.object.RegisterableObjectManager; 24 | import org.terracotta.offheapstore.ReadWriteLockedOffHeapClockCache; 25 | import org.terracotta.offheapstore.buffersource.OffHeapBufferSource; 26 | import org.terracotta.offheapstore.paging.PageSource; 27 | import org.terracotta.offheapstore.paging.UnlimitedPageSource; 28 | import org.terracotta.offheapstore.paging.UpfrontAllocatingPageSource; 29 | import org.terracotta.offheapstore.storage.portability.Portability; 30 | import com.terracottatech.offheapstore.storage.restartable.AbstractRestartabilityCacheIT; 31 | import com.terracottatech.offheapstore.storage.restartable.OffHeapObjectManagerStripe; 32 | import org.terracotta.offheapstore.util.MemoryUnit; 33 | 34 | public class PartialCacheRestartabilityIT extends AbstractRestartabilityCacheIT { 35 | 36 | @Override 37 | protected Map createRestartableMap(long size, MemoryUnit unit, ByteBuffer id, 38 | RestartStore persistence, 39 | RegisterableObjectManager objectMgr, 40 | Portability keyPortability, 41 | Portability valuePortability, 42 | boolean synchronous) { 43 | PageSource source = new UpfrontAllocatingPageSource(new OffHeapBufferSource(), unit.toBytes(size), MemoryUnit.MEGABYTES.toBytes(1)); 44 | RestartableMinimalStorageEngine storageEngine = new RestartablePartialStorageEngine(id, persistence, synchronous, getPointerSize(), source, MemoryUnit.KILOBYTES.toBytes(1), keyPortability, valuePortability, 0.75f); 45 | ReadWriteLockedOffHeapClockCache map = new ReadWriteLockedOffHeapClockCache(new UnlimitedPageSource(new OffHeapBufferSource()), storageEngine); 46 | objectMgr.registerObject(new OffHeapObjectManagerStripe(id, map)); 47 | return map; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/test/java/com/terracottatech/offheapstore/storage/restartable/partial/KeysOnlyCacheRestartabilityIT.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2014-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package com.terracottatech.offheapstore.storage.restartable.partial; 18 | 19 | import java.nio.ByteBuffer; 20 | import java.util.Map; 21 | 22 | import com.terracottatech.frs.RestartStore; 23 | import com.terracottatech.frs.object.RegisterableObjectManager; 24 | import org.terracotta.offheapstore.ReadWriteLockedOffHeapClockCache; 25 | import org.terracotta.offheapstore.buffersource.OffHeapBufferSource; 26 | import org.terracotta.offheapstore.paging.PageSource; 27 | import org.terracotta.offheapstore.paging.UnlimitedPageSource; 28 | import org.terracotta.offheapstore.paging.UpfrontAllocatingPageSource; 29 | import org.terracotta.offheapstore.storage.portability.Portability; 30 | import com.terracottatech.offheapstore.storage.restartable.AbstractRestartabilityCacheIT; 31 | import com.terracottatech.offheapstore.storage.restartable.OffHeapObjectManagerStripe; 32 | import org.terracotta.offheapstore.util.MemoryUnit; 33 | 34 | public class KeysOnlyCacheRestartabilityIT extends AbstractRestartabilityCacheIT { 35 | 36 | @Override 37 | protected Map createRestartableMap(long size, MemoryUnit unit, ByteBuffer id, 38 | RestartStore persistence, 39 | RegisterableObjectManager objectMgr, 40 | Portability keyPortability, 41 | Portability valuePortability, 42 | boolean synchronous) { 43 | PageSource source = new UpfrontAllocatingPageSource(new OffHeapBufferSource(), unit.toBytes(size), MemoryUnit.MEGABYTES.toBytes(1)); 44 | RestartableMinimalStorageEngine storageEngine = new RestartableKeysOnlyStorageEngine(id, persistence, synchronous, getPointerSize(), source, MemoryUnit.KILOBYTES.toBytes(1), keyPortability, valuePortability, 0.75f); 45 | ReadWriteLockedOffHeapClockCache map = new ReadWriteLockedOffHeapClockCache(new UnlimitedPageSource(new OffHeapBufferSource()), storageEngine); 46 | objectMgr.registerObject(new OffHeapObjectManagerStripe(id, map)); 47 | return map; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/org/terracotta/offheapstore/WriteLockedOffHeapClockCache.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-2023 Terracotta, Inc., a Software AG company. 3 | * Copyright IBM Corp. 2024, 2025 4 | * 5 | * Licensed under the Apache License, Version 2.0 (the "License"); 6 | * you may not use this file except in compliance with the License. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | package org.terracotta.offheapstore; 18 | 19 | import java.util.concurrent.locks.Lock; 20 | import java.util.concurrent.locks.ReentrantLock; 21 | import java.util.concurrent.locks.ReentrantReadWriteLock; 22 | 23 | import org.terracotta.offheapstore.paging.PageSource; 24 | import org.terracotta.offheapstore.storage.StorageEngine; 25 | 26 | /** 27 | * An exclusive-read/write off-heap clock cache. 28 | *

29 | * This cache uses one of the unused bits in the off-heap entry's status value to 30 | * store the clock data. This clock data is safe to update during read 31 | * operations since the cache provides exclusive-read/write characteristics. 32 | * Since clock eviction data resides in the hash-map's table, it is correctly 33 | * copied across during table resize operations. 34 | *

35 | * The cache uses a regular {@code ReentrantLock} to provide exclusive read and 36 | * write operations. 37 | * 38 | * @param the type of keys maintained by this map 39 | * @param the type of mapped values 40 | * 41 | * @author Chris Dennis 42 | */ 43 | public class WriteLockedOffHeapClockCache extends AbstractOffHeapClockCache { 44 | 45 | private final Lock lock = new ReentrantLock(); 46 | 47 | public WriteLockedOffHeapClockCache(PageSource source, StorageEngine storageEngine) { 48 | super(source, storageEngine); 49 | } 50 | 51 | public WriteLockedOffHeapClockCache(PageSource source, boolean tableAllocationsSteal, StorageEngine storageEngine) { 52 | super(source, tableAllocationsSteal, storageEngine); 53 | } 54 | 55 | public WriteLockedOffHeapClockCache(PageSource source, StorageEngine storageEngine, int tableSize) { 56 | super(source, storageEngine, tableSize); 57 | } 58 | 59 | public WriteLockedOffHeapClockCache(PageSource source, boolean tableAllocationsSteal, StorageEngine storageEngine, int tableSize) { 60 | super(source, tableAllocationsSteal, storageEngine, tableSize); 61 | } 62 | 63 | @Override 64 | public Lock readLock() { 65 | return lock; 66 | } 67 | 68 | @Override 69 | public Lock writeLock() { 70 | return lock; 71 | } 72 | 73 | @Override 74 | public ReentrantReadWriteLock getLock() { 75 | throw new UnsupportedOperationException(); 76 | } 77 | } 78 | --------------------------------------------------------------------------------