commit c165435: [Minor] Forgot to add a file
Vsevolod Stakhov
vsevolod at rspamd.com
Sat Apr 30 19:21:20 UTC 2022
Author: Vsevolod Stakhov
Date: 2022-04-10 09:06:33 +0100
URL: https://github.com/rspamd/rspamd/commit/c1654354869b81db2a30dc02fef3d5b82b516c33
[Minor] Forgot to add a file
---
src/libserver/symcache/symcache_id_list.hxx | 154 ++++++++++++++++++++++++++++
1 file changed, 154 insertions(+)
diff --git a/src/libserver/symcache/symcache_id_list.hxx b/src/libserver/symcache/symcache_id_list.hxx
new file mode 100644
index 000000000..b42cb9183
--- /dev/null
+++ b/src/libserver/symcache/symcache_id_list.hxx
@@ -0,0 +1,154 @@
+/*-
+ * Copyright 2022 Vsevolod Stakhov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef RSPAMD_SYMCACHE_ID_LIST_HXX
+#define RSPAMD_SYMCACHE_ID_LIST_HXX
+#pragma once
+
+#include <cstdint>
+#include <cstring> // for memset
+#include <algorithm> // for sort
+
+#include "config.h"
+#include "libutil/mem_pool.h"
+
+namespace rspamd::symcache {
+/*
+ * This structure is optimised to store ids list:
+ * - If the first element is -1 then use dynamic part, else use static part
+ * There is no std::variant to save space
+ */
+struct id_list {
+ union {
+ std::uint32_t st[4];
+ struct {
+ std::uint32_t e; /* First element */
+ std::uint16_t len;
+ std::uint16_t allocated;
+ std::uint32_t *n;
+ } dyn;
+ } data;
+
+ id_list() = default;
+ auto reset() {
+ std::memset(&data, 0, sizeof(data));
+ }
+
+ /**
+ * Returns ids from a compressed list, accepting a mutable reference for number of elements
+ * @param nids output of the number of elements
+ * @return
+ */
+ auto get_ids(std::size_t &nids) const -> const std::uint32_t *
+ {
+ if (data.dyn.e == -1) {
+ /* Dynamic list */
+ nids = data.dyn.len;
+
+ return data.dyn.n;
+ }
+ else {
+ auto cnt = 0;
+
+ while (data.st[cnt] != 0 && cnt < G_N_ELEMENTS(data.st)) {
+ cnt++;
+ }
+
+ nids = cnt;
+
+ return data.st;
+ }
+ }
+
+ auto add_id(std::uint32_t id, rspamd_mempool_t *pool) -> void
+ {
+ if (data.st[0] == -1) {
+ /* Dynamic array */
+ if (data.dyn.len < data.dyn.allocated) {
+ /* Trivial, append + sort */
+ data.dyn.n[data.dyn.len++] = id;
+ }
+ else {
+ /* Reallocate */
+ g_assert(data.dyn.allocated <= G_MAXINT16);
+ data.dyn.allocated *= 2;
+
+ auto *new_array = rspamd_mempool_alloc_array_type(pool,
+ data.dyn.allocated, std::uint32_t);
+ memcpy(new_array, data.dyn.n, data.dyn.len * sizeof(std::uint32_t));
+ data.dyn.n = new_array;
+ data.dyn.n[data.dyn.len++] = id;
+ }
+
+ std::sort(data.dyn.n, data.dyn.n + data.dyn.len);
+ }
+ else {
+ /* Static part */
+ auto cnt = 0u;
+ while (data.st[cnt] != 0 && cnt < G_N_ELEMENTS(data.st)) {
+ cnt++;
+ }
+
+ if (cnt < G_N_ELEMENTS(data.st)) {
+ data.st[cnt] = id;
+ }
+ else {
+ /* Switch to dynamic */
+ data.dyn.allocated = G_N_ELEMENTS(data.st) * 2;
+ auto *new_array = rspamd_mempool_alloc_array_type(pool,
+ data.dyn.allocated, std::uint32_t);
+ memcpy(new_array, data.st, sizeof(data.st));
+ data.dyn.n = new_array;
+ data.dyn.e = -1; /* Marker */
+ data.dyn.len = G_N_ELEMENTS(data.st);
+
+ /* Recursively jump to dynamic branch that will handle insertion + sorting */
+ add_id(id, pool); // tail call
+ }
+ }
+ }
+
+ auto set_ids(const std::uint32_t *ids, std::size_t nids, rspamd_mempool_t *pool) -> void {
+ if (nids <= G_N_ELEMENTS(data.st)) {
+ /* Use static version */
+ reset();
+
+ for (auto i = 0; i < nids; i++) {
+ data.st[i] = ids[i];
+ }
+ }
+ else {
+ /* Need to use a separate list */
+ data.dyn.e = -1; /* Flag */
+ data.dyn.n = rspamd_mempool_alloc_array_type(pool, nids, std::uint32_t);
+ data.dyn.len = nids;
+ data.dyn.allocated = nids;
+
+ for (auto i = 0; i < nids; i++) {
+ data.dyn.n[i] = ids[i];
+ }
+
+ /* Keep sorted */
+ std::sort(data.dyn.n, data.dyn.n + data.dyn.len);
+ }
+ }
+};
+
+static_assert(std::is_trivial_v<id_list>);
+
+}
+
+#endif //RSPAMD_SYMCACHE_ID_LIST_HXX
More information about the Commits
mailing list