diff --git a/apps/ssb.json b/apps/ssb.json
index c4846f48..52a95833 100644
--- a/apps/ssb.json
+++ b/apps/ssb.json
@@ -1,5 +1,5 @@
{
"type": "tildefriends-app",
"emoji": "🦀",
- "previous": "&Qae0CxJGEH7OspuapuXX/GurmV+VBtQiMhHRmCBKCwU=.sha256"
+ "previous": "&wOd/+1l5wpywBlfxC1Lm0i+HhYidrgSfrn9LRX7qy2w=.sha256"
}
diff --git a/apps/ssb/tf-tab-connections.js b/apps/ssb/tf-tab-connections.js
index ee9f6982..51058a3d 100644
--- a/apps/ssb/tf-tab-connections.js
+++ b/apps/ssb/tf-tab-connections.js
@@ -103,6 +103,21 @@ class TfTabConnectionsElement extends LitElement {
`;
}
+ render_progress(name, value, max) {
+ if (max && value != max) {
+ return html`
+
+
+ ${name} ${value} / ${max} (${Math.round((100.0 * value) / max)}%)
+
+
+ `;
+ }
+ }
+
render_broadcast(connection) {
let self = this;
return html`
@@ -154,6 +169,16 @@ class TfTabConnectionsElement extends LitElement {
: undefined}
${connection.flags.one_shot ? '🔃' : undefined}
+ ${this.render_progress(
+ 'recv',
+ connection.progress.in.total - connection.progress.in.current,
+ connection.progress.in.total
+ )}
+ ${this.render_progress(
+ 'send',
+ connection.progress.out.total - connection.progress.out.current,
+ connection.progress.out.total
+ )}
${connection.tunnel !== undefined
? '🚇'
: html`(${connection.host}:${connection.port})`}
diff --git a/src/ssb.ebt.c b/src/ssb.ebt.c
index 3dc8948d..1b03d8c6 100644
--- a/src/ssb.ebt.c
+++ b/src/ssb.ebt.c
@@ -30,6 +30,9 @@ typedef struct _tf_ssb_ebt_t
int entries_count;
int send_clock_pending;
+
+ int max_in;
+ int max_out;
} tf_ssb_ebt_t;
tf_ssb_ebt_t* tf_ssb_ebt_create(tf_ssb_connection_t* connection)
@@ -56,6 +59,25 @@ static int _ebt_entry_compare(const void* a, const void* b)
return strcmp(id, entry->id);
}
+static void _ebt_count_messages(tf_ssb_ebt_t* ebt, int* in, int* out)
+{
+ for (int i = 0; i < ebt->entries_count; i++)
+ {
+ ebt_entry_t* entry = &ebt->entries[i];
+ if (entry->in >= 0 && entry->out >= 0)
+ {
+ if (entry->in > entry->out)
+ {
+ *in += entry->in - entry->out;
+ }
+ else if (entry->out > entry->in)
+ {
+ *out += entry->out - entry->in;
+ }
+ }
+ }
+}
+
static ebt_entry_t* _ebt_get_entry(tf_ssb_ebt_t* ebt, const char* id)
{
uint8_t bin[k_id_bin_len];
@@ -135,6 +157,13 @@ void tf_ssb_ebt_receive_clock(tf_ssb_ebt_t* ebt, JSContext* context, JSValue clo
}
JS_FreeValue(context, in_clock);
}
+
+ int in = 0;
+ int out = 0;
+ _ebt_count_messages(ebt, &in, &out);
+ ebt->max_in = tf_max(in, ebt->max_in);
+ ebt->max_out = tf_max(out, ebt->max_out);
+
uv_mutex_unlock(&ebt->mutex);
for (uint32_t i = 0; i < plen; ++i)
{
@@ -164,29 +193,32 @@ static void _ebt_add_to_clock(ebt_get_clock_t* work, const char* id, int64_t val
{
int count = work->clock ? work->clock->count : 0;
ebt_entry_t* entry = _ebt_get_entry(work->ebt, id);
- if (entry &&
- ((replicate && !entry->out_replicate) || (receive && !entry->out_receive) || ((replicate || receive || entry->out_replicate || entry->out_receive) && entry->out != value)))
+ if (entry)
{
entry->out = value;
entry->out_replicate = entry->out_replicate || replicate;
entry->out_receive = entry->out_receive || receive;
- int index = tf_util_insert_index(id, count ? work->clock->entries : NULL, count, sizeof(tf_ssb_ebt_clock_entry_t), _ebt_compare_entry);
- int64_t out_value = entry->out_replicate ? ((value << 1) | (entry->out_receive ? 0 : 1)) : -1;
- if (index < count && strcmp(id, work->clock->entries[index].id) == 0)
+ if ((replicate && !entry->out_replicate) || (receive && !entry->out_receive) ||
+ ((replicate || receive || entry->out_replicate || entry->out_receive) && entry->out != value))
{
- work->clock->entries[index].value = out_value;
- }
- else
- {
- work->clock = tf_resize_vec(work->clock, sizeof(tf_ssb_ebt_clock_t) + (count + 1) * sizeof(tf_ssb_ebt_clock_entry_t));
- if (index < count)
+ int index = tf_util_insert_index(id, count ? work->clock->entries : NULL, count, sizeof(tf_ssb_ebt_clock_entry_t), _ebt_compare_entry);
+ int64_t out_value = entry->out_replicate ? ((value << 1) | (entry->out_receive ? 0 : 1)) : -1;
+ if (index < count && strcmp(id, work->clock->entries[index].id) == 0)
{
- memmove(work->clock->entries + index + 1, work->clock->entries + index, (count - index) * sizeof(tf_ssb_ebt_clock_entry_t));
+ work->clock->entries[index].value = out_value;
+ }
+ else
+ {
+ work->clock = tf_resize_vec(work->clock, sizeof(tf_ssb_ebt_clock_t) + (count + 1) * sizeof(tf_ssb_ebt_clock_entry_t));
+ if (index < count)
+ {
+ memmove(work->clock->entries + index + 1, work->clock->entries + index, (count - index) * sizeof(tf_ssb_ebt_clock_entry_t));
+ }
+ work->clock->entries[index] = (tf_ssb_ebt_clock_entry_t) { .value = out_value };
+ snprintf(work->clock->entries[index].id, sizeof(work->clock->entries[index].id), "%s", id);
+ work->clock->count = count + 1;
}
- work->clock->entries[index] = (tf_ssb_ebt_clock_entry_t) { .value = out_value };
- snprintf(work->clock->entries[index].id, sizeof(work->clock->entries[index].id), "%s", id);
- work->clock->count = count + 1;
}
}
}
@@ -268,6 +300,14 @@ static void _tf_ssb_ebt_get_send_clock_work(tf_ssb_connection_t* connection, voi
uv_mutex_unlock(&work->ebt->mutex);
tf_free(requested);
}
+
+ uv_mutex_lock(&work->ebt->mutex);
+ int in = 0;
+ int out = 0;
+ _ebt_count_messages(work->ebt, &in, &out);
+ work->ebt->max_in = tf_max(in, work->ebt->max_in);
+ work->ebt->max_out = tf_max(out, work->ebt->max_out);
+ uv_mutex_unlock(&work->ebt->mutex);
}
static void _tf_ssb_ebt_get_send_clock_after_work(tf_ssb_connection_t* connection, int status, void* user_data)
@@ -356,3 +396,12 @@ void tf_ssb_ebt_debug_clock(tf_ssb_ebt_t* ebt, JSContext* context, JSValue debug
}
uv_mutex_unlock(&ebt->mutex);
}
+
+void tf_ssb_ebt_get_progress(tf_ssb_ebt_t* ebt, int* in_pending, int* in_total, int* out_pending, int* out_total)
+{
+ uv_mutex_lock(&ebt->mutex);
+ _ebt_count_messages(ebt, in_pending, out_pending);
+ *in_total = ebt->max_in;
+ *out_total = ebt->max_out;
+ uv_mutex_unlock(&ebt->mutex);
+}
diff --git a/src/ssb.ebt.h b/src/ssb.ebt.h
index 16e0038e..3b87d354 100644
--- a/src/ssb.ebt.h
+++ b/src/ssb.ebt.h
@@ -106,3 +106,13 @@ void tf_ssb_ebt_set_send_clock_pending(tf_ssb_ebt_t* ebt, int pending);
** @param debug A JS object populated with the information.
*/
void tf_ssb_ebt_debug_clock(tf_ssb_ebt_t* ebt, JSContext* context, JSValue debug);
+
+/**
+** Get a representation of sync progress.
+** @param ebt The EBT instance.
+** @param in_pending Populated with the number of messages remaining to be received.
+** @param in_total Populated with the total number of messages to receive this session.
+** @param out_pending Populated with the number of messages remaining to send.
+** @param out_total Populated with the total number of messages to send this session.
+*/
+void tf_ssb_ebt_get_progress(tf_ssb_ebt_t* ebt, int* in_pending, int* in_total, int* out_pending, int* out_total);
diff --git a/src/ssb.js.c b/src/ssb.js.c
index dfcf8bb3..0b918e9a 100644
--- a/src/ssb.js.c
+++ b/src/ssb.js.c
@@ -3,6 +3,7 @@
#include "log.h"
#include "mem.h"
#include "ssb.db.h"
+#include "ssb.ebt.h"
#include "ssb.h"
#include "util.js.h"
@@ -942,6 +943,21 @@ static JSValue _tf_ssb_connections(JSContext* context, JSValueConst this_val, in
{
JS_SetPropertyStr(context, object, "destroy_reason", JS_NewString(context, destroy_reason));
}
+ int in = 0;
+ int out = 0;
+ int max_in = 0;
+ int max_out = 0;
+ tf_ssb_ebt_get_progress(tf_ssb_connection_get_ebt(connection), &in, &max_in, &out, &max_out);
+ JSValue progress = JS_NewObject(context);
+ JSValue in_progress = JS_NewObject(context);
+ JS_SetPropertyStr(context, in_progress, "current", JS_NewInt32(context, in));
+ JS_SetPropertyStr(context, in_progress, "total", JS_NewInt32(context, max_in));
+ JS_SetPropertyStr(context, progress, "in", in_progress);
+ JSValue out_progress = JS_NewObject(context);
+ JS_SetPropertyStr(context, out_progress, "current", JS_NewInt32(context, out));
+ JS_SetPropertyStr(context, out_progress, "total", JS_NewInt32(context, max_out));
+ JS_SetPropertyStr(context, progress, "out", out_progress);
+ JS_SetPropertyStr(context, object, "progress", progress);
JS_SetPropertyUint32(context, result, i, object);
}
}