Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/main/java/com/teragrep/buf_01/buffer/lease/Lease.java
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,7 @@ public interface Lease<T> extends AutoCloseable, Stubable {
* @return slice of the lease, registered as a sublease.
*/
public abstract Lease<T> sliceAt(long offset);

@Override
public abstract void close();
}
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ public boolean isStub() {
}

@Override
public void close() throws Exception {
public void close() {
origin.close();
}

Expand Down
20 changes: 19 additions & 1 deletion src/main/java/com/teragrep/buf_01/buffer/pool/LeaseMultiGet.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
*/
package com.teragrep.buf_01.buffer.pool;

import com.teragrep.buf_01.buffer.lease.MemorySegmentLease;
import com.teragrep.buf_01.buffer.lease.OpenableLease;
import com.teragrep.poj_01.pool.Pool;

Expand Down Expand Up @@ -89,9 +90,12 @@ public LeaseMultiGet(final Pool<OpenableLease<MemorySegment>> leasePool) {
}

@Override
public List<OpenableLease<MemorySegment>> get(final long bytesCount) {
public List<OpenableLease<MemorySegment>> getAsList(final long bytesCount) {
// We don't know how many leases we will get in advance
// Need to use a list and expand if necessary
long currentSize = 0;
final List<OpenableLease<MemorySegment>> leases = new ArrayList<>();

while (currentSize < bytesCount) {
final OpenableLease<MemorySegment> lease = leasePool.get();
if (lease.isStub()) {
Expand All @@ -100,9 +104,23 @@ public List<OpenableLease<MemorySegment>> get(final long bytesCount) {
leases.add(lease);
currentSize += lease.leasedObject().byteSize();
}

return leases;
}

@Override
public OpenableLease<MemorySegment>[] getAsArray(final long bytesCount) {
final List<OpenableLease<MemorySegment>> leases = getAsList(bytesCount);
final int size = leases.size();
final OpenableLease<MemorySegment>[] rv = new MemorySegmentLease[size];

for (int i = 0; i < size; i++) {
rv[i] = leases.get(i);
}

return rv;
}

@Override
public boolean equals(final Object o) {
if (o == null || getClass() != o.getClass()) {
Expand Down
7 changes: 5 additions & 2 deletions src/main/java/com/teragrep/buf_01/buffer/pool/MultiGet.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,10 @@
*/
package com.teragrep.buf_01.buffer.pool;

// spotless:off

import java.util.List;

// spotless:off
/**
* @interface MultiGet
* @brief Provides an interface for getting multiples of the given type.
Expand All @@ -72,5 +73,7 @@
// spotless:on
public interface MultiGet<T> {

public abstract List<T> get(long count);
public abstract List<T> getAsList(final long count);

public abstract T[] getAsArray(final long count);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* Teragrep Buffer Library for Java
* Copyright (C) 2026 Suomen Kanuuna Oy
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*
* Additional permission under GNU Affero General Public License version 3
* section 7
*
* If you modify this Program, or any covered work, by linking or combining it
* with other code, such other code is not for that reason alone subject to any
* of the requirements of the GNU Affero GPL version 3 as long as this Program
* is the same Program as licensed from Suomen Kanuuna Oy without any additional
* modifications.
*
* Supplemented terms under GNU Affero General Public License version 3
* section 7
*
* Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified
* versions must be marked as "Modified version of" The Program.
*
* Names of the licensors and authors may not be used for publicity purposes.
*
* No rights are granted for use of trade names, trademarks, or service marks
* which are in The Program if any.
*
* Licensee must indemnify licensors and authors for any liability that these
* contractual assumptions impose on licensors and authors.
*
* To the extent this program is licensed as part of the Commercial versions of
* Teragrep, the applicable Commercial License may apply to this file if you as
* a licensee so wish it.
*/
package com.teragrep.buf_01.buffer.pool;

import com.teragrep.buf_01.buffer.lease.OpenableLease;
import com.teragrep.buf_01.buffer.lease.TrackedLease;
import com.teragrep.buf_01.buffer.lease.TrackedMemorySegmentLease;

import java.lang.foreign.MemorySegment;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public final class TrackedLeaseMultiGet implements MultiGet<TrackedLease<MemorySegment>> {

private final MultiGet<OpenableLease<MemorySegment>> origin;

public TrackedLeaseMultiGet(final MultiGet<OpenableLease<MemorySegment>> origin) {
this.origin = origin;
}

@Override
public List<TrackedLease<MemorySegment>> getAsList(final long count) {
final List<OpenableLease<MemorySegment>> leases = origin.getAsList(count);
final List<TrackedLease<MemorySegment>> rv = new ArrayList<>(leases.size());

leases.forEach(lease -> {
rv.add(new TrackedMemorySegmentLease(lease));
});

return rv;
}

@Override
public TrackedLease<MemorySegment>[] getAsArray(final long count) {
final OpenableLease<MemorySegment>[] leases = origin.getAsArray(count);
final int len = leases.length;
final TrackedLease<MemorySegment>[] rv = new TrackedMemorySegmentLease[len];

for (int i = 0; i < len; i++) {
rv[i] = new TrackedMemorySegmentLease(leases[i]);
}

return rv;
}

@Override
public boolean equals(final Object o) {
if (o == null || getClass() != o.getClass()) {
return false;
}
final TrackedLeaseMultiGet that = (TrackedLeaseMultiGet) o;
return Objects.equals(origin, that.origin);
}

@Override
public int hashCode() {
return Objects.hashCode(origin);
}
}
40 changes: 28 additions & 12 deletions src/test/java/com/teragrep/buf_01/buffer/LeaseMultiGetTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@

import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.util.Arrays;
import java.util.List;

final class LeaseMultiGetTest {
Expand All @@ -71,10 +72,14 @@ void testTakeOneLease() {
new UnboundPool<>(new ArenaMemorySegmentLeaseSupplier(Arena.ofShared(), 5), new MemorySegmentLeaseStub())
);
final MultiGet<OpenableLease<MemorySegment>> multiGet = new LeaseMultiGet(pool);
final List<OpenableLease<MemorySegment>> leases = multiGet.get(5);
final OpenableLease<MemorySegment>[] leases = multiGet.getAsArray(5);
final List<OpenableLease<MemorySegment>> leasesList = multiGet.getAsList(5);

Assertions.assertEquals(1, leases.size());
Assertions.assertEquals(5, leases.getFirst().leasedObject().byteSize());
Assertions.assertEquals(1, leases.length);
Assertions.assertEquals(5, leases[0].leasedObject().byteSize());

Assertions.assertEquals(1, leasesList.size());
Assertions.assertEquals(5, leasesList.getFirst().leasedObject().byteSize());
}

@Test
Expand All @@ -84,11 +89,16 @@ void testTakeTwoLeases() {
new UnboundPool<>(new ArenaMemorySegmentLeaseSupplier(Arena.ofShared(), 3), new MemorySegmentLeaseStub())
);
final MultiGet<OpenableLease<MemorySegment>> multiGet = new LeaseMultiGet(pool);
final List<OpenableLease<MemorySegment>> leases = multiGet.get(5);
final OpenableLease<MemorySegment>[] leases = multiGet.getAsArray(5);
final List<OpenableLease<MemorySegment>> leasesList = multiGet.getAsList(5);

Assertions.assertEquals(2, leases.length);
Assertions.assertEquals(3, leases[0].leasedObject().byteSize());
Assertions.assertEquals(3, leases[leases.length - 1].leasedObject().byteSize());

Assertions.assertEquals(2, leases.size());
Assertions.assertEquals(3, leases.getFirst().leasedObject().byteSize());
Assertions.assertEquals(3, leases.getLast().leasedObject().byteSize());
Assertions.assertEquals(2, leasesList.size());
Assertions.assertEquals(3, leasesList.getFirst().leasedObject().byteSize());
Assertions.assertEquals(3, leasesList.getLast().leasedObject().byteSize());
}

@Test
Expand All @@ -98,10 +108,14 @@ void testTakeFourLeases() {
new UnboundPool<>(new ArenaMemorySegmentLeaseSupplier(Arena.ofShared(), 3), new MemorySegmentLeaseStub())
);
final MultiGet<OpenableLease<MemorySegment>> multiGet = new LeaseMultiGet(pool);
final List<OpenableLease<MemorySegment>> leases = multiGet.get(10);
final OpenableLease<MemorySegment>[] leases = multiGet.getAsArray(10);
final List<OpenableLease<MemorySegment>> leasesList = multiGet.getAsList(10);

Assertions.assertEquals(4, leases.length);
Assertions.assertEquals(4, Arrays.stream(leases).filter(l -> 3 == l.leasedObject().byteSize()).count());

Assertions.assertEquals(4, leases.size());
Assertions.assertEquals(4, leases.stream().filter(l -> 3 == l.leasedObject().byteSize()).count());
Assertions.assertEquals(4, leasesList.size());
Assertions.assertEquals(4, leasesList.stream().filter(l -> 3 == l.leasedObject().byteSize()).count());
}

@Test
Expand All @@ -111,9 +125,11 @@ void testTakeZeroLeases() {
new UnboundPool<>(new ArenaMemorySegmentLeaseSupplier(Arena.ofShared(), 3), new MemorySegmentLeaseStub())
);
final MultiGet<OpenableLease<MemorySegment>> multiGet = new LeaseMultiGet(pool);
final List<OpenableLease<MemorySegment>> leases = multiGet.get(0);
final OpenableLease<MemorySegment>[] leases = multiGet.getAsArray(0);
final List<OpenableLease<MemorySegment>> leasesList = multiGet.getAsList(0);

Assertions.assertEquals(0, leases.size());
Assertions.assertEquals(0, leases.length);
Assertions.assertEquals(0, leasesList.size());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* Teragrep Buffer Library for Java
* Copyright (C) 2026 Suomen Kanuuna Oy
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*
* Additional permission under GNU Affero General Public License version 3
* section 7
*
* If you modify this Program, or any covered work, by linking or combining it
* with other code, such other code is not for that reason alone subject to any
* of the requirements of the GNU Affero GPL version 3 as long as this Program
* is the same Program as licensed from Suomen Kanuuna Oy without any additional
* modifications.
*
* Supplemented terms under GNU Affero General Public License version 3
* section 7
*
* Origin of the software must be attributed to Suomen Kanuuna Oy. Any modified
* versions must be marked as "Modified version of" The Program.
*
* Names of the licensors and authors may not be used for publicity purposes.
*
* No rights are granted for use of trade names, trademarks, or service marks
* which are in The Program if any.
*
* Licensee must indemnify licensors and authors for any liability that these
* contractual assumptions impose on licensors and authors.
*
* To the extent this program is licensed as part of the Commercial versions of
* Teragrep, the applicable Commercial License may apply to this file if you as
* a licensee so wish it.
*/
package com.teragrep.buf_01.buffer;

import com.teragrep.buf_01.buffer.lease.MemorySegmentLeaseStub;
import com.teragrep.buf_01.buffer.lease.OpenableLease;
import com.teragrep.buf_01.buffer.lease.TrackedLease;
import com.teragrep.buf_01.buffer.lease.TrackedMemorySegmentLease;
import com.teragrep.buf_01.buffer.pool.LeaseMultiGet;
import com.teragrep.buf_01.buffer.pool.MultiGet;
import com.teragrep.buf_01.buffer.pool.OpeningPool;
import com.teragrep.buf_01.buffer.pool.TrackedLeaseMultiGet;
import com.teragrep.buf_01.buffer.supply.ArenaMemorySegmentLeaseSupplier;
import com.teragrep.poj_01.pool.Pool;
import com.teragrep.poj_01.pool.UnboundPool;
import nl.jqno.equalsverifier.EqualsVerifier;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import java.lang.foreign.Arena;
import java.lang.foreign.MemorySegment;
import java.util.List;

public final class TrackedLeaseMultiGetTest {

@Test
void testDecorating() {
final Pool<OpenableLease<MemorySegment>> pool = new OpeningPool(
new UnboundPool<>(new ArenaMemorySegmentLeaseSupplier(Arena.ofShared(), 5), new MemorySegmentLeaseStub())
);
final MultiGet<OpenableLease<MemorySegment>> multiGet = new LeaseMultiGet(pool);
final MultiGet<TrackedLease<MemorySegment>> trackedMultiGet = new TrackedLeaseMultiGet(multiGet);

final TrackedLease<MemorySegment>[] leases = trackedMultiGet.getAsArray(5);
final List<TrackedLease<MemorySegment>> leasesList = trackedMultiGet.getAsList(5);

Assertions.assertEquals(1, leases.length);
Assertions.assertEquals(5, leases[0].leasedObject().byteSize());
Assertions.assertEquals(TrackedMemorySegmentLease.class, leases[0].getClass());
Assertions.assertEquals(0L, leases[0].currentPosition());
Assertions.assertEquals(-1L, leases[0].currentLimit());

Assertions.assertEquals(1, leasesList.size());
Assertions.assertEquals(5, leasesList.getFirst().leasedObject().byteSize());
Assertions.assertEquals(TrackedMemorySegmentLease.class, leasesList.getFirst().getClass());
Assertions.assertEquals(0L, leasesList.getFirst().currentPosition());
Assertions.assertEquals(-1L, leasesList.getFirst().currentLimit());
}

@Test
void testEqualsContract() {
EqualsVerifier.forClass(TrackedLeaseMultiGet.class).verify();
}
}