Preserve Android standby retry waits and clarify history contracts
This commit is contained in:
1 parent
0444a4bfd9
commit
fefc0ee003
3 files changed
+29
-11
No files matched your search
@@ -13,6 +13,9 @@
|
||||
#include "../../lib/mem.h"
|
||||
#include "../../lib/u_async.h"
|
||||
#include "../../lib/platform_compat.h"
|
||||
#ifdef UTUN_HAVE_STANDBY
|
||||
#include "standby.h"
|
||||
#endif
|
||||
#include <openssl/evp.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -65,6 +68,9 @@ struct DB_SYNC {
|
||||
struct DB_SYNC_INSTANCE** instances;
|
||||
int instance_count, instance_capacity;
|
||||
void* peer_check_timer;
|
||||
#ifdef UTUN_HAVE_STANDBY
|
||||
void* peer_check_wait; /* Отменяемое ожидание активной фазы Android. */
|
||||
#endif
|
||||
struct db_sync_done_cbk_entry* done_cbks;
|
||||
unsigned dispatch_depth;
|
||||
struct db_notice* notices;
|
||||
@@ -932,12 +938,26 @@ schedule:
|
||||
|
||||
static void db_sync_resume_peer_check(struct DB_SYNC* db) {
|
||||
if (!db || !db->enabled || db->peer_check_timer) return;
|
||||
#ifdef UTUN_HAVE_STANDBY
|
||||
if (db->peer_check_wait) return;
|
||||
#endif
|
||||
db->peer_check_timer = uasync_set_timeout(db->inst->ua, DB_SYNC_PEER_CHECK_INTERVAL * 10000ULL, db, db_sync_peer_check_cb, "history_retry");
|
||||
if (!db->peer_check_timer) DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "history retry timer allocation");
|
||||
}
|
||||
static void db_sync_peer_check_cb(void* arg) {
|
||||
struct DB_SYNC* db = arg; db->peer_check_timer = NULL; int pending = 0;
|
||||
if (!db->enabled) return;
|
||||
#ifdef UTUN_HAVE_STANDBY
|
||||
db->peer_check_wait = NULL;
|
||||
if (standby_get_sleep_tb() > 0) {
|
||||
db->peer_check_wait = standby_wait(db, db_sync_peer_check_cb);
|
||||
if (!db->peer_check_wait) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_CHAT_SYNC, "history standby wait allocation; retry later");
|
||||
db_sync_resume_peer_check(db);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
for (int i = 0; i < db->instance_count; i++) {
|
||||
struct DB_SYNC_INSTANCE* si = db->instances[i];
|
||||
if (si->index.pending) {
|
||||
@@ -1048,6 +1068,9 @@ void db_sync_destroy(struct UTUN_INSTANCE* inst) {
|
||||
if (!db) return;
|
||||
db->enabled = 0;
|
||||
if (db->peer_check_timer) uasync_cancel_timeout(inst->ua, db->peer_check_timer);
|
||||
#ifdef UTUN_HAVE_STANDBY
|
||||
if (db->peer_check_wait) standby_wait_cancel(db->peer_check_wait);
|
||||
#endif
|
||||
while (db->instance_count) db_sync_instance_remove(db->instances[db->instance_count - 1]);
|
||||
while (db->notices) db_notice_abort(db->notices);
|
||||
while (db->done_cbks) {
|
||||
|
||||
+3
-9
@@ -30,19 +30,13 @@ struct DB_SYNC_INSTANCE;
|
||||
// PUSH и записи MESSAGES: [message_id:32][ts:8BE][author:8BE][dlen:4BE][data][sig:64].
|
||||
// ACK_PUSH wire: [message_id:32]. Подтверждает конкретную запись; повторы идемпотентны.
|
||||
|
||||
// Defaults
|
||||
#define DB_SYNC_DEFAULT_TTL 86400
|
||||
#define DB_SYNC_DEFAULT_MAPSIZE (100UL * 1024 * 1024)
|
||||
// Интервалы служебных таймеров в секундах.
|
||||
#define DB_SYNC_PEER_CHECK_INTERVAL 5
|
||||
#define DB_SYNC_SYNC_TIMEOUT 15
|
||||
#define DB_SYNC_TTL_INTERVAL 3600
|
||||
|
||||
// Record flags
|
||||
#define DB_REC_FLAG_WAS_SENT 0x01
|
||||
|
||||
// Sync protocol constants
|
||||
#define DB_SEND_DATA_MAX 32
|
||||
|
||||
// Ed25519 signature size
|
||||
#define DB_SIG_SIZE 64
|
||||
|
||||
@@ -91,8 +85,8 @@ int db_sync_select(struct DB_SYNC_INSTANCE* si, uint32_t offset, uint32_t l
|
||||
|
||||
// Insert callback: fired after local or peer insert succeeds.
|
||||
// author_node_id — исходный автор записи, не обязательно переславший её пир.
|
||||
// initial_sync = 1 если запись пришла в рамках bulk-обмена SEND_DATA (initial/re-sync),
|
||||
// 0 для live-PUSH и локальных вставок.
|
||||
// initial_sync = 1 для страницы MESSAGES, 0 для live-PUSH и локальной вставки.
|
||||
// Вызов после commit: для страниц отложен до выхода из обработчика Merkle.
|
||||
typedef void (*db_sync_insert_cb)(struct DB_SYNC_INSTANCE* si,
|
||||
const uint8_t message_id[32],
|
||||
uint64_t record_timestamp,
|
||||
|
||||
@@ -46,7 +46,7 @@ struct merkle_sync_data_ops {
|
||||
/* Немедленный атомарный приём с проверкой границ листа/курсора; при наличии заменяет apply_items. */
|
||||
int (*apply_page)(void* ctx, const char* ns, uint64_t peer, uint64_t prefix, int after_valid,
|
||||
const merkle_key_t* after, const merkle_key_t* next, int more, const uint8_t* data, size_t len);
|
||||
int (*validate_peer)(void* ctx, const char* ns, uint64_t peer); // необязательная проверка: только 1 разрешает приём
|
||||
int (*validate_peer)(void* ctx, const char* ns, uint64_t peer); // допуск пира: только 1 разрешает обмен
|
||||
/* Политика работы (например sleep/sound), 1 разрешает обмен; без callback спящий пир отложен. */
|
||||
int (*can_run)(void* ctx, const char* ns, uint64_t peer);
|
||||
/* Результат каждой контрольной точки/ошибки, включая автоматические раунды.
|
||||
@@ -88,7 +88,8 @@ void merkle_sync_destroy(struct UTUN_INSTANCE* inst);
|
||||
* Успех — подтверждение одинакового корня конкретного раунда, не вечный статус.
|
||||
* Повторные запросы объединяются; каждый callback вызывается один раз, обход не сбрасывается.
|
||||
* После первого start изменения дерева автоматически синхронизируются с этим пиром.
|
||||
* cb может быть NULL. Нужен доступный UP-пир, не self и не peer_sleep_phase.
|
||||
* cb может быть NULL. Нужен UP-пир, не self, с допуском validate_peer и can_run.
|
||||
* Без can_run обмен со спящим пиром откладывается.
|
||||
* <0: запрос не принят, callback не вызывается. DOWN/DELETE/REINIT завершают запросы ошибкой.
|
||||
* При блокировке исходящего пакета или ожидании ответа действует таймаут 30 секунд.
|
||||
* Явные cancel/destroy освобождают запросы без callback.
|
||||
|
||||
Reference in new issue
Block a user