+ resulting_limit = (uint32_t) (ident->limit / (ident->comm.remote_node_count + 1));
+ }
+
+ print_statistics(ident, ideal_weight, total_weight, ident->localweight,
+ identifier, table, resulting_limit);
+
+ return resulting_limit;
+}
+
+#ifdef SHADOW_ACCTING
+
+/* Runs through the allocate functionality without making any state changes to
+ * the identity. Useful for comparisons, especially for comparing standard
+ * and sample&hold accounting schemes. */
+static void allocate_fps_pretend(identity_t *ident, double total_weight,
+ common_accounting_t *table, const char *identifier) {
+
+ uint32_t resulting_limit = 0;
+ double ideal_weight = 0.0;
+ double peer_weights = total_weight - ident->last_localweight_copy;
+ double ideal_under = 0.0;
+ double ideal_over = 0.0;
+
+ if (peer_weights < 0.0) {
+ peer_weights = 0.0;
+ }
+
+ if (ident->dampen_state_copy == DAMPEN_TEST) {
+ int64_t rate_delta = (int64_t) table->inst_rate - (int64_t) table->last_inst_rate;
+ double threshold = (double) ident->effective_limit * (double) LARGE_INCREASE_PERCENTAGE / 10;
+
+ if (rate_delta > threshold) {
+ ident->dampen_state_copy = DAMPEN_PASSED;
+ } else {
+ ident->dampen_state_copy = DAMPEN_FAILED;
+ }
+ }
+
+ /* Rate/weight sanity. */
+ if (table->rate <= 0) {
+ ideal_weight = 0.0;
+ }
+
+ /* Under the limit OR we failed our dampening test OR our current
+ * outgoing traffic rate is under the low "flowstart" watermark. */
+ else if (ident->dampen_state_copy == DAMPEN_FAILED ||
+ table->rate < close_enough(ident->locallimit)) {
+
+ /* Boost low-limits so that they have room to grow. */
+ if (table->rate < FLOW_START_THRESHOLD) {
+ ideal_weight = ideal_under = allocate_fps_under_limit(ident, table->rate * 4, peer_weights);
+ } else {
+ ideal_weight = ideal_under = allocate_fps_under_limit(ident, table->rate, peer_weights);
+ }
+
+ ideal_over = allocate_fps_over_limit(ident);
+
+ if (ideal_over < ideal_under) {
+ /* Degenerate case in which the agressive weight calculation was
+ * actually less than the under-the-limit case. Use it instead
+ * and skip the dampening check in the next interval. */
+ ideal_weight = ideal_over;
+ ident->dampen_state_copy = DAMPEN_SKIP;
+ } else {
+ ident->dampen_state_copy = DAMPEN_NONE;
+ }
+
+ /* Apply EWMA. */
+ ident->localweight_copy = (ident->localweight_copy * ident->ewma_weight +
+ ideal_weight * (1 - ident->ewma_weight));