support limit

This commit is contained in:
Rongsong Shen 2026-01-12 15:20:51 +08:00
parent bef32ace38
commit ecf1916d78
33 changed files with 3036 additions and 243 deletions

379
src/lib/group.c Normal file
View file

@ -0,0 +1,379 @@
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "group.h"
#include "kvmgr.h"
#include "objmgr.h"
#include "utils.h"
#include "xce/types.h"
static void group_killer(xce_group_t* g)
{
int i;
if (g == NULL) {
return;
}
for (i = 0; i < g->members.count; i++) {
xce_g_member_t* m = (xce_g_member_t*)xlist_get(&(g->members), i);
if (!m->is_group) {
FREEUP(m->u.name);
}
FREEUP(m);
}
for (i = 0; i < g->ex_members.count; i++) {
xce_g_member_t* m = (xce_g_member_t*)xlist_get(&(g->ex_members), i);
if (!m->is_group) {
FREEUP(m->u.name);
}
FREEUP(m);
}
for (i = 0; i < g->affecteds.count; i++) {
xce_group_t* g1 = (xce_group_t*)xlist_get(&(g->affecteds), i);
xlist_del(&(g1->members), g);
xlist_del(&(g1->ex_members), g);
}
xlist_fini(&(g->members));
xlist_fini(&(g->ex_members));
xlist_fini(&(g->affecteds));
FREEUP(g->name);
FREEUP(g);
}
int groupmgr_init(groupmgr_t* mgr, int nslots, int delta)
{
int rc = 0;
xce_group_config_t all = { .name = "all" };
xce_group_config_t empty = { .name = "empty" };
xce_group_t* g = NULL;
memset(mgr, 0x0, sizeof(*mgr));
rc = kvmgr_init(&(mgr->groups), string_hash_key, nslots, delta,
(zarray_item_killer_t)group_killer);
if (rc < 0) {
return rc;
}
/* create builtin all group */
g = build_group(mgr, &all, NULL);
if (g == NULL) {
return -ENOMEM;
}
/* create builtin empty group */
g = build_group(mgr, &empty, NULL);
if (g == NULL) {
return -ENOMEM;
}
return 1;
}
void groupmgr_fini(groupmgr_t* mgr) { kvmgr_fini(&(mgr->groups)); }
int groupmgr_add(groupmgr_t* mgr, xce_group_t* g)
{
return kvmgr_add(&(mgr->groups), (void*)g->name, g);
}
xce_group_t* groupmgr_lock(groupmgr_t* mgr, char* name, int op)
{
return (xce_group_t*)kvmgr_lock(&(mgr->groups), (void*)name, op);
}
void groupmgr_del(groupmgr_t* mgr, xce_group_t* g)
{
kvmgr_del(&(mgr->groups), (void*)g->name);
}
int groupmgr_iter(groupmgr_t* mgr, xlist_t* l, void* arg)
{
return kvmgr_iter(&(mgr->groups), NULL, l, arg);
}
xce_group_t* get_group(groupmgr_t* mgr, char* name)
{
xce_group_t* g = NULL;
if ((mgr == NULL) || (name == NULL)) {
return NULL;
}
g = groupmgr_lock(mgr, name, OBJREF_NOP);
return g;
}
xce_g_member_t* make_g_member(groupmgr_t* mgr, char* name)
{
xce_g_member_t* m = NULL;
xce_group_t* g = NULL;
if ((mgr == NULL) || (name == NULL)) {
errno = EINVAL;
return NULL;
}
m = (xce_g_member_t*)calloc(1, sizeof(*m));
if (m == NULL) {
return NULL;
}
g = get_group(mgr, name);
if (g != NULL) {
m->is_group = 1;
m->u.g = g;
} else {
m->is_group = 0;
m->u.name = strdup(name);
}
return m;
}
static int update_group_dirty(xce_group_t* g)
{
int i;
int count = 0;
for (i = 0; i < g->affecteds.count; i++) {
xce_group_t* g1 = (xce_group_t*)xlist_get(&(g->affecteds), i);
if (g1 == NULL) {
continue;
}
g1->dirty = 1;
count++;
count += update_group_dirty(g1);
}
return count;
}
int fmt_group(char* buf, int len, xce_group_t* g)
{
int i, pos;
if (strcmp(g->name, "all") == 0) {
return snprintf(buf, len, "all");
}
if (strcmp(g->name, "empty") == 0) {
return snprintf(buf, len, "[]");
}
snprintf(buf, len, "[");
pos = strlen(buf);
for (i = 0; i < g->members.count; i++) {
xce_g_member_t* m = (xce_g_member_t*)xlist_get(&(g->members), i);
if (m == NULL) {
continue;
}
snprintf(buf + pos, len - pos, "%s ",
(m->is_group) ? m->u.g->name : m->u.name);
pos = strlen(buf);
}
for (i = 0; i < g->ex_members.count; i++) {
xce_g_member_t* m = (xce_g_member_t*)xlist_get(&(g->ex_members), i);
if (m == NULL) {
continue;
}
snprintf(buf + pos, len - pos, "~%s ",
(m->is_group) ? m->u.g->name : m->u.name);
pos = strlen(buf);
}
while ((pos > 0) && (buf[pos - 1] == ' ')) {
pos--;
}
snprintf(buf + pos, len - pos, "]");
return strlen(buf);
}
xce_group_t* build_group(groupmgr_t* mgr, xce_group_config_t* g_config,
char* default_group_name)
{
xce_group_t* g = NULL;
char* g_name;
int i;
if ((mgr == NULL) || (g_config == NULL)) {
errno = EINVAL;
return NULL;
}
g_name = g_config->name;
if ((g_name == NULL) || (strlen(g_name) == 0)) {
g_name = default_group_name;
}
if (g_name == NULL) {
return NULL;
}
g = get_group(mgr, g_name);
if (g != NULL) {
for (i = 0; i < g->members.count; i++) {
xce_g_member_t* m = (xce_g_member_t*)xlist_get(&(g->members), i);
if (m == NULL) {
continue;
}
if (m->is_group == 0) {
FREEUP(m->u.name);
}
FREEUP(m);
}
g->members.count = 0;
for (i = 0; i < g->ex_members.count; i++) {
xce_g_member_t* m = (xce_g_member_t*)xlist_get(&(g->ex_members), i);
if (m == NULL) {
continue;
}
if (m->is_group == 0) {
FREEUP(m->u.name);
}
FREEUP(m);
}
g->ex_members.count = 0;
g->dirty = 1;
} else {
g = (xce_group_t*)calloc(1, sizeof(*g));
if (g == NULL) {
return NULL;
}
xlist_init(&(g->affecteds), 4);
xlist_init(&(g->members), 4);
xlist_init(&(g->ex_members), 4);
g->name = strdup(g_name);
g->dirty = 0;
}
for (i = 0; i < g_config->members.count; i++) {
char* g_name = g_config->members.data[i];
xce_g_member_t* m = make_g_member(mgr, g_name);
if (m == NULL) {
continue;
}
xlist_store(&(g->members), m);
if (m->is_group) {
xlist_store(&(m->u.g->affecteds), g);
}
}
for (i = 0; i < g_config->ex_members.count; i++) {
char* g_name = g_config->ex_members.data[i];
xce_g_member_t* m = make_g_member(mgr, g_name);
if (m == NULL) {
continue;
}
xlist_store(&(g->ex_members), m);
if (m->is_group) {
xlist_store(&(m->u.g->affecteds), g);
}
}
groupmgr_add(mgr, g);
if (g->dirty) {
update_group_dirty(g);
}
return g;
}
static int check_in_member(xce_g_member_t* m, va_list ap)
{
char* name = va_arg(ap, char*);
if ((m == NULL) || (name == NULL)) {
return 0;
}
if (m->is_group) {
if (is_in_group(m->u.g, name)) {
return 1;
}
return 0;
}
if (strcmp(m->u.name, name) == 0) {
return 1;
}
return 0;
}
int is_in_group(xce_group_t* g, char* name)
{
if ((g == NULL) || (name == NULL)) {
return -EINVAL;
}
/* everything should be in all group */
if (strcmp(g->name, "all") == 0) {
return 1;
}
/* nothing is in empty group */
if (strcmp(g->name, "empty") == 0) {
return 0;
}
if (strcmp(g->name, name) == 0) {
return 1;
}
if (xlist_find(&(g->ex_members), (xlist_find_fn_t)check_in_member, name)
!= NULL) {
return 0;
}
if (xlist_find(&(g->members), (xlist_find_fn_t)check_in_member, name)
!= NULL) {
return 1;
}
return 0;
}
int is_group_all(xce_group_t* g)
{
if (g == NULL) {
return 0;
}
if (g->name == NULL) {
return 0;
}
return (strcmp(g->name, "all") == 0);
}