support directive: #@add_annotation

pull/37/head
yuqing 2018-08-20 16:24:52 +08:00
parent 9cd25c3686
commit 2aab8aa4c5
5 changed files with 315 additions and 92 deletions

View File

@ -1,6 +1,8 @@
Version 1.40 2018-08-16
Version 1.40 2018-08-20
* add function conn_pool_parse_server_info and conn_pool_load_server_info
* support directive: #@add_annotation, for example:
#@add_annotation CONFIG_GET /usr/lib/libshmcache.so /etc/libshmcache.conf
Version 1.39 2018-07-31
* add #@function REPLACE_VARS

View File

@ -14,6 +14,7 @@
#include <string.h>
#include <errno.h>
#include <limits.h>
#include <dlfcn.h>
#include "shared_func.h"
#include "logger.h"
#include "http_func.h"
@ -126,9 +127,13 @@ static void iniDoSetAnnotations(AnnotationEntry *src, const int src_count,
}
pDest->func_name = pSrc->func_name;
pDest->arg = pSrc->arg;
pDest->func_init = pSrc->func_init;
pDest->func_destroy = pSrc->func_destroy;
pDest->func_get = pSrc->func_get;
pDest->func_free = pSrc->func_free;
pDest->dlhandle = pSrc->dlhandle;
pDest->inited = false;
if (pDest == pDestEnd) //insert
{
++(*dest_count);
@ -137,16 +142,43 @@ static void iniDoSetAnnotations(AnnotationEntry *src, const int src_count,
}
}
static int iniAnnotationFuncLocalIpGet(IniContext *context, char *param,
char **pOutValue, int max_values)
static AnnotationEntry *iniFindAnnotation(AnnotationEntry *annotatios,
const char *func_name)
{
AnnotationEntry *pAnnoEntry;
if (annotatios == NULL)
{
return NULL;
}
pAnnoEntry = annotatios;
while (pAnnoEntry->func_name != NULL)
{
if (strcmp(func_name, pAnnoEntry->func_name) == 0)
{
return pAnnoEntry;
}
pAnnoEntry++;
}
return NULL;
}
static int iniAnnotationFuncLocalIpGet(IniContext *context,
struct ini_annotation_entry *annotation,
const IniItem *item, char **pOutValue, int max_values)
{
bool need_private_ip;
int count;
int index;
char param[FAST_INI_ITEM_VALUE_SIZE];
const char *next_ip;
char *square_start;
char name_part[16];
strcpy(param, item->value);
memset(name_part, 0, sizeof(name_part));
square_start = strchr(param, '[');
if (square_start != NULL && param[strlen(param) - 1] == ']') {
@ -197,8 +229,9 @@ static int iniAnnotationFuncLocalIpGet(IniContext *context, char *param,
return count;
}
static int iniAnnotationFuncShellExec(IniContext *context, char *param,
char **pOutValue, int max_values)
static int iniAnnotationFuncShellExec(IniContext *context,
struct ini_annotation_entry *annotation,
const IniItem *item, char **pOutValue, int max_values)
{
int count;
int result;
@ -213,24 +246,24 @@ static int iniAnnotationFuncShellExec(IniContext *context, char *param,
return count;
}
if ((result=getExecResult(param, output, FAST_INI_ITEM_VALUE_SIZE)) != 0)
if ((result=getExecResult(item->value, output, FAST_INI_ITEM_VALUE_SIZE)) != 0)
{
logWarning("file: "__FILE__", line: %d, "
"exec %s fail, errno: %d, error info: %s",
__LINE__, param, result, STRERROR(result));
__LINE__, item->value, result, STRERROR(result));
free(output);
return count;
}
if (*output == '\0')
{
logWarning("file: "__FILE__", line: %d, "
"empty reply when exec: %s", __LINE__, param);
"empty reply when exec: %s", __LINE__, item->value);
}
pOutValue[count++] = fc_trim(output);
return count;
}
static int iniCopyBuffer(char *dest, const int size, char *src, int len)
static int iniCopyBuffer(char *dest, const int size, const char *src, int len)
{
if (len == 0) {
return 0;
@ -252,18 +285,19 @@ static int iniCopyBuffer(char *dest, const int size, char *src, int len)
return len;
}
static char *doReplaceVars(IniContext *pContext, char *param, const int max_size)
static char *doReplaceVars(IniContext *pContext, const char *param,
const int max_size)
{
#define VARIABLE_TAG_MIN_LENGTH 4 //%{v}
SetDirectiveVars *set;
char *p;
char *e;
const char *p;
const char *e;
char name[64];
char *start;
char *value;
char *pLoopEnd;
char *pEnd;
const char *start;
const char *value;
const char *pLoopEnd;
const char *pEnd;
char *pDest;
char *output;
int name_len;
@ -351,11 +385,12 @@ static char *doReplaceVars(IniContext *pContext, char *param, const int max_size
return output;
}
static int iniAnnotationReplaceVars(IniContext *pContext, char *param,
char **pOutValue, int max_values)
static int iniAnnotationReplaceVars(IniContext *pContext,
struct ini_annotation_entry *annotation,
const IniItem *item, char **pOutValue, int max_values)
{
char *output;
output = doReplaceVars(pContext, param, FAST_INI_ITEM_VALUE_SIZE);
output = doReplaceVars(pContext, item->value, FAST_INI_ITEM_VALUE_SIZE);
if (output == NULL) {
return 0;
}
@ -365,7 +400,8 @@ static int iniAnnotationReplaceVars(IniContext *pContext, char *param,
}
}
static void iniAnnotationFuncFree(char **values, const int count)
void iniAnnotationFreeValues(struct ini_annotation_entry *annotation,
char **values, const int count)
{
int i;
for (i=0; i<count; i++) {
@ -380,28 +416,22 @@ static void iniSetBuiltinAnnotations(IniContext *pContext,
AnnotationEntry builtins[_BUILTIN_ANNOTATION_COUNT];
AnnotationEntry *pAnnotation;
memset(builtins, 0, sizeof(builtins));
pAnnotation = builtins;
pAnnotation->func_name = "LOCAL_IP_GET";
pAnnotation->func_init = NULL;
pAnnotation->func_destroy = NULL;
pAnnotation->func_get = iniAnnotationFuncLocalIpGet;
pAnnotation->func_free = NULL;
pAnnotation++;
pAnnotation->func_name = "REPLACE_VARS";
pAnnotation->func_init = NULL;
pAnnotation->func_destroy = NULL;
pAnnotation->func_get = iniAnnotationReplaceVars;
pAnnotation->func_free = iniAnnotationFuncFree;
pAnnotation->func_free = iniAnnotationFreeValues;
pAnnotation++;
if ((pContext->flags & FAST_INI_FLAGS_SHELL_EXECUTE) != 0)
{
pAnnotation->func_name = "SHELL_EXEC";
pAnnotation->func_init = NULL;
pAnnotation->func_destroy = NULL;
pAnnotation->func_get = iniAnnotationFuncShellExec;
pAnnotation->func_free = iniAnnotationFuncFree;
pAnnotation->func_free = iniAnnotationFreeValues;
pAnnotation++;
}
@ -443,10 +473,9 @@ static int iniSetAnnotations(IniContext *pContext, const char annotation_type,
return 0;
}
int iniSetAnnotationCallBack(AnnotationEntry *map, int count)
int iniSetAnnotationCallBack(AnnotationEntry *annotations, int count)
{
int bytes;
AnnotationEntry *pDest;
if (count <= 0)
{
@ -466,34 +495,33 @@ int iniSetAnnotationCallBack(AnnotationEntry *map, int count)
return ENOMEM;
}
iniDoSetAnnotations(map, count, g_annotations, &g_annotation_count);
pDest = g_annotations + g_annotation_count;
pDest->func_name = NULL;
pDest->func_init = NULL;
pDest->func_destroy = NULL;
pDest->func_get = NULL;
memset(g_annotations + g_annotation_count, 0,
sizeof(AnnotationEntry) * (count + 1));
iniDoSetAnnotations(annotations, count, g_annotations, &g_annotation_count);
return 0;
}
void iniDestroyAnnotationCallBack()
{
AnnotationEntry *pAnnoMap;
AnnotationEntry *pAnnoEntry;
if (g_annotations == NULL)
{
return;
}
pAnnoMap = g_annotations;
while (pAnnoMap->func_name)
pAnnoEntry = g_annotations;
while (pAnnoEntry->func_name)
{
if (pAnnoMap->func_destroy != NULL)
if (pAnnoEntry->func_destroy != NULL)
{
pAnnoMap->func_destroy();
pAnnoEntry->func_destroy(pAnnoEntry);
}
pAnnoMap++;
if (pAnnoEntry->dlhandle != NULL)
{
dlclose(pAnnoEntry->dlhandle);
}
pAnnoEntry++;
}
free(g_annotations);
@ -558,6 +586,43 @@ int iniLoadFromFile(const char *szFilename, IniContext *pContext)
NULL, 0, FAST_INI_FLAGS_NONE);
}
static void iniDestroyAnnotations(const int old_annotation_count)
{
AnnotationEntry *pAnnoEntry;
if (g_annotations == NULL)
{
return;
}
logDebug("iniDestroyAnnotations, old_annotation_count: %d, "
"g_annotation_count: %d",
old_annotation_count, g_annotation_count);
if (old_annotation_count == 0)
{
iniDestroyAnnotationCallBack();
return;
}
pAnnoEntry = g_annotations + old_annotation_count;
while (pAnnoEntry->func_name)
{
if (pAnnoEntry->func_destroy != NULL)
{
pAnnoEntry->func_destroy(pAnnoEntry);
}
if (pAnnoEntry->dlhandle != NULL)
{
dlclose(pAnnoEntry->dlhandle);
}
pAnnoEntry++;
}
memset(g_annotations + old_annotation_count, 0,
sizeof(AnnotationEntry) * (g_annotation_count - old_annotation_count));
g_annotation_count = old_annotation_count;
}
int iniLoadFromFileEx(const char *szFilename, IniContext *pContext,
const char annotation_type, AnnotationEntry *annotations, const int count,
const char flags)
@ -566,6 +631,7 @@ int iniLoadFromFileEx(const char *szFilename, IniContext *pContext,
int len;
char *pLast;
char full_filename[MAX_PATH_SIZE];
int old_annotation_count;
if ((result=iniInitContext(pContext, annotation_type,
annotations, count, flags)) != 0)
@ -646,7 +712,13 @@ int iniLoadFromFileEx(const char *szFilename, IniContext *pContext,
}
}
old_annotation_count = g_annotation_count;
result = iniDoLoadFromFile(full_filename, pContext);
if (g_annotation_count > old_annotation_count)
{
iniDestroyAnnotations(old_annotation_count);
}
if (result == 0)
{
iniSortItems(pContext);
@ -710,6 +782,7 @@ int iniLoadFromBufferEx(char *content, IniContext *pContext,
const char flags)
{
int result;
int old_annotation_count;
if ((result=iniInitContext(pContext, annotation_type,
annotations, count, flags)) != 0)
@ -717,7 +790,13 @@ int iniLoadFromBufferEx(char *content, IniContext *pContext,
return result;
}
old_annotation_count = g_annotation_count;
result = iniLoadItemsFromBuffer(content, pContext);
if (g_annotation_count > old_annotation_count)
{
iniDestroyAnnotations(old_annotation_count);
}
if (result == 0)
{
iniSortItems(pContext);
@ -737,6 +816,128 @@ int iniLoadFromBuffer(char *content, IniContext *pContext)
NULL, 0, FAST_INI_FLAGS_NONE);
}
typedef int (*init_annotation_func0)(AnnotationEntry *annotation);
typedef int (*init_annotation_func1)(AnnotationEntry *annotation,
const char *arg1);
typedef int (*init_annotation_func2)(AnnotationEntry *annotation,
const char *arg1, const char *arg2);
typedef int (*init_annotation_func3)(AnnotationEntry *annotation,
const char *arg1, const char *arg2, const char *arg3);
static int iniAddAnnotation(char *params)
{
#define MAX_PARAMS 5
char *cols[MAX_PARAMS];
char *func_name;
char *library;
AnnotationEntry annotation;
void *dlhandle;
void *init_func;
char symbol[64];
int argc;
int count;
int result;
trim(params);
count = splitEx(params, ' ', cols, MAX_PARAMS);
if (count < 2)
{
logError("file: "__FILE__", line: %d, "
"invalid format, correct format: "
"#@add_annotation FUNC_NAME library ...", __LINE__);
return EINVAL;
}
func_name = fc_trim(cols[0]);
library = fc_trim(cols[1]);
if (func_name == '\0')
{
logError("file: "__FILE__", line: %d, "
"empty func name, correct format: "
"#@add_annotation FUNC_NAME library ...", __LINE__);
return EINVAL;
}
if (library == '\0')
{
logError("file: "__FILE__", line: %d, "
"empty library, correct format: "
"#@add_annotation FUNC_NAME library ...", __LINE__);
return EINVAL;
}
if (iniFindAnnotation(g_annotations, func_name) != NULL)
{
logWarning("file: "__FILE__", line: %d, "
"function %s already exist", __LINE__, func_name);
return EEXIST;
}
if (strcmp(library, "-") == 0)
{
library = NULL;
}
else if (!fileExists(library))
{
logError("file: "__FILE__", line: %d, "
"library %s not exist", __LINE__, library);
return ENOENT;
}
dlhandle = dlopen(library, RTLD_LAZY);
if (dlhandle == NULL)
{
logError("file: "__FILE__", line: %d, "
"dlopen %s fail, error info: %s",
__LINE__, library != NULL ? library : "",
dlerror());
return EFAULT;
}
snprintf(symbol, sizeof(symbol), "%s_init_annotation", func_name);
init_func = dlsym(dlhandle, symbol);
if (init_func == NULL)
{
logError("file: "__FILE__", line: %d, "
"dlsym function %s fail, error info: %s",
__LINE__, symbol, dlerror());
dlclose(dlhandle);
return ENOENT;
}
memset(&annotation, 0, sizeof(annotation));
argc = count - 2;
switch (argc)
{
case 0:
result = ((init_annotation_func0)init_func)(&annotation);
break;
case 1:
result = ((init_annotation_func1)init_func)(&annotation, cols[2]);
break;
case 2:
result = ((init_annotation_func2)init_func)(&annotation,
cols[2], cols[3]);
break;
case 3:
result = ((init_annotation_func3)init_func)(&annotation,
cols[2], cols[3], cols[4]);
break;
}
if (result != 0)
{
logError("file: "__FILE__", line: %d, "
"call function %s fail, ret: %d",
__LINE__, symbol, result);
dlclose(dlhandle);
return EFAULT;
}
annotation.dlhandle = dlhandle;
return iniSetAnnotationCallBack(&annotation, 1);
}
static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext)
{
IniSection *pSection;
@ -844,11 +1045,15 @@ static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext)
free(pIncludeFilename);
continue;
}
else if ((*pLine == '#' && \
strncasecmp(pLine+1, "@function", 9) == 0 && \
(*(pLine+10) == ' ' || *(pLine+10) == '\t')))
else if (*pLine == '#')
{
if (pContext->annotation_type != FAST_INI_ANNOTATION_DISABLE)
if (pContext->annotation_type == FAST_INI_ANNOTATION_DISABLE)
{
continue;
}
if (strncasecmp(pLine+1, "@function", 9) == 0 &&
(*(pLine+10) == ' ' || *(pLine+10) == '\t'))
{
nNameLen = strlen(pLine + 11);
if (nNameLen > FAST_INI_ITEM_NAME_LEN)
@ -870,6 +1075,16 @@ static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext)
__LINE__);
}
}
else if (strncasecmp(pLine+1, "@add_annotation", 15) == 0 &&
(*(pLine+16) == ' ' || *(pLine+16) == '\t'))
{
result = iniAddAnnotation(pLine + 17);
if (!(result == 0 || result == EEXIST))
{
break;
}
}
continue;
}
@ -985,16 +1200,15 @@ static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext)
if (isAnnotation)
{
AnnotationEntry *pAnnoMapBase;
AnnotationEntry *pAnnoMap = NULL;
bool found;
AnnotationEntry *pAnnoEntryBase;
AnnotationEntry *pAnnoEntry = NULL;
isAnnotation = 0;
if ((pAnnoMapBase=iniGetAnnotations(pContext)) == NULL)
if ((pAnnoEntryBase=iniGetAnnotations(pContext)) == NULL)
{
pAnnoMapBase = g_annotations;
pAnnoEntryBase = g_annotations;
}
if (pAnnoMapBase == NULL)
if (pAnnoEntryBase == NULL)
{
logWarning("file: "__FILE__", line: %d, " \
"not set annotationMap and (%s) will use " \
@ -1005,38 +1219,29 @@ static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext)
continue;
}
found = false;
nItemCnt = -1;
for (i=0; i<2; i++)
{
pAnnoMap = pAnnoMapBase;
while (pAnnoMap->func_name != NULL)
pAnnoEntry = iniFindAnnotation(pAnnoEntryBase, pFuncName);
if (pAnnoEntry != NULL)
{
if (strcmp(pFuncName, pAnnoMap->func_name) == 0)
if (pAnnoEntry->func_init != NULL && !pAnnoEntry->inited)
{
if (pAnnoMap->func_init != NULL)
{
pAnnoMap->func_init();
}
if (pAnnoMap->func_get != NULL)
{
nItemCnt = pAnnoMap->func_get(pContext,
pItem->value, pItemValues, 100);
}
found = true;
break;
pAnnoEntry->inited = true;
pAnnoEntry->func_init(pAnnoEntry);
}
pAnnoMap++;
}
if (found)
{
if (pAnnoEntry->func_get != NULL)
{
nItemCnt = pAnnoEntry->func_get(pContext,
pAnnoEntry, pItem, pItemValues, 100);
}
break;
}
if (g_annotations != NULL && pAnnoMapBase != g_annotations)
if (g_annotations != NULL && pAnnoEntryBase != g_annotations)
{
pAnnoMapBase = g_annotations;
pAnnoEntryBase = g_annotations;
}
else
{
@ -1094,9 +1299,9 @@ static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext)
}
}
if (pAnnoMap != NULL && pAnnoMap->func_free != NULL)
if (pAnnoEntry != NULL && pAnnoEntry->func_free != NULL)
{
pAnnoMap->func_free(pItemValues, nItemCnt);
pAnnoEntry->func_free(pAnnoEntry, pItemValues, nItemCnt);
}
continue;
}

