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 }