mirror of
https://github.com/usatiuk/dhfs.git
synced 2025-10-28 12:37:48 +01:00
Compare commits
4 Commits
b89b182c58
...
8d3244fe64
| Author | SHA1 | Date | |
|---|---|---|---|
| 8d3244fe64 | |||
| 0a8985c93f | |||
| a8cf483eee | |||
| f7338f4e80 |
@@ -14,6 +14,9 @@ Syncthing and allowing you to stream your files like Google Drive File Stream
|
||||
This is a simple wrapper around the jar/web ui distribution that allows you to run/stop
|
||||
the DHFS server in the background, and update itself (hopefully!)
|
||||
|
||||
## How to use it and how it works?
|
||||
## How to use it?
|
||||
|
||||
TODO 😁
|
||||
|
||||
Unpack the run-wrapper and run the `run` script. The filesystem should be mounted to the `fuse` folder in the run-wrapper root directory.
|
||||
|
||||
Then, a web interface will be available at `losthost:8080`, that can be used to connect with other peers.
|
||||
|
||||
@@ -115,7 +115,7 @@ public class KillIT {
|
||||
Log.info(ls2);
|
||||
Log.info(cat2);
|
||||
|
||||
return ls1.equals(ls2) && cat1.equals(cat2);
|
||||
return ls1.equals(ls2) && cat1.equals(cat2) && ls1.getExitCode() == 0 && ls2.getExitCode() == 0 && cat1.getExitCode() == 0 && cat2.getExitCode() == 0;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -133,7 +133,7 @@ public class LazyFsIT {
|
||||
+ ls2 + "\n"
|
||||
+ cat2 + "\n");
|
||||
|
||||
return ls1.equals(ls2) && cat1.equals(cat2);
|
||||
return ls1.equals(ls2) && cat1.equals(cat2) && ls1.getExitCode() == 0 && ls2.getExitCode() == 0 && cat1.getExitCode() == 0 && cat2.getExitCode() == 0;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,6 @@ import com.usatiuk.objects.iterators.IteratorStart;
|
||||
import com.usatiuk.objects.iterators.KeyPredicateKvIterator;
|
||||
import com.usatiuk.objects.iterators.ReversibleKvIterator;
|
||||
import com.usatiuk.objects.snapshot.Snapshot;
|
||||
import com.usatiuk.utils.RefcountedCloseable;
|
||||
import io.quarkus.arc.properties.IfBuildProperty;
|
||||
import io.quarkus.logging.Log;
|
||||
import io.quarkus.runtime.ShutdownEvent;
|
||||
@@ -104,53 +103,48 @@ public class LmdbObjectPersistentStore implements ObjectPersistentStore {
|
||||
if (!_ready) throw new IllegalStateException("Wrong service order!");
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Optional<ByteString> readObject(JObjectKey name) {
|
||||
verifyReady();
|
||||
try (Txn<ByteBuffer> txn = _env.txnRead()) {
|
||||
var value = _db.get(txn, name.toByteBuffer());
|
||||
return Optional.ofNullable(value).map(ByteString::copyFrom);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Snapshot<JObjectKey, ByteString> getSnapshot() {
|
||||
var txn = new RefcountedCloseable<>(_env.txnRead());
|
||||
long commitId = readTxId(txn.get()).orElseThrow();
|
||||
return new Snapshot<JObjectKey, ByteString>() {
|
||||
private final RefcountedCloseable<Txn<ByteBuffer>> _txn = txn;
|
||||
private final long _id = commitId;
|
||||
private boolean _closed = false;
|
||||
var txn = _env.txnRead();
|
||||
try {
|
||||
long commitId = readTxId(txn).orElseThrow();
|
||||
return new Snapshot<JObjectKey, ByteString>() {
|
||||
private final Txn<ByteBuffer> _txn = txn;
|
||||
private final long _id = commitId;
|
||||
private boolean _closed = false;
|
||||
|
||||
@Override
|
||||
public CloseableKvIterator<JObjectKey, ByteString> getIterator(IteratorStart start, JObjectKey key) {
|
||||
assert !_closed;
|
||||
return new KeyPredicateKvIterator<>(new LmdbKvIterator(_txn.ref(), start, key), start, key, (k) -> !k.value().equals(DB_VER_OBJ_NAME_STR));
|
||||
}
|
||||
@Override
|
||||
public CloseableKvIterator<JObjectKey, ByteString> getIterator(IteratorStart start, JObjectKey key) {
|
||||
assert !_closed;
|
||||
return new KeyPredicateKvIterator<>(new LmdbKvIterator(_txn, start, key), start, key, (k) -> !k.value().equals(DB_VER_OBJ_NAME_STR));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Optional<ByteString> readObject(JObjectKey name) {
|
||||
assert !_closed;
|
||||
var got = _db.get(_txn.get(), name.toByteBuffer());
|
||||
var ret = Optional.ofNullable(got).map(UnsafeByteOperations::unsafeWrap);
|
||||
return ret;
|
||||
}
|
||||
@Nonnull
|
||||
@Override
|
||||
public Optional<ByteString> readObject(JObjectKey name) {
|
||||
assert !_closed;
|
||||
var got = _db.get(_txn, name.toByteBuffer());
|
||||
var ret = Optional.ofNullable(got).map(UnsafeByteOperations::unsafeWrap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long id() {
|
||||
assert !_closed;
|
||||
return _id;
|
||||
}
|
||||
@Override
|
||||
public long id() {
|
||||
assert !_closed;
|
||||
return _id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
assert !_closed;
|
||||
_closed = true;
|
||||
_txn.unref();
|
||||
}
|
||||
};
|
||||
@Override
|
||||
public void close() {
|
||||
assert !_closed;
|
||||
_closed = true;
|
||||
_txn.close();
|
||||
}
|
||||
};
|
||||
} catch (Exception e) {
|
||||
txn.close();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -205,28 +199,28 @@ public class LmdbObjectPersistentStore implements ObjectPersistentStore {
|
||||
|
||||
private class LmdbKvIterator extends ReversibleKvIterator<JObjectKey, ByteString> {
|
||||
private static final Cleaner CLEANER = Cleaner.create();
|
||||
private final RefcountedCloseable<Txn<ByteBuffer>> _txn;
|
||||
private final Txn<ByteBuffer> _txn; // Managed by the snapshot
|
||||
private final Cursor<ByteBuffer> _cursor;
|
||||
private final MutableObject<Boolean> _closed = new MutableObject<>(false);
|
||||
// private final Exception _allocationStacktrace = new Exception();
|
||||
private final Exception _allocationStacktrace = null;
|
||||
// private final Exception _allocationStacktrace = null;
|
||||
private boolean _hasNext = false;
|
||||
private JObjectKey _peekedNextKey = null;
|
||||
|
||||
LmdbKvIterator(RefcountedCloseable<Txn<ByteBuffer>> txn, IteratorStart start, JObjectKey key) {
|
||||
LmdbKvIterator(Txn<ByteBuffer> txn, IteratorStart start, JObjectKey key) {
|
||||
_txn = txn;
|
||||
_goingForward = true;
|
||||
|
||||
_cursor = _db.openCursor(_txn.get());
|
||||
_cursor = _db.openCursor(_txn);
|
||||
|
||||
var closedRef = _closed;
|
||||
var bt = _allocationStacktrace;
|
||||
CLEANER.register(this, () -> {
|
||||
if (!closedRef.getValue()) {
|
||||
Log.error("Iterator was not closed before GC, allocated at: {0}", bt);
|
||||
System.exit(-1);
|
||||
}
|
||||
});
|
||||
// var bt = _allocationStacktrace;
|
||||
// CLEANER.register(this, () -> {
|
||||
// if (!closedRef.getValue()) {
|
||||
// Log.error("Iterator was not closed before GC, allocated at: {0}", bt);
|
||||
// System.exit(-1);
|
||||
// }
|
||||
// });
|
||||
|
||||
verifyReady();
|
||||
|
||||
@@ -308,7 +302,6 @@ public class LmdbObjectPersistentStore implements ObjectPersistentStore {
|
||||
}
|
||||
_closed.setValue(true);
|
||||
_cursor.close();
|
||||
_txn.unref();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,14 +21,6 @@ public class MemoryObjectPersistentStore implements ObjectPersistentStore {
|
||||
private TreePMap<JObjectKey, ByteString> _objects = TreePMap.empty();
|
||||
private long _lastCommitId = 0;
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Optional<ByteString> readObject(JObjectKey name) {
|
||||
synchronized (this) {
|
||||
return Optional.ofNullable(_objects.get(name));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Snapshot<JObjectKey, ByteString> getSnapshot() {
|
||||
synchronized (this) {
|
||||
|
||||
@@ -10,9 +10,6 @@ import java.util.Optional;
|
||||
// Persistent storage of objects
|
||||
// All changes are written as sequential transactions
|
||||
public interface ObjectPersistentStore {
|
||||
@Nonnull
|
||||
Optional<ByteString> readObject(JObjectKey name);
|
||||
|
||||
Snapshot<JObjectKey, ByteString> getSnapshot();
|
||||
|
||||
Runnable prepareTx(TxManifestRaw names, long txId);
|
||||
|
||||
@@ -23,11 +23,6 @@ public class SerializingObjectPersistentStore {
|
||||
@Inject
|
||||
ObjectPersistentStore delegateStore;
|
||||
|
||||
@Nonnull
|
||||
Optional<JDataVersionedWrapper> readObject(JObjectKey name) {
|
||||
return delegateStore.readObject(name).map(serializer::deserialize);
|
||||
}
|
||||
|
||||
public Snapshot<JObjectKey, JDataVersionedWrapper> getSnapshot() {
|
||||
return new Snapshot<JObjectKey, JDataVersionedWrapper>() {
|
||||
private final Snapshot<JObjectKey, ByteString> _backing = delegateStore.getSnapshot();
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
package com.usatiuk.utils;
|
||||
|
||||
import io.quarkus.logging.Log;
|
||||
import org.apache.commons.lang3.mutable.MutableObject;
|
||||
|
||||
import java.lang.ref.Cleaner;
|
||||
|
||||
public class RefcountedCloseable<T extends AutoCloseable> {
|
||||
private static final Cleaner CLEANER = Cleaner.create();
|
||||
private final T _closeable;
|
||||
private final MutableObject<Boolean> _closed = new MutableObject<>(false);
|
||||
private int _refCount = 1;
|
||||
|
||||
public RefcountedCloseable(T closeable) {
|
||||
_closeable = closeable;
|
||||
var closedRef = _closed;
|
||||
CLEANER.register(this, () -> {
|
||||
if (!closedRef.getValue()) {
|
||||
Log.error("RefcountedCloseable was not closed before GC");
|
||||
System.exit(-1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public RefcountedCloseable<T> ref() {
|
||||
synchronized (this) {
|
||||
if (_closed.getValue()) {
|
||||
return null;
|
||||
}
|
||||
_refCount++;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public void unref() {
|
||||
synchronized (this) {
|
||||
_refCount--;
|
||||
if (_refCount == 0) {
|
||||
try {
|
||||
assert !_closed.getValue();
|
||||
_closed.setValue(true);
|
||||
_closeable.close();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public T get() {
|
||||
return _closeable;
|
||||
}
|
||||
}
|
||||
38
webui/package-lock.json
generated
38
webui/package-lock.json
generated
@@ -9,6 +9,7 @@
|
||||
"version": "0.0.1",
|
||||
"dependencies": {
|
||||
"jwt-decode": "^4.0.0",
|
||||
"node-forge": "^1.3.1",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"react-router": "^7.5.2",
|
||||
@@ -21,6 +22,7 @@
|
||||
"@parcel/validator-typescript": "^2.14.4",
|
||||
"@types/eslint": "^9.6.1",
|
||||
"@types/eslint-config-prettier": "^6.11.3",
|
||||
"@types/node-forge": "^1.3.11",
|
||||
"@types/react": "^19.0.12",
|
||||
"@types/react-dom": "^19.0.4",
|
||||
"@typescript-eslint/eslint-plugin": "^8.28.0",
|
||||
@@ -2436,6 +2438,26 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "22.15.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.2.tgz",
|
||||
"integrity": "sha512-uKXqKN9beGoMdBfcaTY1ecwz6ctxuJAcUlwE55938g0ZJ8lRxwAZqRz2AJ4pzpt5dHdTPMB863UZ0ESiFUcP7A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.21.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node-forge": {
|
||||
"version": "1.3.11",
|
||||
"resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.11.tgz",
|
||||
"integrity": "sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/react": {
|
||||
"version": "19.0.12",
|
||||
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.12.tgz",
|
||||
@@ -5465,6 +5487,15 @@
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/node-forge": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
|
||||
"integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
|
||||
"license": "(BSD-3-Clause OR GPL-2.0)",
|
||||
"engines": {
|
||||
"node": ">= 6.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/node-gyp-build-optional-packages": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.1.1.tgz",
|
||||
@@ -6871,6 +6902,13 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
||||
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/update-browserslist-db": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
"browserslist": "> 0.5%, last 2 versions, not dead",
|
||||
"dependencies": {
|
||||
"jwt-decode": "^4.0.0",
|
||||
"node-forge": "^1.3.1",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"react-router": "^7.5.2",
|
||||
@@ -25,6 +26,7 @@
|
||||
"@parcel/validator-typescript": "^2.14.4",
|
||||
"@types/eslint": "^9.6.1",
|
||||
"@types/eslint-config-prettier": "^6.11.3",
|
||||
"@types/node-forge": "^1.3.11",
|
||||
"@types/react": "^19.0.12",
|
||||
"@types/react-dom": "^19.0.4",
|
||||
"@typescript-eslint/eslint-plugin": "^8.28.0",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as forge from "node-forge";
|
||||
|
||||
export async function hashCert(cert: string) {
|
||||
const hash = await crypto.subtle.digest(
|
||||
"SHA-1",
|
||||
new TextEncoder().encode(cert),
|
||||
);
|
||||
return btoa(String.fromCharCode(...new Uint8Array(hash)));
|
||||
const md = forge.md.sha1.create();
|
||||
md.update(cert);
|
||||
return md.digest().toHex();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user