mirror of
https://gitlab.com/veilid/veilidchat.git
synced 2025-07-24 15:05:22 -04:00
checkpoint
This commit is contained in:
parent
8a5af51ec7
commit
37f6ca19f7
26 changed files with 357 additions and 166 deletions
|
@ -64,7 +64,7 @@ Future<void> Function() makeTestDHTLogAddTruncate({required int stride}) =>
|
|||
const chunk = 25;
|
||||
for (var n = 0; n < dataset.length; n += chunk) {
|
||||
print('$n-${n + chunk - 1} ');
|
||||
final success = await w.tryAddItems(dataset.sublist(n, n + chunk));
|
||||
final success = await w.tryAddAll(dataset.sublist(n, n + chunk));
|
||||
expect(success, isTrue);
|
||||
}
|
||||
});
|
||||
|
@ -73,22 +73,22 @@ Future<void> Function() makeTestDHTLogAddTruncate({required int stride}) =>
|
|||
|
||||
print('get all\n');
|
||||
{
|
||||
final dataset2 = await dlog.operate((r) async => r.getItemRange(0));
|
||||
final dataset2 = await dlog.operate((r) async => r.getRange(0));
|
||||
expect(dataset2, equals(dataset));
|
||||
}
|
||||
{
|
||||
final dataset3 =
|
||||
await dlog.operate((r) async => r.getItemRange(64, length: 128));
|
||||
await dlog.operate((r) async => r.getRange(64, length: 128));
|
||||
expect(dataset3, equals(dataset.sublist(64, 64 + 128)));
|
||||
}
|
||||
{
|
||||
final dataset4 =
|
||||
await dlog.operate((r) async => r.getItemRange(0, length: 1000));
|
||||
await dlog.operate((r) async => r.getRange(0, length: 1000));
|
||||
expect(dataset4, equals(dataset.sublist(0, 1000)));
|
||||
}
|
||||
{
|
||||
final dataset5 =
|
||||
await dlog.operate((r) async => r.getItemRange(500, length: 499));
|
||||
await dlog.operate((r) async => r.getRange(500, length: 499));
|
||||
expect(dataset5, equals(dataset.sublist(500, 999)));
|
||||
}
|
||||
print('truncate\n');
|
||||
|
@ -96,8 +96,8 @@ Future<void> Function() makeTestDHTLogAddTruncate({required int stride}) =>
|
|||
await dlog.operateAppend((w) async => w.truncate(w.length - 5));
|
||||
}
|
||||
{
|
||||
final dataset6 = await dlog
|
||||
.operate((r) async => r.getItemRange(500 - 5, length: 499));
|
||||
final dataset6 =
|
||||
await dlog.operate((r) async => r.getRange(500 - 5, length: 499));
|
||||
expect(dataset6, equals(dataset.sublist(500, 999)));
|
||||
}
|
||||
print('truncate 2\n');
|
||||
|
@ -105,8 +105,8 @@ Future<void> Function() makeTestDHTLogAddTruncate({required int stride}) =>
|
|||
await dlog.operateAppend((w) async => w.truncate(w.length - 251));
|
||||
}
|
||||
{
|
||||
final dataset7 = await dlog
|
||||
.operate((r) async => r.getItemRange(500 - 256, length: 499));
|
||||
final dataset7 =
|
||||
await dlog.operate((r) async => r.getRange(500 - 256, length: 499));
|
||||
expect(dataset7, equals(dataset.sublist(500, 999)));
|
||||
}
|
||||
print('clear\n');
|
||||
|
@ -115,7 +115,7 @@ Future<void> Function() makeTestDHTLogAddTruncate({required int stride}) =>
|
|||
}
|
||||
print('get all\n');
|
||||
{
|
||||
final dataset8 = await dlog.operate((r) async => r.getItemRange(0));
|
||||
final dataset8 = await dlog.operate((r) async => r.getRange(0));
|
||||
expect(dataset8, isEmpty);
|
||||
}
|
||||
print('delete and close\n');
|
||||
|
|
|
@ -64,7 +64,7 @@ Future<void> Function() makeTestDHTShortArrayAdd({required int stride}) =>
|
|||
final res = await arr.operateWrite((w) async {
|
||||
for (var n = 4; n < 8; n++) {
|
||||
print('$n ');
|
||||
final success = await w.tryAddItem(dataset[n]);
|
||||
final success = await w.tryAdd(dataset[n]);
|
||||
expect(success, isTrue);
|
||||
}
|
||||
});
|
||||
|
@ -75,8 +75,8 @@ Future<void> Function() makeTestDHTShortArrayAdd({required int stride}) =>
|
|||
{
|
||||
final res = await arr.operateWrite((w) async {
|
||||
print('${dataset.length ~/ 2}-${dataset.length}');
|
||||
final success = await w.tryAddItems(
|
||||
dataset.sublist(dataset.length ~/ 2, dataset.length));
|
||||
final success = await w
|
||||
.tryAddAll(dataset.sublist(dataset.length ~/ 2, dataset.length));
|
||||
expect(success, isTrue);
|
||||
});
|
||||
expect(res, isNull);
|
||||
|
@ -87,7 +87,7 @@ Future<void> Function() makeTestDHTShortArrayAdd({required int stride}) =>
|
|||
final res = await arr.operateWrite((w) async {
|
||||
for (var n = 0; n < 4; n++) {
|
||||
print('$n ');
|
||||
final success = await w.tryInsertItem(n, dataset[n]);
|
||||
final success = await w.tryInsert(n, dataset[n]);
|
||||
expect(success, isTrue);
|
||||
}
|
||||
});
|
||||
|
@ -98,8 +98,8 @@ Future<void> Function() makeTestDHTShortArrayAdd({required int stride}) =>
|
|||
{
|
||||
final res = await arr.operateWrite((w) async {
|
||||
print('8-${dataset.length ~/ 2}');
|
||||
final success = await w.tryInsertItems(
|
||||
8, dataset.sublist(8, dataset.length ~/ 2));
|
||||
final success =
|
||||
await w.tryInsertAll(8, dataset.sublist(8, dataset.length ~/ 2));
|
||||
expect(success, isTrue);
|
||||
});
|
||||
expect(res, isNull);
|
||||
|
@ -107,12 +107,12 @@ Future<void> Function() makeTestDHTShortArrayAdd({required int stride}) =>
|
|||
|
||||
//print('get all\n');
|
||||
{
|
||||
final dataset2 = await arr.operate((r) async => r.getItemRange(0));
|
||||
final dataset2 = await arr.operate((r) async => r.getRange(0));
|
||||
expect(dataset2, equals(dataset));
|
||||
}
|
||||
{
|
||||
final dataset3 =
|
||||
await arr.operate((r) async => r.getItemRange(64, length: 128));
|
||||
await arr.operate((r) async => r.getRange(64, length: 128));
|
||||
expect(dataset3, equals(dataset.sublist(64, 64 + 128)));
|
||||
}
|
||||
|
||||
|
@ -126,7 +126,7 @@ Future<void> Function() makeTestDHTShortArrayAdd({required int stride}) =>
|
|||
|
||||
//print('get all\n');
|
||||
{
|
||||
final dataset4 = await arr.operate((r) async => r.getItemRange(0));
|
||||
final dataset4 = await arr.operate((r) async => r.getRange(0));
|
||||
expect(dataset4, isEmpty);
|
||||
}
|
||||
|
||||
|
|
|
@ -62,13 +62,24 @@ message DHTShortArray {
|
|||
// calculated through iteration
|
||||
}
|
||||
|
||||
// Reference to data on the DHT
|
||||
message DHTDataReference {
|
||||
veilid.TypedKey dht_data = 1;
|
||||
veilid.TypedKey hash = 2;
|
||||
}
|
||||
|
||||
// Reference to data on the BlockStore
|
||||
message BlockStoreDataReference {
|
||||
veilid.TypedKey block = 1;
|
||||
}
|
||||
|
||||
// DataReference
|
||||
// Pointer to data somewhere in Veilid
|
||||
// Abstraction over DHTData and BlockStore
|
||||
message DataReference {
|
||||
oneof kind {
|
||||
veilid.TypedKey dht_data = 1;
|
||||
// TypedKey block = 2;
|
||||
DHTDataReference dht_data = 1;
|
||||
BlockStoreDataReference block_store_data = 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ import 'package:meta/meta.dart';
|
|||
|
||||
import '../../../veilid_support.dart';
|
||||
import '../../proto/proto.dart' as proto;
|
||||
import '../interfaces/dht_append.dart';
|
||||
import '../interfaces/dht_add.dart';
|
||||
|
||||
part 'dht_log_spine.dart';
|
||||
part 'dht_log_read.dart';
|
||||
|
|
|
@ -92,7 +92,7 @@ class DHTLogCubit<T> extends Cubit<DHTLogBusyState<T>>
|
|||
|
||||
Future<void> _refreshInner(void Function(AsyncValue<DHTLogStateData<T>>) emit,
|
||||
{bool forceRefresh = false}) async {
|
||||
final avElements = await _loadElements(_tail, _count);
|
||||
final avElements = await loadElements(_tail, _count);
|
||||
final err = avElements.asError;
|
||||
if (err != null) {
|
||||
emit(AsyncValue.error(err.error, err.stackTrace));
|
||||
|
@ -108,9 +108,10 @@ class DHTLogCubit<T> extends Cubit<DHTLogBusyState<T>>
|
|||
elements: elements, tail: _tail, count: _count, follow: _follow)));
|
||||
}
|
||||
|
||||
Future<AsyncValue<IList<DHTLogElementState<T>>>> _loadElements(
|
||||
Future<AsyncValue<IList<DHTLogElementState<T>>>> loadElements(
|
||||
int tail, int count,
|
||||
{bool forceRefresh = false}) async {
|
||||
await _initWait();
|
||||
try {
|
||||
final allItems = await _log.operate((reader) async {
|
||||
final length = reader.length;
|
||||
|
@ -118,7 +119,7 @@ class DHTLogCubit<T> extends Cubit<DHTLogBusyState<T>>
|
|||
final start = (count < end) ? end - count : 0;
|
||||
|
||||
final offlinePositions = await reader.getOfflinePositions();
|
||||
final allItems = (await reader.getItemRange(start,
|
||||
final allItems = (await reader.getRange(start,
|
||||
length: end - start, forceRefresh: forceRefresh))
|
||||
?.indexed
|
||||
.map((x) => DHTLogElementState(
|
||||
|
|
|
@ -12,7 +12,7 @@ class _DHTLogRead implements DHTLogReadOperations {
|
|||
int get length => _spine.length;
|
||||
|
||||
@override
|
||||
Future<Uint8List?> getItem(int pos, {bool forceRefresh = false}) async {
|
||||
Future<Uint8List?> get(int pos, {bool forceRefresh = false}) async {
|
||||
if (pos < 0 || pos >= length) {
|
||||
throw IndexError.withLength(pos, length);
|
||||
}
|
||||
|
@ -21,8 +21,8 @@ class _DHTLogRead implements DHTLogReadOperations {
|
|||
return null;
|
||||
}
|
||||
|
||||
return lookup.scope((sa) => sa.operate(
|
||||
(read) => read.getItem(lookup.pos, forceRefresh: forceRefresh)));
|
||||
return lookup.scope((sa) =>
|
||||
sa.operate((read) => read.get(lookup.pos, forceRefresh: forceRefresh)));
|
||||
}
|
||||
|
||||
(int, int) _clampStartLen(int start, int? len) {
|
||||
|
@ -40,14 +40,14 @@ class _DHTLogRead implements DHTLogReadOperations {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<List<Uint8List>?> getItemRange(int start,
|
||||
Future<List<Uint8List>?> getRange(int start,
|
||||
{int? length, bool forceRefresh = false}) async {
|
||||
final out = <Uint8List>[];
|
||||
(start, length) = _clampStartLen(start, length);
|
||||
|
||||
final chunks = Iterable<int>.generate(length).slices(maxDHTConcurrency).map(
|
||||
(chunk) => chunk
|
||||
.map((pos) => getItem(pos + start, forceRefresh: forceRefresh)));
|
||||
(chunk) =>
|
||||
chunk.map((pos) => get(pos + start, forceRefresh: forceRefresh)));
|
||||
|
||||
for (final chunk in chunks) {
|
||||
final elems = await chunk.wait;
|
||||
|
|
|
@ -3,16 +3,15 @@ part of 'dht_log.dart';
|
|||
class _DHTLogPosition extends DHTCloseable<_DHTLogPosition, DHTShortArray> {
|
||||
_DHTLogPosition._({
|
||||
required _DHTLogSpine dhtLogSpine,
|
||||
required DHTShortArray shortArray,
|
||||
required this.shortArray,
|
||||
required this.pos,
|
||||
required int segmentNumber,
|
||||
}) : _segmentShortArray = shortArray,
|
||||
_dhtLogSpine = dhtLogSpine,
|
||||
}) : _dhtLogSpine = dhtLogSpine,
|
||||
_segmentNumber = segmentNumber;
|
||||
final int pos;
|
||||
|
||||
final _DHTLogSpine _dhtLogSpine;
|
||||
final DHTShortArray _segmentShortArray;
|
||||
final DHTShortArray shortArray;
|
||||
var _openCount = 1;
|
||||
final int _segmentNumber;
|
||||
final Mutex _mutex = Mutex();
|
||||
|
@ -23,7 +22,7 @@ class _DHTLogPosition extends DHTCloseable<_DHTLogPosition, DHTShortArray> {
|
|||
|
||||
/// The type of the openable scope
|
||||
@override
|
||||
FutureOr<DHTShortArray> scoped() => _segmentShortArray;
|
||||
FutureOr<DHTShortArray> scoped() => shortArray;
|
||||
|
||||
/// Add a reference to this log
|
||||
@override
|
||||
|
|
|
@ -17,7 +17,7 @@ class _DHTLogWrite extends _DHTLogRead implements DHTLogWriteOperations {
|
|||
}
|
||||
final lookup = await _spine.lookupPosition(pos);
|
||||
if (lookup == null) {
|
||||
throw StateError("can't write to dht log");
|
||||
throw StateError("can't lookup position in write to dht log");
|
||||
}
|
||||
|
||||
// Write item to the segment
|
||||
|
@ -26,7 +26,47 @@ class _DHTLogWrite extends _DHTLogRead implements DHTLogWriteOperations {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<bool> tryAddItem(Uint8List value) async {
|
||||
Future<void> swap(int aPos, int bPos) async {
|
||||
if (aPos < 0 || aPos >= _spine.length) {
|
||||
throw IndexError.withLength(aPos, _spine.length);
|
||||
}
|
||||
if (bPos < 0 || bPos >= _spine.length) {
|
||||
throw IndexError.withLength(bPos, _spine.length);
|
||||
}
|
||||
final aLookup = await _spine.lookupPosition(aPos);
|
||||
if (aLookup == null) {
|
||||
throw StateError("can't lookup position a in swap of dht log");
|
||||
}
|
||||
final bLookup = await _spine.lookupPosition(bPos);
|
||||
if (bLookup == null) {
|
||||
throw StateError("can't lookup position b in swap of dht log");
|
||||
}
|
||||
|
||||
// Swap items in the segments
|
||||
if (aLookup.shortArray == bLookup.shortArray) {
|
||||
await aLookup.scope((sa) => sa.operateWriteEventual((aWrite) async {
|
||||
await aWrite.swap(aLookup.pos, bLookup.pos);
|
||||
return true;
|
||||
}));
|
||||
} else {
|
||||
final bItem = Output<Uint8List>();
|
||||
await aLookup.scope(
|
||||
(sa) => bLookup.scope((sb) => sa.operateWriteEventual((aWrite) async {
|
||||
if (bItem.value == null) {
|
||||
final aItem = await aWrite.get(aLookup.pos);
|
||||
if (aItem == null) {
|
||||
throw StateError("can't get item for position a in swap");
|
||||
}
|
||||
await sb.operateWriteEventual((bWrite) async =>
|
||||
bWrite.tryWriteItem(bLookup.pos, aItem, output: bItem));
|
||||
}
|
||||
return aWrite.tryWriteItem(aLookup.pos, bItem.value!);
|
||||
})));
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> tryAdd(Uint8List value) async {
|
||||
// Allocate empty index at the end of the list
|
||||
final insertPos = _spine.length;
|
||||
_spine.allocateTail(1);
|
||||
|
@ -44,12 +84,12 @@ class _DHTLogWrite extends _DHTLogRead implements DHTLogWriteOperations {
|
|||
// We should always be appending at the length
|
||||
throw StateError('appending should be at the end');
|
||||
}
|
||||
return write.tryAddItem(value);
|
||||
return write.tryAdd(value);
|
||||
}));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<bool> tryAddItems(List<Uint8List> values) async {
|
||||
Future<bool> tryAddAll(List<Uint8List> values) async {
|
||||
// Allocate empty index at the end of the list
|
||||
final insertPos = _spine.length;
|
||||
_spine.allocateTail(values.length);
|
||||
|
@ -79,7 +119,7 @@ class _DHTLogWrite extends _DHTLogRead implements DHTLogWriteOperations {
|
|||
// We should always be appending at the length
|
||||
throw StateError('appending should be at the end');
|
||||
}
|
||||
return write.tryAddItems(sublistValues);
|
||||
return write.tryAddAll(sublistValues);
|
||||
}));
|
||||
if (!ok) {
|
||||
success = false;
|
||||
|
|
|
@ -54,13 +54,12 @@ class DHTShortArrayCubit<T> extends Cubit<DHTShortArrayBusyState<T>>
|
|||
try {
|
||||
final newState = await _shortArray.operate((reader) async {
|
||||
final offlinePositions = await reader.getOfflinePositions();
|
||||
final allItems =
|
||||
(await reader.getItemRange(0, forceRefresh: forceRefresh))
|
||||
?.indexed
|
||||
.map((x) => DHTShortArrayElementState(
|
||||
value: _decodeElement(x.$2),
|
||||
isOffline: offlinePositions.contains(x.$1)))
|
||||
.toIList();
|
||||
final allItems = (await reader.getRange(0, forceRefresh: forceRefresh))
|
||||
?.indexed
|
||||
.map((x) => DHTShortArrayElementState(
|
||||
value: _decodeElement(x.$2),
|
||||
isOffline: offlinePositions.contains(x.$1)))
|
||||
.toIList();
|
||||
return allItems;
|
||||
});
|
||||
if (newState != null) {
|
||||
|
|
|
@ -12,7 +12,7 @@ class _DHTShortArrayRead implements DHTShortArrayReadOperations {
|
|||
int get length => _head.length;
|
||||
|
||||
@override
|
||||
Future<Uint8List?> getItem(int pos, {bool forceRefresh = false}) async {
|
||||
Future<Uint8List?> get(int pos, {bool forceRefresh = false}) async {
|
||||
if (pos < 0 || pos >= length) {
|
||||
throw IndexError.withLength(pos, length);
|
||||
}
|
||||
|
@ -49,14 +49,14 @@ class _DHTShortArrayRead implements DHTShortArrayReadOperations {
|
|||
}
|
||||
|
||||
@override
|
||||
Future<List<Uint8List>?> getItemRange(int start,
|
||||
Future<List<Uint8List>?> getRange(int start,
|
||||
{int? length, bool forceRefresh = false}) async {
|
||||
final out = <Uint8List>[];
|
||||
(start, length) = _clampStartLen(start, length);
|
||||
|
||||
final chunks = Iterable<int>.generate(length).slices(maxDHTConcurrency).map(
|
||||
(chunk) => chunk
|
||||
.map((pos) => getItem(pos + start, forceRefresh: forceRefresh)));
|
||||
(chunk) =>
|
||||
chunk.map((pos) => get(pos + start, forceRefresh: forceRefresh)));
|
||||
|
||||
for (final chunk in chunks) {
|
||||
final elems = await chunk.wait;
|
||||
|
|
|
@ -16,15 +16,14 @@ class _DHTShortArrayWrite extends _DHTShortArrayRead
|
|||
_DHTShortArrayWrite._(super.head) : super._();
|
||||
|
||||
@override
|
||||
Future<bool> tryAddItem(Uint8List value) =>
|
||||
tryInsertItem(_head.length, value);
|
||||
Future<bool> tryAdd(Uint8List value) => tryInsert(_head.length, value);
|
||||
|
||||
@override
|
||||
Future<bool> tryAddItems(List<Uint8List> values) =>
|
||||
tryInsertItems(_head.length, values);
|
||||
Future<bool> tryAddAll(List<Uint8List> values) =>
|
||||
tryInsertAll(_head.length, values);
|
||||
|
||||
@override
|
||||
Future<bool> tryInsertItem(int pos, Uint8List value) async {
|
||||
Future<bool> tryInsert(int pos, Uint8List value) async {
|
||||
if (pos < 0 || pos > _head.length) {
|
||||
throw IndexError.withLength(pos, _head.length);
|
||||
}
|
||||
|
@ -44,7 +43,7 @@ class _DHTShortArrayWrite extends _DHTShortArrayRead
|
|||
}
|
||||
|
||||
@override
|
||||
Future<bool> tryInsertItems(int pos, List<Uint8List> values) async {
|
||||
Future<bool> tryInsertAll(int pos, List<Uint8List> values) async {
|
||||
if (pos < 0 || pos > _head.length) {
|
||||
throw IndexError.withLength(pos, _head.length);
|
||||
}
|
||||
|
@ -100,7 +99,7 @@ class _DHTShortArrayWrite extends _DHTShortArrayRead
|
|||
}
|
||||
|
||||
@override
|
||||
Future<void> swapItem(int aPos, int bPos) async {
|
||||
Future<void> swap(int aPos, int bPos) async {
|
||||
if (aPos < 0 || aPos >= _head.length) {
|
||||
throw IndexError.withLength(aPos, _head.length);
|
||||
}
|
||||
|
@ -112,7 +111,7 @@ class _DHTShortArrayWrite extends _DHTShortArrayRead
|
|||
}
|
||||
|
||||
@override
|
||||
Future<void> removeItem(int pos, {Output<Uint8List>? output}) async {
|
||||
Future<void> remove(int pos, {Output<Uint8List>? output}) async {
|
||||
if (pos < 0 || pos >= _head.length) {
|
||||
throw IndexError.withLength(pos, _head.length);
|
||||
}
|
||||
|
|
|
@ -12,30 +12,30 @@ abstract class DHTAdd {
|
|||
/// changed before the element could be added or a newer value was found on
|
||||
/// the network.
|
||||
/// Throws a StateError if the container exceeds its maximum size.
|
||||
Future<bool> tryAddItem(Uint8List value);
|
||||
Future<bool> tryAdd(Uint8List value);
|
||||
|
||||
/// Try to add a list of items to the DHT container.
|
||||
/// Return true if the elements were successfully added, and false if the
|
||||
/// state changed before the element could be added or a newer value was found
|
||||
/// on the network.
|
||||
/// Throws a StateError if the container exceeds its maximum size.
|
||||
Future<bool> tryAddItems(List<Uint8List> values);
|
||||
Future<bool> tryAddAll(List<Uint8List> values);
|
||||
}
|
||||
|
||||
extension DHTAddExt on DHTAdd {
|
||||
/// Convenience function:
|
||||
/// Like tryAddItem but also encodes the input value as JSON and parses the
|
||||
/// returned element as JSON
|
||||
Future<bool> tryAppendItemJson<T>(
|
||||
Future<bool> tryAddJson<T>(
|
||||
T newValue,
|
||||
) =>
|
||||
tryAddItem(jsonEncodeBytes(newValue));
|
||||
tryAdd(jsonEncodeBytes(newValue));
|
||||
|
||||
/// Convenience function:
|
||||
/// Like tryAddItem but also encodes the input value as a protobuf object
|
||||
/// and parses the returned element as a protobuf object
|
||||
Future<bool> tryAddItemProtobuf<T extends GeneratedMessage>(
|
||||
Future<bool> tryAddProtobuf<T extends GeneratedMessage>(
|
||||
T newValue,
|
||||
) =>
|
||||
tryAddItem(newValue.writeToBuffer());
|
||||
tryAdd(newValue.writeToBuffer());
|
||||
}
|
|
@ -14,7 +14,7 @@ abstract class DHTInsertRemove {
|
|||
/// Throws an IndexError if the position removed exceeds the length of
|
||||
/// the container.
|
||||
/// Throws a StateError if the container exceeds its maximum size.
|
||||
Future<bool> tryInsertItem(int pos, Uint8List value);
|
||||
Future<bool> tryInsert(int pos, Uint8List value);
|
||||
|
||||
/// Try to insert items at position 'pos' of the DHT container.
|
||||
/// Return true if the elements were successfully inserted, and false if the
|
||||
|
@ -23,38 +23,33 @@ abstract class DHTInsertRemove {
|
|||
/// Throws an IndexError if the position removed exceeds the length of
|
||||
/// the container.
|
||||
/// Throws a StateError if the container exceeds its maximum size.
|
||||
Future<bool> tryInsertItems(int pos, List<Uint8List> values);
|
||||
|
||||
/// Swap items at position 'aPos' and 'bPos' in the DHTArray.
|
||||
/// Throws an IndexError if either of the positions swapped exceeds the length
|
||||
/// of the container
|
||||
Future<void> swapItem(int aPos, int bPos);
|
||||
Future<bool> tryInsertAll(int pos, List<Uint8List> values);
|
||||
|
||||
/// Remove an item at position 'pos' in the DHT container.
|
||||
/// If the remove was successful this returns:
|
||||
/// * outValue will return the prior contents of the element
|
||||
/// Throws an IndexError if the position removed exceeds the length of
|
||||
/// the container.
|
||||
Future<void> removeItem(int pos, {Output<Uint8List>? output});
|
||||
Future<void> remove(int pos, {Output<Uint8List>? output});
|
||||
}
|
||||
|
||||
extension DHTInsertRemoveExt on DHTInsertRemove {
|
||||
/// Convenience function:
|
||||
/// Like removeItem but also parses the returned element as JSON
|
||||
Future<void> removeItemJson<T>(T Function(dynamic) fromJson, int pos,
|
||||
/// Like remove but also parses the returned element as JSON
|
||||
Future<void> removeJson<T>(T Function(dynamic) fromJson, int pos,
|
||||
{Output<T>? output}) async {
|
||||
final outValueBytes = output == null ? null : Output<Uint8List>();
|
||||
await removeItem(pos, output: outValueBytes);
|
||||
await remove(pos, output: outValueBytes);
|
||||
output.mapSave(outValueBytes, (b) => jsonDecodeBytes(fromJson, b));
|
||||
}
|
||||
|
||||
/// Convenience function:
|
||||
/// Like removeItem but also parses the returned element as JSON
|
||||
Future<void> removeItemProtobuf<T extends GeneratedMessage>(
|
||||
/// Like remove but also parses the returned element as JSON
|
||||
Future<void> removeProtobuf<T extends GeneratedMessage>(
|
||||
T Function(List<int>) fromBuffer, int pos,
|
||||
{Output<T>? output}) async {
|
||||
final outValueBytes = output == null ? null : Output<Uint8List>();
|
||||
await removeItem(pos, output: outValueBytes);
|
||||
await remove(pos, output: outValueBytes);
|
||||
output.mapSave(outValueBytes, fromBuffer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,14 +15,14 @@ abstract class DHTRandomRead {
|
|||
/// rather than returning the existing locally stored copy of the elements.
|
||||
/// Throws an IndexError if the 'pos' is not within the length
|
||||
/// of the container.
|
||||
Future<Uint8List?> getItem(int pos, {bool forceRefresh = false});
|
||||
Future<Uint8List?> get(int pos, {bool forceRefresh = false});
|
||||
|
||||
/// Return a list of a range of items in the DHTArray. If 'forceRefresh'
|
||||
/// is specified, the network will always be checked for newer values
|
||||
/// rather than returning the existing locally stored copy of the elements.
|
||||
/// Throws an IndexError if either 'start' or '(start+length)' is not within
|
||||
/// the length of the container.
|
||||
Future<List<Uint8List>?> getItemRange(int start,
|
||||
Future<List<Uint8List>?> getRange(int start,
|
||||
{int? length, bool forceRefresh = false});
|
||||
|
||||
/// Get a list of the positions that were written offline and not flushed yet
|
||||
|
@ -31,32 +31,32 @@ abstract class DHTRandomRead {
|
|||
|
||||
extension DHTRandomReadExt on DHTRandomRead {
|
||||
/// Convenience function:
|
||||
/// Like getItem but also parses the returned element as JSON
|
||||
Future<T?> getItemJson<T>(T Function(dynamic) fromJson, int pos,
|
||||
/// Like get but also parses the returned element as JSON
|
||||
Future<T?> getJson<T>(T Function(dynamic) fromJson, int pos,
|
||||
{bool forceRefresh = false}) =>
|
||||
getItem(pos, forceRefresh: forceRefresh)
|
||||
get(pos, forceRefresh: forceRefresh)
|
||||
.then((out) => jsonDecodeOptBytes(fromJson, out));
|
||||
|
||||
/// Convenience function:
|
||||
/// Like getAllItems but also parses the returned elements as JSON
|
||||
Future<List<T>?> getItemRangeJson<T>(T Function(dynamic) fromJson, int start,
|
||||
/// Like getRange but also parses the returned elements as JSON
|
||||
Future<List<T>?> getRangeJson<T>(T Function(dynamic) fromJson, int start,
|
||||
{int? length, bool forceRefresh = false}) =>
|
||||
getItemRange(start, length: length, forceRefresh: forceRefresh)
|
||||
getRange(start, length: length, forceRefresh: forceRefresh)
|
||||
.then((out) => out?.map(fromJson).toList());
|
||||
|
||||
/// Convenience function:
|
||||
/// Like getItem but also parses the returned element as a protobuf object
|
||||
Future<T?> getItemProtobuf<T extends GeneratedMessage>(
|
||||
/// Like get but also parses the returned element as a protobuf object
|
||||
Future<T?> getProtobuf<T extends GeneratedMessage>(
|
||||
T Function(List<int>) fromBuffer, int pos,
|
||||
{bool forceRefresh = false}) =>
|
||||
getItem(pos, forceRefresh: forceRefresh)
|
||||
get(pos, forceRefresh: forceRefresh)
|
||||
.then((out) => (out == null) ? null : fromBuffer(out));
|
||||
|
||||
/// Convenience function:
|
||||
/// Like getAllItems but also parses the returned elements as protobuf objects
|
||||
Future<List<T>?> getItemRangeProtobuf<T extends GeneratedMessage>(
|
||||
/// Like getRange but also parses the returned elements as protobuf objects
|
||||
Future<List<T>?> getRangeProtobuf<T extends GeneratedMessage>(
|
||||
T Function(List<int>) fromBuffer, int start,
|
||||
{int? length, bool forceRefresh = false}) =>
|
||||
getItemRange(start, length: length, forceRefresh: forceRefresh)
|
||||
getRange(start, length: length, forceRefresh: forceRefresh)
|
||||
.then((out) => out?.map(fromBuffer).toList());
|
||||
}
|
||||
|
|
|
@ -23,6 +23,11 @@ abstract class DHTRandomWrite {
|
|||
/// of the container.
|
||||
Future<bool> tryWriteItem(int pos, Uint8List newValue,
|
||||
{Output<Uint8List>? output});
|
||||
|
||||
/// Swap items at position 'aPos' and 'bPos' in the DHTArray.
|
||||
/// Throws an IndexError if either of the positions swapped exceeds the length
|
||||
/// of the container
|
||||
Future<void> swap(int aPos, int bPos);
|
||||
}
|
||||
|
||||
extension DHTRandomWriteExt on DHTRandomWrite {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
export 'dht_append.dart';
|
||||
export 'dht_add.dart';
|
||||
export 'dht_clear.dart';
|
||||
export 'dht_closeable.dart';
|
||||
export 'dht_insert_remove.dart';
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'package:async_tools/async_tools.dart';
|
|||
import 'package:charcode/charcode.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:protobuf/protobuf.dart';
|
||||
|
||||
import '../veilid_support.dart';
|
||||
|
||||
|
@ -128,13 +129,13 @@ class TableDBArray {
|
|||
});
|
||||
}
|
||||
|
||||
Future<List<Uint8List>> getRange(int start, int end) async {
|
||||
Future<List<Uint8List>> getRange(int start, [int? end]) async {
|
||||
await _initWait();
|
||||
return _mutex.protect(() async {
|
||||
if (!_open) {
|
||||
throw StateError('not open');
|
||||
}
|
||||
return _getRangeInner(start, end);
|
||||
return _getRangeInner(start, end ?? _length);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -629,3 +630,36 @@ class TableDBArray {
|
|||
final StreamController<TableDBArrayUpdate> _changeStream =
|
||||
StreamController.broadcast();
|
||||
}
|
||||
|
||||
extension TableDBArrayExt on TableDBArray {
|
||||
/// Convenience function:
|
||||
/// Like get but also parses the returned element as JSON
|
||||
Future<T?> getJson<T>(
|
||||
T Function(dynamic) fromJson,
|
||||
int pos,
|
||||
) =>
|
||||
get(
|
||||
pos,
|
||||
).then((out) => jsonDecodeOptBytes(fromJson, out));
|
||||
|
||||
/// Convenience function:
|
||||
/// Like getRange but also parses the returned elements as JSON
|
||||
Future<List<T>?> getRangeJson<T>(T Function(dynamic) fromJson, int start,
|
||||
[int? end]) =>
|
||||
getRange(start, end ?? _length).then((out) => out.map(fromJson).toList());
|
||||
|
||||
/// Convenience function:
|
||||
/// Like get but also parses the returned element as a protobuf object
|
||||
Future<T?> getProtobuf<T extends GeneratedMessage>(
|
||||
T Function(List<int>) fromBuffer,
|
||||
int pos,
|
||||
) =>
|
||||
get(pos).then(fromBuffer);
|
||||
|
||||
/// Convenience function:
|
||||
/// Like getRange but also parses the returned elements as protobuf objects
|
||||
Future<List<T>?> getRangeProtobuf<T extends GeneratedMessage>(
|
||||
T Function(List<int>) fromBuffer, int start, [int? end]) =>
|
||||
getRange(start, end ?? _length)
|
||||
.then((out) => out.map(fromBuffer).toList());
|
||||
}
|
||||
|
|
|
@ -13,16 +13,16 @@ abstract class VeilidCrypto {
|
|||
class VeilidCryptoPrivate implements VeilidCrypto {
|
||||
VeilidCryptoPrivate._(VeilidCryptoSystem cryptoSystem, SharedSecret secretKey)
|
||||
: _cryptoSystem = cryptoSystem,
|
||||
_secretKey = secretKey;
|
||||
_secret = secretKey;
|
||||
final VeilidCryptoSystem _cryptoSystem;
|
||||
final SharedSecret _secretKey;
|
||||
final SharedSecret _secret;
|
||||
|
||||
static Future<VeilidCryptoPrivate> fromTypedKey(
|
||||
TypedKey typedKey, String domain) async {
|
||||
final cryptoSystem = await Veilid.instance.getCryptoSystem(typedKey.kind);
|
||||
final keyMaterial = Uint8List(0)
|
||||
..addAll(typedKey.value.decode())
|
||||
..addAll(utf8.encode(domain));
|
||||
TypedKey typedSecret, String domain) async {
|
||||
final cryptoSystem =
|
||||
await Veilid.instance.getCryptoSystem(typedSecret.kind);
|
||||
final keyMaterial = Uint8List.fromList(
|
||||
[...typedSecret.value.decode(), ...utf8.encode(domain)]);
|
||||
final secretKey = await cryptoSystem.generateHash(keyMaterial);
|
||||
return VeilidCryptoPrivate._(cryptoSystem, secretKey);
|
||||
}
|
||||
|
@ -35,18 +35,18 @@ class VeilidCryptoPrivate implements VeilidCrypto {
|
|||
}
|
||||
|
||||
static Future<VeilidCryptoPrivate> fromSharedSecret(
|
||||
CryptoKind kind, SharedSecret secretKey) async {
|
||||
CryptoKind kind, SharedSecret sharedSecret) async {
|
||||
final cryptoSystem = await Veilid.instance.getCryptoSystem(kind);
|
||||
return VeilidCryptoPrivate._(cryptoSystem, secretKey);
|
||||
return VeilidCryptoPrivate._(cryptoSystem, sharedSecret);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Uint8List> encrypt(Uint8List data) =>
|
||||
_cryptoSystem.encryptNoAuthWithNonce(data, _secretKey);
|
||||
_cryptoSystem.encryptNoAuthWithNonce(data, _secret);
|
||||
|
||||
@override
|
||||
Future<Uint8List> decrypt(Uint8List data) =>
|
||||
_cryptoSystem.decryptNoAuthWithNonce(data, _secretKey);
|
||||
_cryptoSystem.decryptNoAuthWithNonce(data, _secret);
|
||||
}
|
||||
|
||||
////////////////////////////////////
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue