2021-08-29 23:18:03 +02:00
|
|
|
package it.cavallium.dbengine.database;
|
|
|
|
|
2021-09-17 16:56:28 +02:00
|
|
|
import io.net5.buffer.api.Buffer;
|
|
|
|
import io.net5.buffer.api.Drop;
|
|
|
|
import io.net5.buffer.api.Owned;
|
|
|
|
import io.net5.buffer.api.Send;
|
2021-10-17 17:15:57 +02:00
|
|
|
import io.net5.buffer.api.internal.ResourceSupport;
|
2021-08-29 23:18:03 +02:00
|
|
|
import java.util.StringJoiner;
|
2021-12-17 01:48:49 +01:00
|
|
|
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
|
|
|
|
2021-12-17 01:48:49 +01: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.close();
|
|
|
|
}
|
|
|
|
} catch (Throwable ex) {
|
|
|
|
logger.error("Failed to close previous", ex);
|
|
|
|
}
|
|
|
|
try {
|
|
|
|
if (obj.current != null) {
|
|
|
|
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
|
|
|
|
2021-10-01 19:17:33 +02:00
|
|
|
private LLDelta(@Nullable Send<Buffer> previous, @Nullable Send<Buffer> current, @Nullable Runnable onClose) {
|
|
|
|
super(DROP);
|
2021-08-29 23:18:03 +02:00
|
|
|
assert isAllAccessible();
|
|
|
|
this.previous = previous != null ? previous.receive().makeReadOnly() : null;
|
|
|
|
this.current = current != null ? current.receive().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;
|
|
|
|
}
|
|
|
|
|
2021-10-17 19:52:43 +02:00
|
|
|
public static LLDelta of(Send<Buffer> previous, Send<Buffer> current) {
|
|
|
|
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 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, maxSend, onClose);
|
|
|
|
drop.attach(instance);
|
|
|
|
return instance;
|
|
|
|
};
|
2021-08-29 23:18:03 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|