| 1 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | |
| 3 | #include "rrdset-index-name.h" |
| 4 | #include "rrdset-index-id.h" |
| 5 | #include "rrdset-slots.h" |
| 6 | |
| 7 | static RRDSET *rrdset_index_find_name(RRDHOST *host, const char *name); |
| 8 | |
| 9 | STRING *rrdset_fix_name(RRDHOST *host, const char *chart_full_id, const char *type, const char *current_name, const char *name) { |
| 10 | if(!name || !*name) return NULL; |
| 11 | |
| 12 | char full_name[RRD_ID_LENGTH_MAX + 1]; |
| 13 | char sanitized_name[CONFIG_MAX_VALUE + 1]; |
| 14 | char new_name[CONFIG_MAX_VALUE + 1]; |
| 15 | |
| 16 | snprintfz(full_name, RRD_ID_LENGTH_MAX, "%s.%s", type, name); |
| 17 | rrdset_strncpyz_name(sanitized_name, full_name, CONFIG_MAX_VALUE); |
| 18 | strncpyz(new_name, sanitized_name, CONFIG_MAX_VALUE); |
| 19 | |
| 20 | if(rrdset_index_find_name(host, new_name)) { |
| 21 | netdata_log_debug(D_RRD_CALLS, "RRDSET: chart name '%s' on host '%s' already exists.", new_name, rrdhost_hostname(host)); |
| 22 | if(!strcmp(chart_full_id, full_name) && (!current_name || !*current_name)) { |
| 23 | unsigned i = 1; |
| 24 | |
| 25 | do { |
| 26 | snprintfz(new_name, CONFIG_MAX_VALUE, "%s_%u", sanitized_name, i); |
| 27 | i++; |
| 28 | } while (rrdset_index_find_name(host, new_name)); |
| 29 | |
| 30 | // netdata_log_info("RRDSET: using name '%s' for chart '%s' on host '%s'.", new_name, full_name, rrdhost_hostname(host)); |
| 31 | } |
| 32 | else |
| 33 | return NULL; |
| 34 | } |
| 35 | |
| 36 | return string_strdupz(new_name); |
| 37 | } |
| 38 | |
| 39 | int rrdset_reset_name(RRDSET *st, const char *name) { |
| 40 | if(unlikely(!strcmp(rrdset_name(st), name))) |
| 41 | return 1; |
| 42 | |
| 43 | RRDHOST *host = st->rrdhost; |
| 44 | |
| 45 | netdata_log_debug(D_RRD_CALLS, "rrdset_reset_name() old: '%s', new: '%s'", rrdset_name(st), name); |
| 46 | |
| 47 | STRING *name_string = rrdset_fix_name(host, rrdset_id(st), rrdset_parts_type(st), string2str(st->name), name); |
| 48 | if(!name_string) return 0; |
| 49 | |
| 50 | if(st->name) { |
| 51 | rrdset_index_del_name(host, st); |
| 52 | SWAP(name_string, st->name); |
| 53 | string_freez(name_string); |
| 54 | } |
| 55 | else |
| 56 | st->name = name_string; |
| 57 | |
| 58 | rrdset_index_add_name(host, st); |
| 59 | |
| 60 | rrdset_flag_clear(st, RRDSET_FLAG_EXPORTING_SEND|RRDSET_FLAG_EXPORTING_IGNORE|RRDSET_FLAG_UPSTREAM_SEND|RRDSET_FLAG_UPSTREAM_IGNORE); |
| 61 | rrdset_metadata_updated(st); |
| 62 | |
| 63 | rrdcontext_updated_rrdset_name(st); |
| 64 | return 2; |
| 65 | } |
| 66 | |
| 67 | static RRDSET *rrdset_index_find_name(RRDHOST *host, const char *name) { |
| 68 | if (unlikely(!host->rrdset_root_index_name)) |
| 69 | return NULL; |
| 70 | return dictionary_get(host->rrdset_root_index_name, name); |
| 71 | } |
| 72 | |
| 73 | void rrdset_index_byname_init(RRDHOST *host) { |
| 74 | if(!host->rrdset_root_index_name) |
| 75 | host->rrdset_root_index_name = dictionary_create_view(host->rrdset_root_index); |
| 76 | } |
| 77 | |
| 78 | void rrdset_index_add_name(RRDHOST *host, RRDSET *st) { |
| 79 | if(!st->name) return; |
| 80 | const DICTIONARY_ITEM *sta = dictionary_get_and_acquire_item(host->rrdset_root_index, rrdset_id(st)); |
| 81 | if(sta) { |
| 82 | const DICTIONARY_ITEM *sta2 = dictionary_view_set_and_acquire_item(host->rrdset_root_index_name, rrdset_name(st), sta); |
| 83 | if(sta2) { |
| 84 | if(dictionary_acquired_item_value(sta2) == st) |
| 85 | rrdset_flag_set(st, RRDSET_FLAG_INDEXED_NAME); |
| 86 | |
| 87 | dictionary_acquired_item_release(host->rrdset_root_index_name, sta2); |
| 88 | } |
| 89 | |
| 90 | dictionary_acquired_item_release(host->rrdset_root_index, sta); |
| 91 | } |
| 92 | } |
| 93 | |
| 94 | void rrdset_index_del_name(RRDHOST *host, RRDSET *st) { |
| 95 | if(rrdset_flag_check(st, RRDSET_FLAG_INDEXED_NAME)) { |
| 96 | const DICTIONARY_ITEM *sta = dictionary_get_and_acquire_item(host->rrdset_root_index_name, rrdset_name(st)); |
| 97 | |
| 98 | if(sta) { |
| 99 | if(dictionary_acquired_item_value(sta) == st) |
| 100 | dictionary_del(host->rrdset_root_index_name, rrdset_name(st)); |
| 101 | |
| 102 | dictionary_acquired_item_release(host->rrdset_root_index_name, sta); |
| 103 | dictionary_garbage_collect(host->rrdset_root_index_name); |
| 104 | } |
| 105 | |
| 106 | rrdset_flag_clear(st, RRDSET_FLAG_INDEXED_NAME); |
| 107 | } |
| 108 | } |
| 109 | |
| 110 | RRDSET *rrdset_find_byname(RRDHOST *host, const char *name) { |
| 111 | RRDSET *st = rrdset_index_find_name(host, name); |
| 112 | |
| 113 | if(st) { |
| 114 | if(!rrdset_is_discoverable(st)) |
| 115 | return NULL; |
| 116 | |
| 117 | st->last_accessed_time_s = now_realtime_sec(); |
| 118 | } |
| 119 | |
| 120 | return(st); |
| 121 | } |