+ s->reply_backlog = jsonrpc_session_get_backlog(s->js);
+ } else if (backlog > s->reply_backlog + s->backlog_threshold) {
+ /* We have a lot of data queued to send to the client. The data is
+ * likely to be mostly monitor updates. It is unlikely that the
+ * monitor updates are due to transactions by 's', because we will not
+ * let 's' make any more transactions until it drains its backlog to 0
+ * (see previous 'if' case). So the monitor updates are probably due
+ * to transactions made by database clients other than 's'. We can't
+ * fix that by preventing 's' from executing more transactions. We
+ * could fix it by preventing every client from executing transactions,
+ * but then one slow or hung client could prevent other clients from
+ * doing useful work.
+ *
+ * Our solution is to cap the maximum backlog to O(1) in the amount of
+ * data in the database. If the backlog exceeds that amount, then we
+ * disconnect the client. When it reconnects, it can fetch the entire
+ * contents of the database using less data than was previously
+ * backlogged. */
+ size_t monitor_length;
+
+ monitor_length = ovsdb_jsonrpc_monitor_json_length_all(s);
+ if (backlog > s->reply_backlog + monitor_length * 2) {
+ VLOG_INFO("%s: %"PRIuSIZE" bytes backlogged but a complete replica "
+ "would only take %"PRIuSIZE" bytes, disconnecting",
+ jsonrpc_session_get_name(s->js),
+ backlog - s->reply_backlog, monitor_length);
+ jsonrpc_session_force_reconnect(s->js);
+ } else {
+ /* The backlog is not unreasonably big. Only check again after it
+ * becomes much bigger. */
+ s->backlog_threshold = 2 * MAX(s->backlog_threshold * 2,
+ monitor_length);
+ }