This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
tango-maat/src/maat_config_monitor.cpp

346 lines
8.8 KiB
C++
Raw Normal View History

2022-11-17 05:05:35 +08:00
/*
**********************************************************************************************
* File: maat_config_monitor.h
* Description: maat config monitor api
* Authors: Liu WenTan <liuwentan@geedgenetworks.com>
* Date: 2022-10-31
* Copyright: (c) 2018-2022 Geedge Networks, Inc. All rights reserved.
***********************************************************************************************
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <sys/stat.h>
2022-11-25 16:32:29 +08:00
#include <dirent.h>
2022-11-17 05:05:35 +08:00
#include "maat_config_monitor.h"
#include "maat_utils.h"
2022-11-25 16:32:29 +08:00
#include "utils.h"
2022-11-17 05:05:35 +08:00
#define CM_MAX_TABLE_NUM 256
#define MAX_CONFIG_LINE (1024 * 16)
struct cm_table_info_t
{
char table_name[NAME_MAX];
char cfg_path[NAME_MAX];
int cfg_num;
char encryp_algorithm[NAME_MAX];
};
int cm_read_cfg_index_file(const char* path, struct cm_table_info_t* idx, int size)
{
int ret = 0;
int i = 0;
char line[MAX_CONFIG_LINE];
struct stat file_info;
FILE* fp = fopen(path,"r");
while (!feof(fp)) {
memset(line, 0, sizeof(line));
fgets(line, sizeof(line), fp);
ret=sscanf(line,"%s\t%d\t%s\t%s",idx[i].table_name
,&(idx[i].cfg_num)
,idx[i].cfg_path
,idx[i].encryp_algorithm);
//jump over empty line
2022-11-25 16:32:29 +08:00
if (!(ret == 3 || ret == 4) || idx[i].cfg_num == 0) {
2022-11-17 05:05:35 +08:00
continue;
}
ret = stat(idx[i].cfg_path, &file_info);
if (ret != 0) {
//log_error
fclose(fp);
return -1;
}
i++;
if (i == size) {
//log_error
break;
}
}
fclose(fp);
return i;
}
2022-11-25 16:32:29 +08:00
const char *path2filename(const char *path)
2022-11-17 05:05:35 +08:00
{
2022-11-25 16:32:29 +08:00
int i = 0;
for (i = strlen(path);i > 0;i--) {
if (path[i]=='/') {
2022-11-17 05:05:35 +08:00
break;
}
}
2022-11-25 16:32:29 +08:00
return path + i + 1;
2022-11-17 05:05:35 +08:00
}
char *read_nxt_line_from_buff(const char *buff, size_t buff_size, size_t *offset, char *line, int line_size)
{
int this_offset=0;
const char* p;
//search for CRLF, aka CR '\r'(old Mac), LF '\n'(UNIX) or CRLF"\r\n" (Windows)
2022-11-25 16:32:29 +08:00
p = (const char *)memchr(buff + *offset, '\n', buff_size - *offset);
2022-11-17 05:05:35 +08:00
if (p == NULL) { // NOT "\n" or "\r\n"
2022-11-25 16:32:29 +08:00
p = (const char *)memchr(buff + *offset, '\r', buff_size - *offset);
2022-11-17 05:05:35 +08:00
}
if (p != NULL) { //point to next character
p++;
} else { //Treat rest buff has no CRLF as a line.
p = buff + buff_size;
}
this_offset = p - (buff + *offset);
2022-11-25 16:32:29 +08:00
memcpy(line, buff + *offset, MIN(this_offset, line_size - 1));
2022-11-17 05:05:35 +08:00
*offset += this_offset;
line[MIN(this_offset, line_size - 1)] = '\0';
return line;
}
int cm_read_table_file(struct cm_table_info_t* index,
int (*update_fn)(const char *, const char *, void *),
void* u_param)
{
int cfg_num = 0,i =0;
int ret = 0;
char line[MAX_CONFIG_LINE]={0};
char *ret_str=NULL;
char *table_file_buff=NULL;
size_t file_sz = 0;
size_t file_offset = 0;
ret = load_file_to_memory(index->cfg_path, (unsigned char **)&table_file_buff, &file_sz);
if (ret < 0) {
// log_error
return -1;
}
read_nxt_line_from_buff(table_file_buff, file_sz, &file_offset, line, sizeof(line));
sscanf(line, "%d\n", &cfg_num);
if(cfg_num != index->cfg_num) {
//log_error
return -1;
}
for (i = 0; i < cfg_num; i++) {
2022-11-25 16:32:29 +08:00
line[sizeof(line) - 1] = '\0';
2022-11-17 05:05:35 +08:00
2022-11-25 16:32:29 +08:00
ret_str = read_nxt_line_from_buff(table_file_buff, file_sz, &file_offset, line, sizeof(line));
if (ret_str == NULL) {
2022-11-17 05:05:35 +08:00
//log_error
break;
}
2022-11-25 16:32:29 +08:00
if(line[sizeof(line) - 1] != '\0') {
2022-11-17 05:05:35 +08:00
//log_error
continue;
}
ret = update_fn(index->table_name, line, u_param);
if (ret<0) {
break;
}
}
free(table_file_buff);
return 0;
}
2022-11-25 16:32:29 +08:00
//replacement of glibc scandir, to adapt dictator malloc wrap
#define ENLARGE_STEP 1024
int my_scandir(const char *dir, struct dirent ***namelist,
int(*filter)(const struct dirent *),
int(*compar)(const void *, const void *))
{
int n = 0;
int DIR_ENT_SIZE = ENLARGE_STEP;
struct dirent entry, *result;
if ((NULL == dir) || (NULL == namelist)) {
return -1;
}
DIR *od = opendir(dir);
if (NULL == od) {
return -1;
}
struct dirent **list = ALLOC(struct dirent *, DIR_ENT_SIZE);
while (0 == readdir_r(od, &entry, &result)) {
if (NULL == result) {
break;
}
if (filter && !filter(&entry)) {
continue;
}
struct dirent *p = ALLOC(struct dirent, 1);
memcpy((void *)p, (void *)(&entry), sizeof(struct dirent));
list[n] = p;
n++;
if (n >= DIR_ENT_SIZE) {
DIR_ENT_SIZE += ENLARGE_STEP;
list = (struct dirent **)realloc((void*)list, DIR_ENT_SIZE * sizeof(struct dirent *));
}
}
closedir(od);
*namelist = list;
if (compar) {
qsort((void *)*namelist, n, sizeof(struct dirent *), compar);
}
return n;
}
int filter_fn(const struct dirent *ent)
{
return (strncmp(ent->d_name,"full_config_index",strlen("full_config_index")) == 0 ||
strncmp(ent->d_name,"inc_config_index",strlen("inc_config_index")) == 0);
}
int get_new_idx_path(long long current_version, const char *file_dir, char ***idx_path, size_t *idx_num)
{
struct dirent **namelist = NULL;
int update_type = CM_UPDATE_TYPE_NONE;
int n = my_scandir(file_dir, &namelist, filter_fn, (int (*)(const void*, const void*))alphasort);
if (n < 0) {
//log_error("scan dir error");
return update_type;
}
long long latest_full_version = 0;
long long latest_inc_version = 0;
int full_file_idx = 0;
int *inc_file_idx = ALLOC(int, n);
int inc_idx_num = 0;
int i = 0;
for (i = 0; i < n; i++) {
long long config_seq = 0;
char update_str[32] = {0};
if ((strcmp(namelist[i]->d_name, ".") == 0) || (strcmp(namelist[i]->d_name, "..") == 0)) {
continue;
}
if (strlen(namelist[i]->d_name) > 42) {
//log_error("config file %s filename too long,should like full_config_index.00000000000000000001",namelist[i]->d_name);
continue;
}
int ret = sscanf(namelist[i]->d_name,"%[a-zA-Z]_config_index.%lld", update_str, &config_seq);
if (ret != 2) {
//log_error("config file %s filename error,should like full_config_index.00000000000000000001",namelist[i]->d_name);
continue;
}
if (strncasecmp(update_str, "full", strlen(update_str)) == 0) {
if (config_seq > latest_full_version) {
latest_full_version = config_seq;
full_file_idx = i;
}
} else if(strncasecmp(update_str,"inc",strlen(update_str))==0) {
if (config_seq > current_version) {
inc_file_idx[inc_idx_num] = i;
inc_idx_num++;
if (config_seq > latest_inc_version) {
latest_inc_version = config_seq;
}
}
} else {
//log_error("config file %s,not full or inc config",namelist[i]->d_name);
}
}
size_t path_len = 0;
//full update
if (latest_full_version > current_version) {
*idx_path = (char **)malloc(sizeof(char **));
path_len = strlen(file_dir) + strlen(namelist[full_file_idx]->d_name) + 1 + 1;
(*idx_path)[0] = (char *)malloc(path_len);
snprintf((*idx_path)[0], path_len, "%s/%s", file_dir, namelist[full_file_idx]->d_name);
*idx_num = 1;
update_type = CM_UPDATE_TYPE_FULL;
} else if (latest_inc_version > current_version) {
//inc update,it's possible that do inc after full update in this function,but we'll process it at next loop.
*idx_path = (char **)malloc(sizeof(char **) * inc_idx_num);
for (i = 0; i < inc_idx_num; i++) {
path_len = strlen(file_dir) + strlen(namelist[inc_file_idx[i]]->d_name) + 1 + 1;
(*idx_path)[i] = (char *)malloc(path_len);
snprintf((*idx_path)[i], path_len, "%s/%s", file_dir, namelist[inc_file_idx[i]]->d_name);
}
*idx_num = inc_idx_num;
update_type = CM_UPDATE_TYPE_INC;
} else {
update_type = CM_UPDATE_TYPE_NONE;
}
free(inc_file_idx);
for (i = 0; i < n; i++) {
free(namelist[i]);
}
free(namelist);
return update_type;
}
void config_monitor_traverse(long long current_version, const char *idx_dir,
void (*start_fn)(long long, int, void *),
2022-11-17 05:05:35 +08:00
int (*update_fn)(const char *, const char *, void *),
void (*finish_fn)(void *),
void *u_param)
{
size_t i = 0;
2022-11-25 16:32:29 +08:00
long long new_version = 0;
2022-11-17 05:05:35 +08:00
char **idx_path_array = NULL;
size_t idx_path_num = 0;
struct cm_table_info_t table_array[CM_MAX_TABLE_NUM];
memset(table_array, 0, sizeof(table_array));
2022-11-25 16:32:29 +08:00
int update_type = get_new_idx_path(current_version, idx_dir, &idx_path_array, &idx_path_num);
if (update_type != CM_UPDATE_TYPE_NONE) {
2022-11-17 05:05:35 +08:00
for (i = 0; i < idx_path_num; i++) {
int table_num = cm_read_cfg_index_file(idx_path_array[i], table_array, CM_MAX_TABLE_NUM);
if (table_num < 0) {
2022-11-25 16:32:29 +08:00
//log_error luis
2022-11-17 05:05:35 +08:00
break;
}
char str_not_care[256] = {0};
2022-11-25 16:32:29 +08:00
const char *table_filename = path2filename(idx_path_array[i]);
sscanf(table_filename, "%[a-zA-Z]_config_index.%lld", str_not_care, &new_version);
2022-11-17 05:05:35 +08:00
if (start_fn != NULL) {
start_fn(new_version, update_type, u_param);
}
for (int j = 0; j < table_num; j++) {
cm_read_table_file(table_array + j, update_fn, u_param);
}
if (finish_fn != NULL) {
finish_fn(u_param);
}
}
}
for (i = 0; i < idx_path_num; i++) {
free(idx_path_array[i]);
}
free(idx_path_array);
}