master
c 158 lines 4.66 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "windows-events-fields-cache.h"
4
5 typedef struct field_key {
6 uint64_t value;
7 ND_UUID provider;
8 } WEVT_FIELD_KEY;
9
10 typedef struct field_value {
11 WEVT_FIELD_KEY key;
12 uint32_t name_size;
13 char name[];
14 } WEVT_FIELD_VALUE;
15
16 #define SIMPLE_HASHTABLE_NAME _FIELDS_CACHE
17 #define SIMPLE_HASHTABLE_VALUE_TYPE WEVT_FIELD_VALUE *
18 #define SIMPLE_HASHTABLE_KEY_TYPE WEVT_FIELD_KEY
19 #define SIMPLE_HASHTABLE_VALUE2KEY_FUNCTION field_cache_value_to_key
20 #define SIMPLE_HASHTABLE_COMPARE_KEYS_FUNCTION field_cache_cache_compar
21 #define SIMPLE_HASHTABLE_SAMPLE_IMPLEMENTATION 1
22 #include "libnetdata/simple_hashtable/simple_hashtable.h"
23
24 static inline WEVT_FIELD_KEY *field_cache_value_to_key(WEVT_FIELD_VALUE *p) {
25 return &p->key;
26 }
27
28 static inline bool field_cache_cache_compar(WEVT_FIELD_KEY *a, WEVT_FIELD_KEY *b) {
29 return memcmp(a, b, sizeof(WEVT_FIELD_KEY)) == 0;
30 }
31
32 struct ht {
33 SPINLOCK spinlock;
34 size_t allocations;
35 size_t bytes;
36 struct simple_hashtable_FIELDS_CACHE ht;
37 };
38
39 static struct {
40 bool initialized;
41 struct ht ht[WEVT_FIELD_TYPE_MAX];
42 } fdc = {
43 .initialized = false,
44 };
45
46 void field_cache_init(void) {
47 for(size_t type = 0; type < WEVT_FIELD_TYPE_MAX ; type++) {
48 spinlock_init(&fdc.ht[type].spinlock);
49 simple_hashtable_init_FIELDS_CACHE(&fdc.ht[type].ht, 10000);
50 }
51 }
52
53 static inline bool should_zero_provider(WEVT_FIELD_TYPE type, uint64_t value) {
54 switch(type) {
55 case WEVT_FIELD_TYPE_LEVEL:
56 return !is_valid_provider_level(value, true);
57
58 case WEVT_FIELD_TYPE_KEYWORD:
59 return !is_valid_provider_keyword(value, true);
60
61 case WEVT_FIELD_TYPE_OPCODE:
62 return !is_valid_provider_opcode(value, true);
63
64 case WEVT_FIELD_TYPE_TASK:
65 return !is_valid_provider_task(value, true);
66
67 default:
68 return false;
69 }
70 }
71
72 bool field_cache_get(WEVT_FIELD_TYPE type, const ND_UUID *uuid, uint64_t value, TXT_UTF8 *dst) {
73 fatal_assert(type < WEVT_FIELD_TYPE_MAX);
74
75 struct ht *ht = &fdc.ht[type];
76
77 WEVT_FIELD_KEY t = {
78 .value = value,
79 .provider = should_zero_provider(type, value) ? UUID_ZERO : *uuid,
80 };
81 XXH64_hash_t hash = XXH3_64bits(&t, sizeof(t));
82
83 spinlock_lock(&ht->spinlock);
84 SIMPLE_HASHTABLE_SLOT_FIELDS_CACHE *slot = simple_hashtable_get_slot_FIELDS_CACHE(&ht->ht, hash, &t, true);
85 WEVT_FIELD_VALUE *v = SIMPLE_HASHTABLE_SLOT_DATA(slot);
86 spinlock_unlock(&ht->spinlock);
87
88 if(v) {
89 txt_utf8_resize(dst, v->name_size, false);
90 memcpy(dst->data, v->name, v->name_size);
91 dst->used = v->name_size;
92 dst->src = TXT_SOURCE_FIELD_CACHE;
93 return true;
94 }
95
96 return false;
97 }
98
99 static WEVT_FIELD_VALUE *wevt_create_cache_entry(WEVT_FIELD_KEY *t, TXT_UTF8 *name, size_t *bytes) {
100 *bytes = sizeof(WEVT_FIELD_VALUE) + name->used;
101 WEVT_FIELD_VALUE *v = callocz(1, *bytes);
102 v->key = *t;
103 memcpy(v->name, name->data, name->used);
104 v->name_size = name->used;
105 return v;
106 }
107
108 //static bool is_numeric(const char *s) {
109 // while(*s) {
110 // if(!isdigit((uint8_t)*s++))
111 // return false;
112 // }
113 //
114 // return true;
115 //}
116
117 void field_cache_set(WEVT_FIELD_TYPE type, const ND_UUID *uuid, uint64_t value, TXT_UTF8 *name) {
118 fatal_assert(type < WEVT_FIELD_TYPE_MAX);
119
120 struct ht *ht = &fdc.ht[type];
121
122 WEVT_FIELD_KEY t = {
123 .value = value,
124 .provider = should_zero_provider(type, value) ? UUID_ZERO : *uuid,
125 };
126 XXH64_hash_t hash = XXH3_64bits(&t, sizeof(t));
127
128 spinlock_lock(&ht->spinlock);
129 SIMPLE_HASHTABLE_SLOT_FIELDS_CACHE *slot = simple_hashtable_get_slot_FIELDS_CACHE(&ht->ht, hash, &t, true);
130 WEVT_FIELD_VALUE *v = SIMPLE_HASHTABLE_SLOT_DATA(slot);
131 if(!v) {
132 size_t bytes;
133 v = wevt_create_cache_entry(&t, name, &bytes);
134 simple_hashtable_set_slot_FIELDS_CACHE(&ht->ht, slot, hash, v);
135
136 ht->allocations++;
137 ht->bytes += bytes;
138 }
139 // else {
140 // if((v->name_size == 1 && name->used > 0) || is_numeric(v->name)) {
141 // size_t bytes;
142 // WEVT_FIELD_VALUE *nv = wevt_create_cache_entry(&t, name, &bytes);
143 // simple_hashtable_set_slot_FIELDS_CACHE(&ht->ht, slot, hash, nv);
144 // ht->bytes += name->used;
145 // ht->bytes -= v->name_size;
146 // freez(v);
147 // }
148 // else if(name->used > 2 && !is_numeric(name->data) && (v->name_size != name->used || strcasecmp(v->name, name->data) != 0)) {
149 // const char *a = v->name;
150 // const char *b = name->data;
151 // int x = 0;
152 // x++;
153 // }
154 // }
155
156 spinlock_unlock(&ht->spinlock);
157 }
158