-/* At least once per minute */
-#define PROFILE_MAX_TIME (60.0)
-/* For messages larger than 2Mb enable profiling */
-#define PROFILE_MESSAGE_SIZE_THRESHOLD (1024 * 1024 * 2)
-/* Enable profile at least once per this amount of messages processed */
-#define PROFILE_PROBABILITY (0.01)
-
/* weight, frequency, time */
#define TIME_ALPHA (1.0)
#define WEIGHT_ALPHA (0.1)
}
}
+auto symcache::maybe_resort() -> bool
+{
+ if (items_by_order->generation_id != cur_order_gen) {
+ /*
+ * Cache has been modified, need to resort it
+ */
+ msg_info_cache("symbols cache has been modified since last check:"
+ " old id: %ud, new id: %ud",
+ items_by_order->generation_id, cur_order_gen);
+ resort();
+
+ return true;
+ }
+
+ return false;
+}
+
}
\ No newline at end of file
lua_State *L;
double reload_time;
double last_profile;
+
+private:
int peak_cb;
int cache_id;
f(sym_it.second.get());
}
}
+
+ /**
+ * Resort cache if anything has been changed since last time
+ * @return
+ */
+ auto maybe_resort() -> bool;
+
+ /**
+ * Returns number of items with ids
+ * @return
+ */
+ auto get_items_count() const -> auto {
+ return items_by_id.size();
+ }
+
+ /**
+ * Returns current set of items ordered for sharing ownership
+ * @return
+ */
+ auto get_cache_order() const -> auto {
+ return items_by_order;
+ }
+
+ /**
+ * Get last profile timestamp
+ * @return
+ */
+ auto get_last_profile() const -> auto {
+ return last_profile;
+ }
+
+ /**
+ * Sets last profile timestamp
+ * @param last_profile
+ * @return
+ */
+ auto set_last_profile(double last_profile){
+ symcache::last_profile = last_profile;
+ }
};
namespace rspamd::symcache {
-auto cache_savepoint::create_savepoint(struct rspamd_task *task, const symcache &cache) -> cache_savepoint *
+/* At least once per minute */
+constexpr static const auto PROFILE_MAX_TIME = 60.0;
+/* For messages larger than 2Mb enable profiling */
+constexpr static const auto PROFILE_MESSAGE_SIZE_THRESHOLD = 1024ul * 1024 * 2;
+/* Enable profile at least once per this amount of messages processed */
+constexpr static const auto PROFILE_PROBABILITY = 0.01;
+
+auto
+cache_savepoint::create_savepoint(struct rspamd_task *task, symcache &cache) -> cache_savepoint *
{
- return nullptr;
+ struct cache_savepoint *checkpoint;
+
+ cache.maybe_resort();
+
+ checkpoint = (struct cache_savepoint *) rspamd_mempool_alloc0 (task->task_pool,
+ sizeof(*checkpoint) +
+ sizeof(struct cache_dynamic_item) * cache.get_items_count());
+
+ checkpoint->order = cache.get_cache_order();
+ rspamd_mempool_add_destructor(task->task_pool,
+ cache_savepoint::savepoint_dtor, checkpoint);
+
+ /* Calculate profile probability */
+ ev_now_update_if_cheap(task->event_loop);
+ ev_tstamp now = ev_now(task->event_loop);
+ checkpoint->profile_start = now;
+
+ if ((cache.get_last_profile() == 0.0 || now > cache.get_last_profile() + PROFILE_MAX_TIME) ||
+ (task->msg.len >= PROFILE_MESSAGE_SIZE_THRESHOLD) ||
+ (rspamd_random_double_fast() >= (1 - PROFILE_PROBABILITY))) {
+ msg_debug_cache_task("enable profiling of symbols for task");
+ checkpoint->profile = true;
+ cache.set_last_profile(now);
+ }
+
+ task->checkpoint = (void *)checkpoint;
+
+ return checkpoint;
}
}
static_assert(sizeof(cache_dynamic_item) == sizeof(std::uint64_t));
static_assert(std::is_trivial_v<cache_dynamic_item>);
-struct cache_savepoint {
- unsigned order_gen;
+class cache_savepoint {
unsigned items_inflight;
bool profile;
bool has_slow;
order_generation_ptr order;
/* Dynamically expanded as needed */
struct cache_dynamic_item dynamic_items[];
+ /* We allocate this structure merely in memory pool, so destructor is absent */
+ ~cache_savepoint() = delete;
+ /* Dropper for a shared ownership */
+ static auto savepoint_dtor(void *ptr) -> void {
+ auto *real_savepoint = (cache_savepoint *)ptr;
+ /* Drop shared ownership */
+ real_savepoint->order.reset();
+ }
public:
- static auto create_savepoint(struct rspamd_task *task, const symcache &cache) -> cache_savepoint *;
+ static auto create_savepoint(struct rspamd_task *task, symcache &cache) -> cache_savepoint *;
};