Skip to content

Commit d9afe10

Browse files
committed
Using hash tables to replace arrays in process spawning
1 parent ad7313b commit d9afe10

File tree

2 files changed

+151
-25
lines changed

2 files changed

+151
-25
lines changed

respawn.c

Lines changed: 150 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,111 @@
1313
#include "tools.h"
1414

1515
#define RESPAWN_FILE "/etc/ueld/respawn.list"
16-
#define MAX_APP 32
16+
#define HASHTABLE_FIRST_NODE_SIZE 32
1717

18-
struct respawn_app {
18+
struct respawn_node {
19+
int nref;
1920
int vt;
2021
pid_t pid;
21-
char* cmd;
22+
char *cmd;
23+
struct respawn_node *next;
2224
};
2325

24-
static struct respawn_app apps[MAX_APP];
25-
static unsigned int appssz = 0;
26+
static struct respawn_node *first_nodes[HASHTABLE_FIRST_NODE_SIZE];
27+
static unsigned int disable = 0;
2628

2729
static size_t length;
28-
static char* respawn;
30+
static char *respawn;
2931

30-
static void runapp(struct respawn_app* app)
32+
#define hashpid(pid) ((pid) % HASHTABLE_FIRST_NODE_SIZE)
33+
#define nodefree(node) (free(node))
34+
#define noderef(node) (((node)->nref)++)
35+
36+
#ifdef __GNUC__
37+
#define likely(x) __builtin_expect((x),1)
38+
#define unlikely(x) __builtin_expect((x),0)
39+
#else
40+
#define likely(x) (x)
41+
#define unlikely(x) (x)
42+
#endif /* __GNUC__ */
43+
44+
static struct respawn_node *nodenew()
45+
{
46+
static struct respawn_node *node;
47+
48+
if ((node = malloc(sizeof(struct respawn_node))) == NULL) {
49+
return NULL;
50+
}
51+
52+
node->nref = 1;
53+
return node;
54+
}
55+
56+
static void nodeunref(struct respawn_node *node)
57+
{
58+
node->nref = node->nref - 1;
59+
if (node->nref <= 0) {
60+
nodefree(node);
61+
}
62+
}
63+
64+
static void insert(pid_t key, struct respawn_node *node)
65+
{
66+
int index = hashpid(key);
67+
68+
noderef(node);
69+
node->next = NULL;
70+
71+
if (first_nodes[index] == NULL) {
72+
first_nodes[index] = node;
73+
} else {
74+
struct respawn_node *prenode = first_nodes[index];
75+
while (prenode->next != NULL) {
76+
prenode = prenode->next;
77+
}
78+
prenode->next = node;
79+
}
80+
}
81+
82+
static struct respawn_node *get(pid_t key)
83+
{
84+
int index = hashpid(key);
85+
86+
struct respawn_node *node = first_nodes[index];
87+
while (node != NULL) {
88+
if (node->pid == key) {
89+
return node;
90+
}
91+
92+
node = node->next;
93+
}
94+
95+
return NULL;
96+
}
97+
98+
static void delete(pid_t key)
99+
{
100+
int index = hashpid(key);
101+
102+
struct respawn_node *prenode = NULL;
103+
struct respawn_node *node = first_nodes[index];
104+
while (node != NULL) {
105+
if (node->pid == key) {
106+
if (prenode) {
107+
prenode->next = node->next;
108+
} else {
109+
first_nodes[index] = node->next;
110+
}
111+
112+
nodeunref(node);
113+
}
114+
115+
prenode = node;
116+
node = node->next;
117+
}
118+
}
119+
120+
static pid_t runapp(struct respawn_node* app)
31121
{
32122
pid_t pid;
33123

@@ -39,11 +129,14 @@ static void runapp(struct respawn_app* app)
39129

40130
if (pid < 0) pid = 0;
41131
app->pid = pid;
132+
133+
return pid;
42134
}
43135

44136
void respawn_init()
45137
{
46138
int fd;
139+
int appssz = 0;
47140
char *p, *vt, *cmd;
48141

49142
if ((fd = open(RESPAWN_FILE, O_RDONLY)) < 0)
@@ -75,11 +168,25 @@ void respawn_init()
75168
*p = 0;
76169
p++;
77170

78-
apps[appssz].vt = atoi(vt);
79-
apps[appssz].pid = 0;
80-
apps[appssz].cmd = cmd;
171+
struct respawn_node *node;
172+
if ((node = nodenew()) != NULL) {
173+
node->vt = atoi(vt);
174+
node->pid = 0;
175+
node->cmd = cmd;
176+
177+
pid_t pid = runapp(node);
178+
179+
if (unlikely(pid <= 0)) {
180+
ueld_print("Run respwan process '%s' first time failed\n", cmd);
181+
} else {
182+
appssz++;
183+
insert(pid, node);
184+
}
81185

82-
runapp(&apps[appssz++]);
186+
nodeunref(node);
187+
} else {
188+
ueld_print("Create respwan node for '%s' failed\n", cmd);
189+
}
83190
}
84191

85192
if (!appssz)
@@ -88,25 +195,44 @@ void respawn_init()
88195

89196
void respawnpid(pid_t pid)
90197
{
91-
for (int i = 0; i < appssz; i++) {
92-
if (apps[i].pid == pid) {
93-
runapp(&apps[i]);
94-
break;
198+
if (disable) {
199+
return;
200+
}
201+
202+
struct respawn_node *node;
203+
if ((node = get(pid)) != NULL) {
204+
pid_t newpid = runapp(node);
205+
206+
if (unlikely(newpid <= 0)) {
207+
ueld_print("Respwan process '%s' failed, remove it from list...\n", node->cmd);
208+
delete(node->pid);
209+
} else {
210+
noderef(node);
211+
delete(node->pid);
212+
node->pid = newpid;
213+
insert(newpid, node);
214+
nodeunref(node);
95215
}
96216
}
97217
}
98218

99219
void clearpid(pid_t pid)
100220
{
101-
if (pid == 0) {
102-
munmap(respawn, length);
103-
appssz = 0;
104-
}
105-
106-
for (int i = 0; i < appssz; i++) {
107-
if (apps[i].pid == pid) {
108-
apps[i].pid = 0;
109-
break;
221+
if (pid != 0) {
222+
delete(pid);
223+
} else {
224+
disable = 1;
225+
for (int i = 0; i < HASHTABLE_FIRST_NODE_SIZE; i++) {
226+
if (first_nodes[i] != NULL) {
227+
struct respawn_node *node = first_nodes[i];
228+
while (node->next != NULL) {
229+
struct respawn_node *tmp = node;
230+
node = node->next;
231+
nodeunref(tmp);
232+
}
233+
nodeunref(node);
234+
first_nodes[i] = NULL;
235+
}
110236
}
111237
}
112238
}

version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.5.1-unstable
1+
0.6.0-unstable

0 commit comments

Comments
 (0)