xref: /spdk/lib/log/log_flags.c (revision 2d65fd75787eb0bb41e61d598e380b026090c148)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2017 Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 #include "spdk/stdinc.h"
7 
8 #include "spdk/log.h"
9 
10 static TAILQ_HEAD(spdk_log_flag_head,
11 		  spdk_log_flag) g_log_flags = TAILQ_HEAD_INITIALIZER(g_log_flags);
12 
13 static struct spdk_log_flag *
get_log_flag(const char * name)14 get_log_flag(const char *name)
15 {
16 	struct spdk_log_flag *flag;
17 
18 	TAILQ_FOREACH(flag, &g_log_flags, tailq) {
19 		if (strcasecmp(name, flag->name) == 0) {
20 			return flag;
21 		}
22 	}
23 
24 	return NULL;
25 }
26 
27 void
spdk_log_register_flag(const char * name,struct spdk_log_flag * flag)28 spdk_log_register_flag(const char *name, struct spdk_log_flag *flag)
29 {
30 	struct spdk_log_flag *iter;
31 
32 	if (name == NULL || flag == NULL) {
33 		SPDK_ERRLOG("missing spdk_log_flag parameters\n");
34 		assert(false);
35 		return;
36 	}
37 
38 	if (get_log_flag(name)) {
39 		SPDK_ERRLOG("duplicate spdk_log_flag '%s'\n", name);
40 		assert(false);
41 		return;
42 	}
43 
44 	TAILQ_FOREACH(iter, &g_log_flags, tailq) {
45 		if (strcasecmp(iter->name, flag->name) > 0) {
46 			TAILQ_INSERT_BEFORE(iter, flag, tailq);
47 			return;
48 		}
49 	}
50 
51 	TAILQ_INSERT_TAIL(&g_log_flags, flag, tailq);
52 }
53 
54 bool
spdk_log_get_flag(const char * name)55 spdk_log_get_flag(const char *name)
56 {
57 	struct spdk_log_flag *flag = get_log_flag(name);
58 
59 	if (flag && flag->enabled) {
60 		return true;
61 	}
62 
63 	return false;
64 }
65 
66 static int
log_set_flag(const char * name,bool value)67 log_set_flag(const char *name, bool value)
68 {
69 	struct spdk_log_flag *flag;
70 	int rc = -EINVAL;
71 
72 	if (strcasecmp(name, "all") == 0) {
73 		TAILQ_FOREACH(flag, &g_log_flags, tailq) {
74 			flag->enabled = value;
75 		}
76 		return 0;
77 	}
78 
79 	TAILQ_FOREACH(flag, &g_log_flags, tailq) {
80 		if (fnmatch(name, flag->name, FNM_CASEFOLD) == 0) {
81 			flag->enabled = value;
82 			rc = 0;
83 		}
84 	}
85 
86 	return rc;
87 }
88 
89 int
spdk_log_set_flag(const char * name)90 spdk_log_set_flag(const char *name)
91 {
92 	return log_set_flag(name, true);
93 }
94 
95 int
spdk_log_clear_flag(const char * name)96 spdk_log_clear_flag(const char *name)
97 {
98 	return log_set_flag(name, false);
99 }
100 
101 struct spdk_log_flag *
spdk_log_get_first_flag(void)102 spdk_log_get_first_flag(void)
103 {
104 	return TAILQ_FIRST(&g_log_flags);
105 }
106 
107 struct spdk_log_flag *
spdk_log_get_next_flag(struct spdk_log_flag * flag)108 spdk_log_get_next_flag(struct spdk_log_flag *flag)
109 {
110 	return TAILQ_NEXT(flag, tailq);
111 }
112 
113 void
spdk_log_usage(FILE * f,const char * log_arg)114 spdk_log_usage(FILE *f, const char *log_arg)
115 {
116 #define LINE_PREFIX			"                           "
117 #define ENTRY_SEPARATOR			", "
118 #define MAX_LINE_LENGTH			100
119 	uint64_t prefix_len = strlen(LINE_PREFIX);
120 	uint64_t separator_len = strlen(ENTRY_SEPARATOR);
121 	const char *first_entry = "--logflag <flag>      enable log flag (all, ";
122 	uint64_t curr_line_len;
123 	uint64_t curr_entry_len;
124 	struct spdk_log_flag *flag;
125 	char first_line[MAX_LINE_LENGTH] = {};
126 
127 	snprintf(first_line, sizeof(first_line), " %s, %s", log_arg, first_entry);
128 	fprintf(f, "%s", first_line);
129 	curr_line_len = strlen(first_line);
130 
131 	TAILQ_FOREACH(flag, &g_log_flags, tailq) {
132 		curr_entry_len = strlen(flag->name);
133 		if ((curr_line_len + curr_entry_len + separator_len) > MAX_LINE_LENGTH) {
134 			fprintf(f, "\n%s", LINE_PREFIX);
135 			curr_line_len = prefix_len;
136 		}
137 
138 		fprintf(f, "%s", flag->name);
139 		curr_line_len += curr_entry_len;
140 
141 		if (TAILQ_LAST(&g_log_flags, spdk_log_flag_head) == flag) {
142 			break;
143 		}
144 
145 		fprintf(f, "%s", ENTRY_SEPARATOR);
146 		curr_line_len += separator_len;
147 	}
148 
149 	fprintf(f, ")\n");
150 }
151