mutex debugging

This commit is contained in:
Christien Rioux 2024-08-06 08:51:19 -07:00
parent 120a7105c8
commit 103975bb56
24 changed files with 88 additions and 65 deletions

View File

@ -90,8 +90,8 @@
"accept": "Accept",
"reject": "Reject",
"finish": "Finish",
"yes_proceed": "Yes, proceed",
"no_cancel": "No, cancel",
"yes": "Yes",
"no": "No",
"waiting_for_network": "Waiting For Network"
},
"toast": {

View File

@ -56,6 +56,7 @@ class AccountRecordCubit extends DefaultDHTRecordCubit<AccountRecordState> {
Future<void> _updateAccountAsync(
AccountSpec accountSpec, Future<void> Function() onSuccess) async {
var changed = false;
await record?.eventualUpdateProtobuf(proto.Account.fromBuffer, (old) async {
changed = false;
if (old == null) {

View File

@ -97,7 +97,7 @@ class _EditAccountPageState extends WindowSetupState<EditAccountPage> {
},
child: Row(mainAxisSize: MainAxisSize.min, children: [
const Icon(Icons.cancel, size: 16).paddingLTRB(0, 0, 4, 0),
Text(translate('button.no_cancel')).paddingLTRB(0, 0, 4, 0)
Text(translate('button.no')).paddingLTRB(0, 0, 4, 0)
])),
ElevatedButton(
onPressed: () {
@ -105,7 +105,7 @@ class _EditAccountPageState extends WindowSetupState<EditAccountPage> {
},
child: Row(mainAxisSize: MainAxisSize.min, children: [
const Icon(Icons.check, size: 16).paddingLTRB(0, 0, 4, 0),
Text(translate('button.yes_proceed')).paddingLTRB(0, 0, 4, 0)
Text(translate('button.yes')).paddingLTRB(0, 0, 4, 0)
]))
]).paddingAll(24)
]));
@ -165,7 +165,7 @@ class _EditAccountPageState extends WindowSetupState<EditAccountPage> {
},
child: Row(mainAxisSize: MainAxisSize.min, children: [
const Icon(Icons.cancel, size: 16).paddingLTRB(0, 0, 4, 0),
Text(translate('button.no_cancel')).paddingLTRB(0, 0, 4, 0)
Text(translate('button.no')).paddingLTRB(0, 0, 4, 0)
])),
ElevatedButton(
onPressed: () {
@ -173,7 +173,7 @@ class _EditAccountPageState extends WindowSetupState<EditAccountPage> {
},
child: Row(mainAxisSize: MainAxisSize.min, children: [
const Icon(Icons.check, size: 16).paddingLTRB(0, 0, 4, 0),
Text(translate('button.yes_proceed')).paddingLTRB(0, 0, 4, 0)
Text(translate('button.yes')).paddingLTRB(0, 0, 4, 0)
]))
]).paddingAll(24)
]));

View File

@ -2,6 +2,7 @@ import 'package:async_tools/async_tools.dart';
import 'package:awesome_extensions/awesome_extensions.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_form_builder/flutter_form_builder.dart';
import 'package:flutter_translate/flutter_translate.dart';
import 'package:form_builder_validators/form_builder_validators.dart';
@ -9,6 +10,7 @@ import 'package:form_builder_validators/form_builder_validators.dart';
import '../../contacts/contacts.dart';
import '../../proto/proto.dart' as proto;
import '../../theme/theme.dart';
import '../../veilid_processor/veilid_processor.dart';
import '../models/models.dart';
const _kDoUpdateSubmit = 'doUpdateSubmit';
@ -291,16 +293,26 @@ class _EditProfileFormState extends State<EditProfileForm> {
const Spacer(),
]).paddingSymmetric(vertical: 4),
if (widget.onSubmit != null)
ElevatedButton(
onPressed: widget.onSubmit == null ? null : _doSubmit,
Builder(builder: (context) {
final networkReady = context
.watch<ConnectionStateCubit>()
.state
.asData
?.value
.isPublicInternetReady ??
false;
return ElevatedButton(
onPressed: networkReady ? _doSubmit : null,
child: Row(mainAxisSize: MainAxisSize.min, children: [
const Icon(Icons.check, size: 16).paddingLTRB(0, 0, 4, 0),
Text((widget.onSubmit == null)
? widget.submitDisabledText
: widget.submitText)
Text(networkReady
? widget.submitText
: widget.submitDisabledText)
.paddingLTRB(0, 0, 4, 0)
]),
)
);
}),
],
),
);