View File

@ -60,10 +60,20 @@ typedef struct ini_context
typedef struct ini_annotation_entry {
char *func_name;
int (*func_init) ();
void (*func_destroy) ();
int (*func_get) (IniContext *context, char *param, char **pOutValue, int max_values);
void (*func_free) (char **values, const int count);
void *arg;
void *dlhandle;
int (*func_init) (struct ini_annotation_entry *annotation);
void (*func_destroy) (struct ini_annotation_entry *annotation);
int (*func_get) (IniContext *context,
struct ini_annotation_entry *annotation,
const IniItem *item,
char **pOutValue, int max_values);
void (*func_free) (struct ini_annotation_entry *annotation,
char **values, const int count);
bool inited;
} AnnotationEntry;
#ifdef __cplusplus
@ -76,9 +86,12 @@ extern "C" {
strcasecmp(pValue, "on") == 0 || \
strcmp(pValue, "1") == 0)
int iniSetAnnotationCallBack(AnnotationEntry *map, int count);
int iniSetAnnotationCallBack(AnnotationEntry *annotations, int count);
void iniDestroyAnnotationCallBack();
void iniAnnotationFreeValues(struct ini_annotation_entry *annotation,
char **values, const int count);
/** load ini items from file
* parameters:
* szFilename: the filename, can be an URL

View File

@ -1,6 +1,10 @@
# to support #@function CONFIG_GET
# the version of libshmcache >= 1.0.7
#@add_annotation CONFIG_GET /usr/local/lib/libshmcache.so /usr/local/etc/libshmcache.conf
#@function CONFIG_GET
app.version = app1.key1
#@set author_name = yuqing
#@set os_name = $(uname -a | awk '{print $1;}')
@ -8,7 +12,7 @@
host = hostname
#@function LOCAL_IP_GET
bind_ip = inner
bind_ip = inner[0]
#@function EXPRESS_CALC
thread_count = 5 * 4 + 6

View File

@ -11,7 +11,8 @@
#include "fastcommon/shared_func.h"
#include "fastcommon/ini_file_reader.h"
static int iniAnnotationFuncExpressCalc(IniContext *context, char *param,
static int iniAnnotationFuncExpressCalc(IniContext *context,
struct ini_annotation_entry *annotation, const IniItem *item,
char **pOutValue, int max_values)
{
int count;
@ -20,7 +21,7 @@ static int iniAnnotationFuncExpressCalc(IniContext *context, char *param,
static char output[256];
count = 0;
sprintf(cmd, "echo \'%s\' | bc -l", param);
sprintf(cmd, "echo \'%s\' | bc -l", item->value);
if ((result=getExecResult(cmd, output, sizeof(output))) != 0)
{
logWarning("file: "__FILE__", line: %d, "
@ -31,7 +32,7 @@ static int iniAnnotationFuncExpressCalc(IniContext *context, char *param,
if (*output == '\0')
{
logWarning("file: "__FILE__", line: %d, "
"empty reply when exec: %s", __LINE__, param);
"empty reply when exec: %s", __LINE__, item->value);
}
pOutValue[count++] = fc_trim(output);
return count;
@ -50,11 +51,9 @@ int main(int argc, char *argv[])
log_init();
memset(annotations, 0, sizeof(annotations));
annotations[0].func_name = "EXPRESS_CALC";
annotations[0].func_init = NULL;
annotations[0].func_destroy = NULL;
annotations[0].func_get = iniAnnotationFuncExpressCalc;
annotations[0].func_free = NULL;
//printf("sizeof(IniContext): %d\n", (int)sizeof(IniContext));
result = iniLoadFromFileEx(szFilename, &context,
@ -66,7 +65,7 @@ int main(int argc, char *argv[])
}
iniPrintItems(&context);
iniDestroyAnnotationCallBack();
iniFreeContext(&context);
return 0;
}