minor debug tags refactoring; implemented call nxlog_get_all_debug_tags; server conso...
[public/netxms.git] / src / libnetxms / debug_tag_tree.cpp
1 /*
2 ** NetXMS - Network Management System
3 ** Utility Library
4 ** Copyright (C) 2003-2017 Raden Solutions
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU Lesser General Public License as published
8 ** by the Free Software Foundation; either version 3 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU Lesser General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 **
20 ** File: debug_tag_tree.cpp
21 **
22 **/
23 #include "debug_tag_tree.h"
24
25 /**
26 * Create empty tree node
27 */
28 DebugTagTreeNode::DebugTagTreeNode()
29 {
30 m_value = NULL;
31 m_direct = false;
32 m_directLevel = 0;
33 m_wildcard = true;
34 m_wildcardLevel = 0;
35 m_children = new StringObjectMap<DebugTagTreeNode>(true);
36 }
37
38 /**
39 * Create new tree node
40 */
41 DebugTagTreeNode::DebugTagTreeNode(const TCHAR *value, size_t len)
42 {
43 m_value = (TCHAR *)malloc(sizeof(TCHAR) * ((int)len + 1));
44 memcpy(m_value, value, sizeof(TCHAR) * (int)len);
45 m_value[len] = 0;
46 m_direct = false;
47 m_directLevel = 0;
48 m_wildcard = false;
49 m_wildcardLevel = 0;
50 m_children = new StringObjectMap<DebugTagTreeNode>(true);
51 }
52
53 /**
54 * Get debug LvL from tree node, returns longest match (recursive)
55 */
56 int DebugTagTreeNode::getDebugLevel(const TCHAR *tag) const
57 {
58 if (tag == NULL)
59 {
60 if (m_direct)
61 return m_directLevel;
62 if (m_wildcard)
63 return m_wildcardLevel;
64 return -1;
65 }
66
67 int result = -1;
68 const TCHAR *ptr = _tcschr(tag, _T('.'));
69 size_t len = (ptr == NULL) ? _tcslen(tag) : (ptr - tag);
70
71 DebugTagTreeNode *child = m_children->get(tag, len);
72 if (child != NULL)
73 result = child->getDebugLevel((ptr != NULL) ? ptr + 1 : NULL);
74
75 if ((result == -1) && m_wildcard)
76 return m_wildcardLevel;
77
78 return result;
79 }
80
81 /**
82 * Add new tree node to its children and grand children etc... (recursive)
83 */
84 void DebugTagTreeNode::add(const TCHAR *tag, int level)
85 {
86 if ((tag != NULL) && !_tcscmp(tag, _T("*")))
87 {
88 if (!m_wildcard)
89 m_wildcard = true;
90 m_wildcardLevel = level;
91 return;
92 }
93
94 const TCHAR *ptr = (tag == NULL) ? NULL : _tcschr(tag, _T('.'));
95
96 if (tag == NULL)
97 {
98 if (!m_direct)
99 m_direct = true;
100 m_directLevel = level;
101 return;
102 }
103
104 size_t len = (ptr == NULL) ? _tcslen(tag) : (ptr - tag);
105 DebugTagTreeNode *child = m_children->get(tag, len);
106 if (child != NULL)
107 child->add((ptr != NULL) ? ptr + 1 : NULL, level);
108 else
109 {
110 child = new DebugTagTreeNode(tag, len);
111 m_children->set(child->getValue(), child);
112 child->add((ptr != NULL) ? ptr + 1 : NULL, level);
113 }
114 }
115
116 /**
117 * Remove entry from child list (recursive)
118 */
119 bool DebugTagTreeNode::remove(const TCHAR *tag)
120 {
121 if (tag != NULL)
122 {
123 if (!_tcscmp(tag, _T("*")))
124 {
125 m_wildcard = false;
126 m_wildcardLevel = 0;
127 }
128 else
129 {
130 const TCHAR *ptr = _tcschr(tag, _T('.'));
131 size_t len = (ptr == NULL) ? _tcslen(tag) : (ptr - tag);
132
133 DebugTagTreeNode *child = m_children->get(tag, len);
134 if (child != NULL && child->remove((ptr != NULL) ? ptr + 1 : NULL))
135 {
136 m_children->remove(child->getValue());
137 }
138 }
139 }
140 else
141 {
142 m_direct = false;
143 m_directLevel = 0;
144 }
145
146 return (m_children->size() == 0) && !m_wildcard;
147 }
148
149 /**
150 * Get all tags under this node
151 */
152 void DebugTagTreeNode::getAllTags(const TCHAR *prefix, ObjectArray<DebugTagInfo> *tags) const
153 {
154 TCHAR name[1024];
155 _tcslcpy(name, prefix, 1024);
156 if (*prefix != 0)
157 _tcslcat(name, _T("."), 1024);
158 size_t l = _tcslen(name);
159 StructArray<KeyValuePair> *c = m_children->toArray();
160 for(int i = 0; i < c->size(); i++)
161 {
162 KeyValuePair *p = c->get(i);
163 _tcslcpy(&name[l], p->key, 1024 - l);
164 const DebugTagTreeNode *n = static_cast<const DebugTagTreeNode*>(p->value);
165 if (n->m_direct)
166 {
167 tags->add(new DebugTagInfo(name, n->m_directLevel));
168 }
169 if (n->m_wildcard)
170 {
171 _tcslcat(name, _T(".*"), 1024);
172 tags->add(new DebugTagInfo(name, n->m_wildcardLevel));
173 _tcslcpy(&name[l], p->key, 1024 - l);
174 }
175 n->getAllTags(name, tags);
176 }
177 }
178
179 /**
180 * Get debug LvL from tree, returns longest match (recursive)
181 */
182 int DebugTagTree::getDebugLevel(const TCHAR *tags)
183 {
184 InterlockedIncrement(&m_readerCount);
185 int result;
186 if (tags == NULL)
187 {
188 result = m_root->getWildcardDebugLevel();
189 }
190 else
191 {
192 result = m_root->getDebugLevel(tags);
193 if (result == -1)
194 result = 0;
195 }
196 InterlockedDecrement(&m_readerCount);
197 return result;
198 }
199
200 /**
201 * Get main debug level
202 */
203 int DebugTagTree::getRootDebugLevel()
204 {
205 InterlockedIncrement(&m_readerCount);
206 int level = m_root->getWildcardDebugLevel();
207 InterlockedDecrement(&m_readerCount);
208 return level;
209 }
210
211 /**
212 * Get all configured tags
213 */
214 ObjectArray<DebugTagInfo> *DebugTagTree::getAllTags()
215 {
216 ObjectArray<DebugTagInfo> *tags = new ObjectArray<DebugTagInfo>(64, 64, true);
217 InterlockedIncrement(&m_readerCount);
218 m_root->getAllTags(_T(""), tags);
219 InterlockedDecrement(&m_readerCount);
220 return tags;
221 }