View File

@ -249,7 +249,7 @@ class SingleContactMessagesCubit extends Cubit<SingleContactMessagesState> {
void runCommand(String command) {
final (cmd, rest) = command.splitOnce(' ');
if (kDebugMode) {
if (kIsDebugMode) {
if (cmd == '/repeat' && rest != null) {
final (countStr, text) = rest.splitOnce(' ');
final count = int.tryParse(countStr);

View File

@ -1,3 +1,4 @@
import 'package:awesome_extensions/awesome_extensions.dart';
import 'package:flutter/material.dart';
import 'package:flutter_translate/flutter_translate.dart';
@ -15,7 +16,8 @@ class EmptyContactListWidget extends StatelessWidget {
final textTheme = theme.textTheme;
final scale = theme.extension<ScaleScheme>()!;
return Column(
return Expanded(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
@ -33,6 +35,6 @@ class EmptyContactListWidget extends StatelessWidget {
),
),
],
);
));
}
}

View File

@ -18,7 +18,7 @@ class VeilidChatGlobalInit {
await getDefaultVeilidPlatformConfig(kIsWeb, VeilidChatApp.name));
// Veilid logging
initVeilidLog(kDebugMode);
initVeilidLog(kIsDebugMode);
// Startup Veilid
await ProcessorRepository.instance.startup();

View File

@ -134,7 +134,7 @@ class RouterCubit extends Cubit<RouterState> {
return _router = GoRouter(
navigatorKey: _rootNavKey,
refreshListenable: StreamListenable(stream.startWith(state).distinct()),
debugLogDiagnostics: kDebugMode,
debugLogDiagnostics: kIsDebugMode,
initialLocation: '/',
routes: routes,
redirect: redirect,

View File

@ -246,7 +246,7 @@ Future<bool> showConfirmModal(
Navigator.pop(context);
},
child: Text(
translate('button.no_cancel'),
translate('button.no'),
style: _buttonTextStyle(context),
),
),
@ -261,7 +261,7 @@ Future<bool> showConfirmModal(
Navigator.pop(context);
},
child: Text(
translate('button.yes_proceed'),
translate('button.yes'),
style: _buttonTextStyle(context),
),
)

View File

@ -152,7 +152,7 @@ void initLoggy() {
if (isTrace) {
logLevel = traceLevel;
} else {
logLevel = kDebugMode ? LogLevel.debug : LogLevel.info;
logLevel = kIsDebugMode ? LogLevel.debug : LogLevel.info;
}
Loggy('').level = getLogOptions(logLevel);

View File

@ -305,10 +305,10 @@ class DHTLog implements DHTDeleteable<DHTLog> {
// Openable
int _openCount;
final _mutex = Mutex();
final _mutex = Mutex(debugLockTimeout: kIsDebugMode ? 60 : null);
// Watch mutex to ensure we keep the representation valid
final Mutex _listenMutex = Mutex();
final Mutex _listenMutex = Mutex(debugLockTimeout: kIsDebugMode ? 60 : null);
// Stream of external changes
StreamController<DHTLogUpdate>? _watchController;
}

View File

@ -713,7 +713,7 @@ class _DHTLogSpine {
DHTShortArray.maxElements;
// Spine head mutex to ensure we keep the representation valid
final Mutex _spineMutex = Mutex();
final Mutex _spineMutex = Mutex(debugLockTimeout: kIsDebugMode ? 60 : null);
// Subscription to head record internal changes
StreamSubscription<DHTRecordWatchChange>? _subscription;
// Notify closure for external spine head changes
@ -733,7 +733,8 @@ class _DHTLogSpine {
// LRU cache of DHT spine elements accessed recently
// Pair of position and associated shortarray segment
final Mutex _spineCacheMutex = Mutex();
final Mutex _spineCacheMutex =
Mutex(debugLockTimeout: kIsDebugMode ? 60 : null);
final List<int> _openCache;
final Map<int, DHTShortArray> _openedSegments;
static const int _openCacheSize = 3;

View File

@ -562,7 +562,7 @@ class DHTRecord implements DHTDeleteable<DHTRecord> {
final KeyPair? _writer;
final VeilidCrypto _crypto;
final String debugName;
final _mutex = Mutex();
final _mutex = Mutex(debugLockTimeout: kIsDebugMode ? 60 : null);
int _openCount;
StreamController<DHTRecordWatchChange>? _watchController;
_WatchState? _watchState;

View File

@ -65,7 +65,7 @@ class OwnedDHTRecordPointer with _$OwnedDHTRecordPointer {
class DHTRecordPool with TableDBBackedJson<DHTRecordPoolAllocations> {
DHTRecordPool._(Veilid veilid, VeilidRoutingContext routingContext)
: _state = const DHTRecordPoolAllocations(),
_mutex = Mutex(debugLockTimeout: 30),
_mutex = Mutex(debugLockTimeout: kIsDebugMode ? 60 : null),
_recordTagLock = AsyncTagLock(),
_opened = <TypedKey, _OpenedRecordInfo>{},
_markedForDelete = <TypedKey>{},
@ -835,9 +835,11 @@ class DHTRecordPool with TableDBBackedJson<DHTRecordPoolAllocations> {
openedRecordInfo.shared.unionWatchState = null;
openedRecordInfo.shared.needsWatchStateUpdate = false;
} on VeilidAPIExceptionTimeout {
log('Timeout in watch cancel for key=$openedRecordKey');
} on VeilidAPIException catch (e) {
// Failed to cancel DHT watch, try again next tick
log('Exception in watch cancel: $e');
log('Exception in watch cancel for key=$openedRecordKey: $e');
}
return;
}
@ -877,12 +879,22 @@ class DHTRecordPool with TableDBBackedJson<DHTRecordPoolAllocations> {
openedRecordInfo.records, realExpiration, renewalTime);
openedRecordInfo.shared.needsWatchStateUpdate = false;
}
} on VeilidAPIExceptionTimeout {
log('Timeout in watch update for key=$openedRecordKey');
} on VeilidAPIException catch (e) {
// Failed to update DHT watch, try again next tick
log('Exception in watch update: $e');
log('Exception in watch update for key=$openedRecordKey: $e');
}
// If we still need a state update after this then do a poll instead
if (openedRecordInfo.shared.needsWatchStateUpdate) {
_pollWatch(openedRecordKey, openedRecordInfo, unionWatchState);
}
}
// In lieu of a completed watch, set off a polling operation
// on the first value of the watched range, which, due to current
// veilid limitations can only be one subkey at a time right now
void _pollWatch(TypedKey openedRecordKey, _OpenedRecordInfo openedRecordInfo,
_WatchState unionWatchState) {
singleFuture((this, _sfPollWatch, openedRecordKey), () async {
@ -942,18 +954,11 @@ class DHTRecordPool with TableDBBackedJson<DHTRecordPoolAllocations> {
final unionWatchState =
_collectUnionWatchState(openedRecordInfo.records);
final processed = _watchStateProcessors.updateState(
_watchStateProcessors.updateState(
openedRecordKey,
unionWatchState,
(newState) =>
_watchStateChange(openedRecordKey, unionWatchState));
// In lieu of a completed watch, set off a polling operation
// on the first value of the watched range, which, due to current
// veilid limitations can only be one subkey at a time right now
if (!processed && unionWatchState != null) {
_pollWatch(openedRecordKey, openedRecordInfo, unionWatchState);
}
}
}
});

View File

@ -289,10 +289,10 @@ class DHTShortArray implements DHTDeleteable<DHTShortArray> {
// Openable
int _openCount;
final _mutex = Mutex();
final _mutex = Mutex(debugLockTimeout: kIsDebugMode ? 60 : null);
// Watch mutex to ensure we keep the representation valid
final Mutex _listenMutex = Mutex();
final Mutex _listenMutex = Mutex(debugLockTimeout: kIsDebugMode ? 60 : null);
// Stream of external changes
StreamController<void>? _watchController;
}

View File

@ -518,7 +518,7 @@ class _DHTShortArrayHead {
////////////////////////////////////////////////////////////////////////////
// Head/element mutex to ensure we keep the representation valid
final Mutex _headMutex = Mutex();
final Mutex _headMutex = Mutex(debugLockTimeout: kIsDebugMode ? 60 : null);
// Subscription to head record internal changes
StreamSubscription<DHTRecordWatchChange>? _subscription;
// Notify closure for external head changes

View File

@ -4,6 +4,7 @@ import 'package:async_tools/async_tools.dart';
import 'package:bloc/bloc.dart';
import 'package:meta/meta.dart';
import 'config.dart';
import 'table_db.dart';
abstract class AsyncTableDBBackedCubit<T> extends Cubit<AsyncValue<T?>>
@ -45,5 +46,5 @@ abstract class AsyncTableDBBackedCubit<T> extends Cubit<AsyncValue<T?>>
}
final WaitSet<void, void> _initWait = WaitSet();
final Mutex _mutex = Mutex();
final Mutex _mutex = Mutex(debugLockTimeout: kIsDebugMode ? 60 : null);
}

View File

@ -5,10 +5,10 @@ import 'package:path_provider/path_provider.dart';
import 'package:veilid/veilid.dart';
// ignore: do_not_use_environment
const bool _kReleaseMode = bool.fromEnvironment('dart.vm.product');
const bool kIsReleaseMode = bool.fromEnvironment('dart.vm.product');
// ignore: do_not_use_environment
const bool _kProfileMode = bool.fromEnvironment('dart.vm.profile');
const bool _kDebugMode = !_kReleaseMode && !_kProfileMode;
const bool kIsProfileMode = bool.fromEnvironment('dart.vm.profile');
const bool kIsDebugMode = !kIsReleaseMode && !kIsProfileMode;
Future<Map<String, dynamic>> getDefaultVeilidPlatformConfig(
bool isWeb, String appName) async {
@ -34,7 +34,7 @@ Future<Map<String, dynamic>> getDefaultVeilidPlatformConfig(
logging: VeilidWASMConfigLogging(
performance: VeilidWASMConfigLoggingPerformance(
enabled: true,
level: _kDebugMode
level: kIsDebugMode
? VeilidConfigLogLevel.debug
: VeilidConfigLogLevel.info,
logsInTimings: true,
@ -50,8 +50,8 @@ Future<Map<String, dynamic>> getDefaultVeilidPlatformConfig(
logging: VeilidFFIConfigLogging(
terminal: VeilidFFIConfigLoggingTerminal(
enabled:
_kDebugMode && (Platform.isIOS || Platform.isAndroid),
level: _kDebugMode
kIsDebugMode && (Platform.isIOS || Platform.isAndroid),
level: kIsDebugMode
? VeilidConfigLogLevel.debug
: VeilidConfigLogLevel.info,
ignoreLogTargets: ignoreLogTargets),

View File

@ -5,6 +5,7 @@ import 'package:async_tools/async_tools.dart';
import 'package:fast_immutable_collections/fast_immutable_collections.dart';
import 'package:protobuf/protobuf.dart';
import 'config.dart';
import 'table_db.dart';
class PersistentQueue<T extends GeneratedMessage>
@ -203,7 +204,7 @@ class PersistentQueue<T extends GeneratedMessage>
final T Function(Uint8List) _fromBuffer;
final bool _deleteOnClose;
final WaitSet<void, void> _initWait = WaitSet();
final Mutex _queueMutex = Mutex();
final Mutex _queueMutex = Mutex(debugLockTimeout: kIsDebugMode ? 60 : null);
IList<T> _queue = IList<T>.empty();
final StreamController<Iterable<T>> _syncAddController = StreamController();
final StreamController<void> _queueReady = StreamController();

View File

@ -614,7 +614,7 @@ class _TableDBArrayBase {
var _initDone = false;
final VeilidCrypto _crypto;
final WaitSet<void, void> _initWait = WaitSet();
final Mutex _mutex = Mutex();
final Mutex _mutex = Mutex(debugLockTimeout: kIsDebugMode ? 60 : null);
// Change tracking
int _headDelta = 0;

View File

@ -37,10 +37,10 @@ packages:
dependency: "direct main"
description:
name: async_tools
sha256: "93df8b92d54d92e3323c630277e902b4ad4f05f798b55cfbc451e98c3e2fb7ba"
sha256: bbded696bfcb1437d0ca510ac047f261f9c7494fea2c488dd32ba2800e7f49e8
url: "https://pub.dev"
source: hosted
version: "0.1.6"
version: "0.1.7"
bloc:
dependency: "direct main"
description:
@ -53,10 +53,10 @@ packages:
dependency: "direct main"
description:
name: bloc_advanced_tools
sha256: f0b2dbe028792c97d1eb30480ed4e8035b5c70ea3bcc95a9c5255142592857f7
sha256: d8a680d8a0469456399fb26bae9f7a1d2a1420b5bdf75e204e0fadab9edb0811
url: "https://pub.dev"
source: hosted
version: "0.1.7"
version: "0.1.8"
boolean_selector:
dependency: transitive
description:

View File

@ -7,9 +7,9 @@ environment:
sdk: '>=3.2.0 <4.0.0'
dependencies:
async_tools: ^0.1.6
async_tools: ^0.1.7
bloc: ^8.1.4
bloc_advanced_tools: ^0.1.7
bloc_advanced_tools: ^0.1.8
charcode: ^1.3.1
collection: ^1.18.0
equatable: ^2.0.5

View File

@ -85,10 +85,10 @@ packages:
dependency: "direct main"
description:
name: async_tools
sha256: "93df8b92d54d92e3323c630277e902b4ad4f05f798b55cfbc451e98c3e2fb7ba"
sha256: bbded696bfcb1437d0ca510ac047f261f9c7494fea2c488dd32ba2800e7f49e8
url: "https://pub.dev"
source: hosted
version: "0.1.6"
version: "0.1.7"
awesome_extensions:
dependency: "direct main"
description:
@ -141,10 +141,10 @@ packages:
dependency: "direct main"
description:
name: bloc_advanced_tools
sha256: f0b2dbe028792c97d1eb30480ed4e8035b5c70ea3bcc95a9c5255142592857f7
sha256: d8a680d8a0469456399fb26bae9f7a1d2a1420b5bdf75e204e0fadab9edb0811
url: "https://pub.dev"
source: hosted
version: "0.1.7"
version: "0.1.8"
blurry_modal_progress_hud:
dependency: "direct main"
description:

View File

@ -14,12 +14,12 @@ dependencies:
animated_theme_switcher: ^2.0.10
ansicolor: ^2.0.2
archive: ^3.6.1
async_tools: ^0.1.6
async_tools: ^0.1.7
awesome_extensions: ^2.0.16
badges: ^3.1.2
basic_utils: ^5.7.0
bloc: ^8.1.4
bloc_advanced_tools: ^0.1.7
bloc_advanced_tools: ^0.1.8
blurry_modal_progress_hud: ^1.1.1
change_case: ^2.1.0
charcode: ^1.3.1