00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "TextBuffer.h"
00025 #include "Tokenizer.h"
00026 #include "ink_defs.h"
00027 #include "ink_string.h"
00028
00029 #include "P_RecFile.h"
00030 #include "P_RecUtils.h"
00031 #include "P_RecMessage.h"
00032 #include "P_RecCore.h"
00033 #include "I_Layout.h"
00034
00035 const char *g_rec_config_fpath = NULL;
00036 LLQ *g_rec_config_contents_llq = NULL;
00037 InkHashTable *g_rec_config_contents_ht = NULL;
00038 ink_mutex g_rec_config_lock;
00039
00040
00041
00042
00043 void
00044 RecConfigFileInit(void)
00045 {
00046 ink_mutex_init(&g_rec_config_lock, NULL);
00047 g_rec_config_contents_llq = create_queue();
00048 g_rec_config_contents_ht = ink_hash_table_create(InkHashTableKeyType_String);
00049 }
00050
00051
00052
00053
00054 static int
00055 RecFileImport_Xmalloc(const char *file, char **file_buf, int *file_size)
00056 {
00057 int err = REC_ERR_FAIL;
00058 RecHandle h_file;
00059 int bytes_read;
00060
00061 if (file && file_buf && file_size) {
00062 *file_buf = 0;
00063 *file_size = 0;
00064 if ((h_file = RecFileOpenR(file)) != REC_HANDLE_INVALID) {
00065 *file_size = RecFileGetSize(h_file);
00066 *file_buf = (char *)ats_malloc(*file_size + 1);
00067 if (RecFileRead(h_file, *file_buf, *file_size, &bytes_read) != REC_ERR_FAIL && bytes_read == *file_size) {
00068 (*file_buf)[*file_size] = '\0';
00069 err = REC_ERR_OKAY;
00070 } else {
00071 ats_free(*file_buf);
00072 *file_buf = 0;
00073 *file_size = 0;
00074 }
00075 RecFileClose(h_file);
00076 }
00077 }
00078
00079 return err;
00080 }
00081
00082
00083
00084
00085 const char *
00086 RecConfigOverrideFromEnvironment(const char * name, const char * value)
00087 {
00088 ats_scoped_str envname(ats_strdup(name));
00089 const char * envval = NULL;
00090
00091
00092 for (char * c = envname; *c != '\0'; ++c) {
00093 switch (*c) {
00094 case '.': *c = '_'; break;
00095 default: *c = ParseRules::ink_toupper(*c); break;
00096 }
00097 }
00098
00099 envval = getenv((const char *)envname);
00100 if (envval) {
00101 return envval;
00102 }
00103
00104 return value;
00105 }
00106
00107
00108
00109
00110 int
00111 RecConfigFileParse(const char * path, RecConfigEntryCallback handler, bool inc_version)
00112 {
00113 char *fbuf;
00114 int fsize;
00115
00116 const char *line;
00117 int line_num;
00118
00119 char *rec_type_str, *name_str, *data_type_str, *data_str;
00120 RecT rec_type;
00121 RecDataT data_type;
00122
00123 Tokenizer line_tok("\r\n");
00124 tok_iter_state line_tok_state;
00125
00126 RecConfigFileEntry *cfe;
00127
00128 RecDebug(DL_Note, "Reading '%s'", path);
00129
00130
00131 ink_mutex_acquire(&g_rec_config_lock);
00132
00133 if (RecFileImport_Xmalloc(path, &fbuf, &fsize) == REC_ERR_FAIL) {
00134 RecLog(DL_Warning, "Could not import '%s'", path);
00135 ink_mutex_release(&g_rec_config_lock);
00136 return REC_ERR_FAIL;
00137 }
00138
00139 while (!queue_is_empty(g_rec_config_contents_llq)) {
00140 cfe = (RecConfigFileEntry *) dequeue(g_rec_config_contents_llq);
00141 ats_free(cfe->entry);
00142 ats_free(cfe);
00143 }
00144 ink_hash_table_destroy(g_rec_config_contents_ht);
00145 g_rec_config_contents_ht = ink_hash_table_create(InkHashTableKeyType_String);
00146
00147 line_tok.Initialize(fbuf, SHARE_TOKS);
00148 line = line_tok.iterFirst(&line_tok_state);
00149 line_num = 1;
00150 while (line) {
00151 char *lc = ats_strdup(line);
00152 char *lt = lc;
00153 char *ln;
00154
00155 while (isspace(*lt))
00156 lt++;
00157 rec_type_str = strtok_r(lt, " \t", &ln);
00158
00159
00160 if ((!rec_type_str) || (rec_type_str && (*rec_type_str == '#'))) {
00161 goto L_next_line;
00162 }
00163
00164 name_str = strtok_r(NULL, " \t", &ln);
00165 data_type_str = strtok_r(NULL, " \t", &ln);
00166
00167
00168 if (ln) {
00169
00170
00171
00172
00173
00174
00175 while (isspace(*ln))
00176 ln++;
00177 if (*ln == '\0') {
00178 data_str = NULL;
00179 } else {
00180 data_str = ln;
00181 while (*ln != '\0')
00182 ln++;
00183 ln--;
00184 while (isspace(*ln) && (ln > data_str))
00185 ln--;
00186 ln++;
00187 *ln = '\0';
00188 }
00189 } else {
00190 data_str = NULL;
00191 }
00192
00193
00194 if (!(rec_type_str && name_str && data_type_str && data_str)) {
00195 RecLog(DL_Warning, "Could not parse line at '%s:%d' -- skipping line: '%s'", path, line_num, line);
00196 goto L_next_line;
00197 }
00198
00199
00200 if (strcmp(rec_type_str, "CONFIG") == 0) {
00201 rec_type = RECT_CONFIG;
00202 } else if (strcmp(rec_type_str, "PROCESS") == 0) {
00203 rec_type = RECT_PROCESS;
00204 } else if (strcmp(rec_type_str, "NODE") == 0) {
00205 rec_type = RECT_NODE;
00206 } else if (strcmp(rec_type_str, "CLUSTER") == 0) {
00207 rec_type = RECT_CLUSTER;
00208 } else if (strcmp(rec_type_str, "LOCAL") == 0) {
00209 rec_type = RECT_LOCAL;
00210 } else {
00211 RecLog(DL_Warning, "Unknown record type '%s' at '%s:%d' -- skipping line", rec_type_str, path, line_num);
00212 goto L_next_line;
00213 }
00214
00215
00216 if (strcmp(data_type_str, "INT") == 0) {
00217 data_type = RECD_INT;
00218 } else if (strcmp(data_type_str, "FLOAT") == 0) {
00219 data_type = RECD_FLOAT;
00220 } else if (strcmp(data_type_str, "STRING") == 0) {
00221 data_type = RECD_STRING;
00222 } else if (strcmp(data_type_str, "COUNTER") == 0) {
00223 data_type = RECD_COUNTER;
00224 } else {
00225 RecLog(DL_Warning, "Unknown data type '%s' at '%s:%d' -- skipping line", data_type_str, path, line_num);
00226 goto L_next_line;
00227 }
00228
00229
00230 handler(rec_type, data_type, name_str, RecConfigOverrideFromEnvironment(name_str, data_str), inc_version);
00231
00232
00233 cfe = (RecConfigFileEntry *)ats_malloc(sizeof(RecConfigFileEntry));
00234 cfe->entry_type = RECE_RECORD;
00235 cfe->entry = ats_strdup(name_str);
00236 enqueue(g_rec_config_contents_llq, (void *) cfe);
00237 ink_hash_table_insert(g_rec_config_contents_ht, name_str, NULL);
00238 goto L_done;
00239
00240 L_next_line:
00241
00242
00243 cfe = (RecConfigFileEntry *)ats_malloc(sizeof(RecConfigFileEntry));
00244 cfe->entry_type = RECE_COMMENT;
00245 cfe->entry = ats_strdup(line);
00246 enqueue(g_rec_config_contents_llq, (void *) cfe);
00247
00248 L_done:
00249 line = line_tok.iterNext(&line_tok_state);
00250 line_num++;
00251 ats_free(lc);
00252 }
00253
00254 ink_mutex_release(&g_rec_config_lock);
00255 ats_free(fbuf);
00256
00257 return REC_ERR_OKAY;
00258 }