-
Notifications
You must be signed in to change notification settings - Fork 48
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Issue #50 Implement offheap-resource provider
- Loading branch information
1 parent
f701b1e
commit c91ddb8
Showing
6 changed files
with
437 additions
and
10 deletions.
There are no files selected for viewing
58 changes: 58 additions & 0 deletions
58
offheap-resource/src/main/java/org/terracotta/offheapresource/OffHeapResource.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
/* | ||
* The contents of this file are subject to the Terracotta Public License Version | ||
* 2.0 (the "License"); You may not use this file except in compliance with the | ||
* License. You may obtain a copy of the License at | ||
* | ||
* http://terracotta.org/legal/terracotta-public-license. | ||
* | ||
* Software distributed under the License is distributed on an "AS IS" basis, | ||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for | ||
* the specific language governing rights and limitations under the License. | ||
* | ||
* The Covered Software is OffHeap Resource. | ||
* | ||
* The Initial Developer of the Covered Software is | ||
* Terracotta, Inc., a Software AG company | ||
*/ | ||
|
||
package org.terracotta.offheapresource; | ||
|
||
import java.util.concurrent.atomic.AtomicLong; | ||
|
||
public class OffHeapResource { | ||
|
||
private final AtomicLong remaining; | ||
|
||
OffHeapResource(long size) { | ||
if (size < 0) { | ||
throw new IllegalArgumentException("Resource size cannot be negative"); | ||
} else { | ||
this.remaining = new AtomicLong(size); | ||
} | ||
} | ||
|
||
public boolean allocate(long size) { | ||
if (size < 0) { | ||
throw new IllegalArgumentException("Allocation size cannot be negative"); | ||
} else { | ||
for (long current = remaining.get(); current >= size; current = remaining.get()) { | ||
if (remaining.compareAndSet(current, current - size)) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
} | ||
|
||
public void free(long size) { | ||
if (size < 0) { | ||
throw new IllegalArgumentException("Freed size cannot be negative"); | ||
} else { | ||
remaining.addAndGet(size); | ||
} | ||
} | ||
|
||
public long available() { | ||
return remaining.get(); | ||
} | ||
} |
56 changes: 56 additions & 0 deletions
56
offheap-resource/src/main/java/org/terracotta/offheapresource/OffHeapResourceIdentifier.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
/* | ||
* The contents of this file are subject to the Terracotta Public License Version | ||
* 2.0 (the "License"); You may not use this file except in compliance with the | ||
* License. You may obtain a copy of the License at | ||
* | ||
* http://terracotta.org/legal/terracotta-public-license. | ||
* | ||
* Software distributed under the License is distributed on an "AS IS" basis, | ||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for | ||
* the specific language governing rights and limitations under the License. | ||
* | ||
* The Covered Software is OffHeap Resource. | ||
* | ||
* The Initial Developer of the Covered Software is | ||
* Terracotta, Inc., a Software AG company | ||
*/ | ||
|
||
package org.terracotta.offheapresource; | ||
|
||
import org.terracotta.entity.ServiceConfiguration; | ||
|
||
/** | ||
* | ||
* @author cdennis | ||
*/ | ||
public final class OffHeapResourceIdentifier implements ServiceConfiguration<OffHeapResource> { | ||
|
||
private final String name; | ||
|
||
public static OffHeapResourceIdentifier identifier(String name) { | ||
return new OffHeapResourceIdentifier(name); | ||
} | ||
|
||
private OffHeapResourceIdentifier(String name) { | ||
if (name == null) { | ||
throw new NullPointerException("Name cannot be null"); | ||
} else { | ||
this.name = name; | ||
} | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return name.hashCode(); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object obj) { | ||
return (obj instanceof OffHeapResourceIdentifier) && name.equals(((OffHeapResourceIdentifier) obj).name); | ||
} | ||
|
||
@Override | ||
public Class<OffHeapResource> getServiceType() { | ||
return OffHeapResource.class; | ||
} | ||
} |
70 changes: 60 additions & 10 deletions
70
offheap-resource/src/main/java/org/terracotta/offheapresource/OffHeapResourcesProvider.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,39 +1,89 @@ | ||
/* | ||
* To change this license header, choose License Headers in Project Properties. | ||
* To change this template file, choose Tools | Templates | ||
* and open the template in the editor. | ||
* The contents of this file are subject to the Terracotta Public License Version | ||
* 2.0 (the "License"); You may not use this file except in compliance with the | ||
* License. You may obtain a copy of the License at | ||
* | ||
* http://terracotta.org/legal/terracotta-public-license. | ||
* | ||
* Software distributed under the License is distributed on an "AS IS" basis, | ||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for | ||
* the specific language governing rights and limitations under the License. | ||
* | ||
* The Covered Software is OffHeap Resource. | ||
* | ||
* The Initial Developer of the Covered Software is | ||
* Terracotta, Inc., a Software AG company | ||
*/ | ||
|
||
package org.terracotta.offheapresource; | ||
|
||
import java.io.IOException; | ||
import java.math.BigInteger; | ||
import java.util.Collection; | ||
import java.util.Collections; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
import org.terracotta.entity.ServiceConfiguration; | ||
import org.terracotta.entity.ServiceProvider; | ||
import org.terracotta.entity.ServiceProviderConfiguration; | ||
import org.terracotta.offheapresource.config.MemoryUnit; | ||
import org.terracotta.offheapresource.config.ResourceType; | ||
|
||
/** | ||
* | ||
* @author cdennis | ||
*/ | ||
class OffHeapResourcesProvider implements ServiceProvider { | ||
|
||
private final Map<OffHeapResourceIdentifier, OffHeapResource> resources = new HashMap<OffHeapResourceIdentifier, OffHeapResource>(); | ||
|
||
@Override | ||
public boolean initialize(ServiceProviderConfiguration configuration) { | ||
throw new UnsupportedOperationException(); | ||
public synchronized boolean initialize(ServiceProviderConfiguration unknownConfig) { | ||
if (unknownConfig instanceof OffHeapResourcesConfiguration) { | ||
OffHeapResourcesConfiguration configuration = (OffHeapResourcesConfiguration) unknownConfig; | ||
if (resources.isEmpty()) { | ||
for (ResourceType r : configuration.getResources()) { | ||
resources.put(OffHeapResourceIdentifier.identifier(r.getName()), new OffHeapResource(convert(r.getValue(), r.getUnit()).longValueExact())); | ||
} | ||
return true; | ||
} else { | ||
throw new IllegalStateException("Resources already initialized"); | ||
} | ||
} else { | ||
return false; | ||
} | ||
} | ||
|
||
@Override | ||
public <T> T getService(long consumerID, ServiceConfiguration<T> configuration) { | ||
throw new UnsupportedOperationException(); | ||
public <T> T getService(long consumerID, ServiceConfiguration<T> unknownConfiguration) { | ||
if (unknownConfiguration instanceof OffHeapResourceIdentifier) { | ||
OffHeapResourceIdentifier identifier = (OffHeapResourceIdentifier) unknownConfiguration; | ||
return (T) identifier.getServiceType().cast(resources.get(identifier)); | ||
} else { | ||
throw new IllegalArgumentException("Unexpected configuration type " + unknownConfiguration.getClass()); | ||
} | ||
} | ||
|
||
@Override | ||
public Collection<Class<?>> getProvidedServiceTypes() { | ||
throw new UnsupportedOperationException(); | ||
return Collections.<Class<?>>singleton(OffHeapResource.class); | ||
} | ||
|
||
@Override | ||
public void close() throws IOException { | ||
throw new UnsupportedOperationException(); | ||
public void close() { | ||
resources.clear(); | ||
} | ||
|
||
private static BigInteger convert(BigInteger value, MemoryUnit unit) { | ||
switch (unit) { | ||
case B: return value.shiftLeft(0); | ||
case K_B: return value.shiftLeft(10); | ||
case MB: return value.shiftLeft(20); | ||
case GB: return value.shiftLeft(30); | ||
case TB: return value.shiftLeft(40); | ||
case PB: return value.shiftLeft(50); | ||
} | ||
throw new IllegalArgumentException("Unknown unit " + unit); | ||
} | ||
} |
53 changes: 53 additions & 0 deletions
53
...-resource/src/test/java/org/terracotta/offheapresource/OffHeapResourceIdentifierTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
/* | ||
* The contents of this file are subject to the Terracotta Public License Version | ||
* 2.0 (the "License"); You may not use this file except in compliance with the | ||
* License. You may obtain a copy of the License at | ||
* | ||
* http://terracotta.org/legal/terracotta-public-license. | ||
* | ||
* Software distributed under the License is distributed on an "AS IS" basis, | ||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for | ||
* the specific language governing rights and limitations under the License. | ||
* | ||
* The Covered Software is OffHeap Resource. | ||
* | ||
* The Initial Developer of the Covered Software is | ||
* Terracotta, Inc., a Software AG company | ||
*/ | ||
package org.terracotta.offheapresource; | ||
|
||
import static org.hamcrest.core.Is.is; | ||
import org.junit.Test; | ||
|
||
import static org.hamcrest.core.IsEqual.equalTo; | ||
import static org.junit.Assert.assertThat; | ||
import static org.junit.Assert.fail; | ||
|
||
public class OffHeapResourceIdentifierTest { | ||
|
||
@Test | ||
public void testNullName() { | ||
try { | ||
OffHeapResourceIdentifier.identifier(null); | ||
fail("Expected NullPointerException"); | ||
} catch (NullPointerException e) { | ||
//expected | ||
} | ||
} | ||
|
||
@Test | ||
public void testServiceType() { | ||
assertThat(OffHeapResourceIdentifier.identifier("foo").getServiceType(), equalTo(OffHeapResource.class)); | ||
} | ||
|
||
@Test | ||
public void testEquals() { | ||
assertThat(OffHeapResourceIdentifier.identifier("foo").equals(OffHeapResourceIdentifier.identifier("foo")), is(true)); | ||
assertThat(OffHeapResourceIdentifier.identifier("foo").equals(OffHeapResourceIdentifier.identifier("bar")), is(false)); | ||
} | ||
|
||
@Test | ||
public void testHashcode() { | ||
assertThat(OffHeapResourceIdentifier.identifier("foo").hashCode(), is(OffHeapResourceIdentifier.identifier("foo").hashCode())); | ||
} | ||
} |
91 changes: 91 additions & 0 deletions
91
offheap-resource/src/test/java/org/terracotta/offheapresource/OffHeapResourceTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
/* | ||
* The contents of this file are subject to the Terracotta Public License Version | ||
* 2.0 (the "License"); You may not use this file except in compliance with the | ||
* License. You may obtain a copy of the License at | ||
* | ||
* http://terracotta.org/legal/terracotta-public-license. | ||
* | ||
* Software distributed under the License is distributed on an "AS IS" basis, | ||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for | ||
* the specific language governing rights and limitations under the License. | ||
* | ||
* The Covered Software is OffHeap Resource. | ||
* | ||
* The Initial Developer of the Covered Software is | ||
* Terracotta, Inc., a Software AG company | ||
*/ | ||
|
||
package org.terracotta.offheapresource; | ||
|
||
import static org.hamcrest.core.Is.is; | ||
import static org.junit.Assert.assertThat; | ||
import static org.junit.Assert.fail; | ||
import org.junit.Test; | ||
|
||
public class OffHeapResourceTest { | ||
|
||
@Test | ||
public void testNegativeResourceSize() { | ||
try { | ||
new OffHeapResource(-1); | ||
fail("Expected IllegalArgumentException"); | ||
} catch (IllegalArgumentException e) { | ||
//expected; | ||
} | ||
} | ||
|
||
@Test | ||
public void testZeroSizeResourceIsUseless() { | ||
OffHeapResource ohr = new OffHeapResource(0); | ||
assertThat(ohr.allocate(1), is(false)); | ||
assertThat(ohr.available(), is(0L)); | ||
} | ||
|
||
@Test | ||
public void testAllocationReducesSize() { | ||
OffHeapResource ohr = new OffHeapResource(20); | ||
assertThat(ohr.available(), is(20L)); | ||
assertThat(ohr.allocate(10), is(true)); | ||
assertThat(ohr.available(), is(10L)); | ||
} | ||
|
||
@Test | ||
public void testNegativeAllocationFails() { | ||
OffHeapResource ohr = new OffHeapResource(20); | ||
try { | ||
ohr.allocate(-1); | ||
fail("Expected IllegalArgumentException"); | ||
} catch (IllegalArgumentException e) { | ||
//expected | ||
} | ||
} | ||
|
||
@Test | ||
public void testAllocationWhenExhaustedFails() { | ||
OffHeapResource ohr = new OffHeapResource(20); | ||
ohr.allocate(20); | ||
assertThat(ohr.allocate(1), is(false)); | ||
assertThat(ohr.available(), is(0L)); | ||
} | ||
|
||
@Test | ||
public void testFreeIncreasesSize() { | ||
OffHeapResource ohr = new OffHeapResource(20); | ||
ohr.allocate(20); | ||
assertThat(ohr.available(), is(0L)); | ||
ohr.free(10); | ||
assertThat(ohr.available(), is(10L)); | ||
} | ||
|
||
@Test | ||
public void testNegativeFreeFails() { | ||
OffHeapResource ohr = new OffHeapResource(20); | ||
ohr.allocate(10); | ||
try { | ||
ohr.free(-10); | ||
fail("Expected IllegalArgumentException"); | ||
} catch (IllegalArgumentException e) { | ||
//expected | ||
} | ||
} | ||
} |
Oops, something went wrong.