CavalliumDBEngine/src/main/java/it/cavallium/dbengine/database/LLDelta.java

173 lines
4.1 KiB
Java
Raw Normal View History

2021-08-29 23:18:03 +02:00
package it.cavallium.dbengine.database;
2022-03-16 13:47:56 +01:00
import io.netty5.buffer.api.Buffer;
import io.netty5.buffer.api.Drop;
import io.netty5.buffer.api.Owned;
import io.netty5.buffer.api.Send;
import io.netty5.buffer.api.internal.ResourceSupport;
2021-08-29 23:18:03 +02:00
import java.util.StringJoiner;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
2021-08-29 23:18:03 +02:00
import org.jetbrains.annotations.Nullable;
2021-10-17 17:15:57 +02:00
public class LLDelta extends ResourceSupport<LLDelta, LLDelta> {
2021-10-01 19:17:33 +02:00
private static final Logger logger = LogManager.getLogger(LLDelta.class);
2021-10-01 19:17:33 +02:00
private static final Drop<LLDelta> DROP = new Drop<>() {
@Override
public void drop(LLDelta obj) {
try {
if (obj.previous != null && obj.previous.isAccessible()) {
2021-10-01 19:17:33 +02:00
obj.previous.close();
}
} catch (Throwable ex) {
logger.error("Failed to close previous", ex);
}
try {
if (obj.current != null && obj.current.isAccessible()) {
2021-10-01 19:17:33 +02:00
obj.current.close();
}
} catch (Throwable ex) {
logger.error("Failed to close current", ex);
}
try {
if (obj.onClose != null) {
obj.onClose.run();
}
} catch (Throwable ex) {
logger.error("Failed to close onDrop", ex);
}
}
@Override
public Drop<LLDelta> fork() {
return this;
}
@Override
public void attach(LLDelta obj) {
}
};
@Nullable
private Buffer previous;
2021-08-29 23:18:03 +02:00
@Nullable
2021-10-01 19:17:33 +02:00
private Buffer current;
2021-08-29 23:18:03 +02:00
@Nullable
2021-10-01 19:17:33 +02:00
private Runnable onClose;
2021-08-29 23:18:03 +02:00
private LLDelta(@Nullable Buffer previous, @Nullable Buffer current, @Nullable Runnable onClose) {
2021-10-01 19:17:33 +02:00
super(DROP);
2021-08-29 23:18:03 +02:00
assert isAllAccessible();
this.previous = previous != null ? previous.makeReadOnly() : null;
this.current = current != null ? current.makeReadOnly() : null;
2021-10-01 19:17:33 +02:00
this.onClose = onClose;
2021-08-29 23:18:03 +02:00
}
private boolean isAllAccessible() {
assert previous == null || previous.isAccessible();
assert current == null || current.isAccessible();
assert this.isAccessible();
assert this.isOwned();
return true;
}
public static LLDelta of(Buffer previous, Buffer current) {
2021-10-17 19:52:43 +02:00
assert (previous == null && current == null) || (previous != current);
return new LLDelta(previous, current, null);
2021-08-29 23:18:03 +02:00
}
public Send<Buffer> previous() {
ensureOwned();
return previous != null ? previous.copy().send() : null;
}
public Send<Buffer> current() {
ensureOwned();
return current != null ? current.copy().send() : null;
}
public Buffer currentUnsafe() {
ensureOwned();
return current;
}
public Buffer previousUnsafe() {
ensureOwned();
return previous;
}
2021-08-29 23:18:03 +02:00
public boolean isModified() {
return !LLUtils.equals(previous, current);
}
private void ensureOwned() {
assert isAllAccessible();
if (!isOwned()) {
if (!isAccessible()) {
throw this.createResourceClosedException();
} else {
throw new IllegalStateException("Resource not owned");
}
}
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
LLDelta LLDelta = (LLDelta) o;
return LLUtils.equals(previous, LLDelta.previous) && LLUtils.equals(current, LLDelta.current);
}
@Override
public int hashCode() {
int result = LLUtils.hashCode(previous);
result = 31 * result + LLUtils.hashCode(current);
return result;
}
@Override
public String toString() {
return new StringJoiner(", ", LLDelta.class.getSimpleName() + "[", "]")
2021-09-24 01:59:56 +02:00
.add("min=" + LLUtils.toStringSafe(previous))
.add("max=" + LLUtils.toStringSafe(current))
2021-08-29 23:18:03 +02:00
.toString();
}
@Override
protected RuntimeException createResourceClosedException() {
return new IllegalStateException("Closed");
}
2021-10-01 19:17:33 +02:00
@Override
protected void makeInaccessible() {
this.current = null;
this.previous = null;
this.onClose = null;
}
2021-08-29 23:18:03 +02:00
@Override
protected Owned<LLDelta> prepareSend() {
2021-09-24 01:59:56 +02:00
Send<Buffer> minSend = this.previous != null ? this.previous.send() : null;
Send<Buffer> maxSend = this.current != null ? this.current.send() : null;
2021-10-01 19:17:33 +02:00
Runnable onClose = this.onClose;
return drop -> {
var instance = new LLDelta(
minSend != null ? minSend.receive() : null,
maxSend != null ? maxSend.receive() : null,
onClose
);
2021-10-01 19:17:33 +02:00
drop.attach(instance);
return instance;
};
2021-08-29 23:18:03 +02:00
}
}