2 * Copyright (C) 2006-2009 Brian Aker
5 * Use and distribution licensed under the BSD license. See
6 * the COPYING file in the parent directory for full text.
13 Startup, and shutdown the memcached servers.
16 #define TEST_PORT_BASE MEMCACHED_DEFAULT_PORT+10
31 #include <libmemcached/memcached.h>
32 #include <libmemcached/util.h>
34 #include <libtest/server.h>
36 static struct timespec global_sleep_value
= { .tv_sec
= 0, .tv_nsec
= 50000 };
38 static void global_sleep(void)
43 nanosleep(&global_sleep_value
, NULL
);
47 static bool wait_for_file(const char *filename
)
54 for (waited
= 0, retry
= 1; ; retry
++, waited
+= this_wait
)
56 if ((! access(filename
, R_OK
)) || (waited
>= timeout
))
61 this_wait
= retry
* retry
/ 3 + 1;
68 static void kill_file(const char *file_buffer
)
72 while ((fp
= fopen(file_buffer
, "r")))
74 char pid_buffer
[1024];
76 if (fgets(pid_buffer
, sizeof(pid_buffer
), fp
) != NULL
)
78 pid_t pid
= (pid_t
)atoi(pid_buffer
);
81 if (kill(pid
, SIGTERM
) == -1)
83 remove(file_buffer
); // If this happens we may be dealing with a dead server that left its pid file.
88 while ((kill(pid
, 0) == 0) && --counter
)
102 void server_startup(server_startup_st
*construct
)
104 if ((construct
->server_list
= getenv("MEMCACHED_SERVERS")))
106 printf("servers %s\n", construct
->server_list
);
107 construct
->servers
= memcached_servers_parse(construct
->server_list
);
108 construct
->server_list
= NULL
;
114 char server_string_buffer
[8096];
116 end_ptr
= server_string_buffer
;
118 uint32_t port_base
= 0;
119 for (uint32_t x
= 0; x
< construct
->count
; x
++)
123 snprintf(construct
->pid_file
[x
], FILENAME_MAX
, "/tmp/memcached.pidXXXXXX");
125 if ((fd
= mkstemp(construct
->pid_file
[x
])) == -1)
134 char variable_buffer
[1024];
136 snprintf(variable_buffer
, sizeof(variable_buffer
), "LIBMEMCACHED_PORT_%u", x
);
138 if ((var
= getenv(variable_buffer
)))
140 construct
->port
[x
]= (in_port_t
)atoi(var
);
145 construct
->port
[x
]= (in_port_t
)(x
+ TEST_PORT_BASE
+ port_base
);
147 if (libmemcached_util_ping("localhost", construct
->port
[x
], NULL
))
150 construct
->port
[x
]= 0;
152 } while (construct
->port
[x
] == 0);
156 char buffer
[FILENAME_MAX
];
159 snprintf(buffer
, sizeof(buffer
), "%s -d -P %s -t 1 -p %u -U %u -m 128",
160 MEMCACHED_BINARY
, construct
->pid_file
[x
], construct
->port
[x
], construct
->port
[x
]);
164 snprintf(buffer
, sizeof(buffer
), "%s -d -P %s -t 1 -p %u -U %u",
165 MEMCACHED_BINARY
, construct
->pid_file
[x
], construct
->port
[x
], construct
->port
[x
]);
168 if (libmemcached_util_ping("localhost", construct
->port
[x
], NULL
))
170 fprintf(stderr
, "Server on port %u already exists\n", construct
->port
[x
]);
174 status
= system(buffer
);
175 fprintf(stderr
, "STARTING SERVER: %s status:%d\n", buffer
, status
);
179 size_t remaining_length
= sizeof(server_string_buffer
) - (size_t)(end_ptr
-server_string_buffer
);
180 count
= snprintf(end_ptr
, remaining_length
, "localhost:%u,", construct
->port
[x
]);
182 if ((size_t)count
>= remaining_length
|| count
< 0)
184 fprintf(stderr
, "server names grew to be larger then buffer allowed\n");
192 for (uint32_t x
= 0; x
< construct
->count
; x
++)
194 if (! wait_for_file(construct
->pid_file
[x
]))
200 for (uint32_t x
= 0; x
< construct
->count
; x
++)
202 uint32_t counter
= 3000; // Absurd, just to catch run away process
203 while (construct
->pids
[x
] <= 0 && --counter
)
205 FILE *file
= fopen(construct
->pid_file
[x
], "r");
208 char pid_buffer
[1024];
209 char *found
= fgets(pid_buffer
, sizeof(pid_buffer
), file
);
213 construct
->pids
[x
]= atoi(pid_buffer
);
216 if (construct
->pids
[x
] > 0)
224 fprintf(stderr
, "%s -> fopen(%s)\n", construct
->pid_file
[x
], strerror(errno
));
234 // Safety 3rd, check to see if the file has gone away
235 if (! wait_for_file(construct
->pid_file
[x
]))
241 bool was_started
= false;
242 if (construct
->pids
[x
] > 0)
247 if (kill(construct
->pids
[x
], 0) == 0)
256 if (was_started
== false)
258 fprintf(stderr
, "Failed to open buffer %s(%d)\n", construct
->pid_file
[x
], construct
->pids
[x
]);
259 for (uint32_t y
= 0; y
< construct
->count
; y
++)
261 if (construct
->pids
[y
] > 0)
262 kill(construct
->pids
[y
], SIGTERM
);
268 construct
->server_list
= strdup(server_string_buffer
);
270 printf("servers %s\n", construct
->server_list
);
271 construct
->servers
= memcached_servers_parse(construct
->server_list
);
274 assert(construct
->servers
);
276 srandom((unsigned int)time(NULL
));
278 for (uint32_t x
= 0; x
< memcached_server_list_count(construct
->servers
); x
++)
280 printf("\t%s : %d\n", memcached_server_name(&construct
->servers
[x
]), memcached_server_port(&construct
->servers
[x
]));
281 assert(construct
->servers
[x
].fd
== -1);
282 assert(construct
->servers
[x
].cursor_active
== 0);
288 void server_shutdown(server_startup_st
*construct
)
290 if (construct
->server_list
)
292 for (uint32_t x
= 0; x
< construct
->count
; x
++)
294 kill_file(construct
->pid_file
[x
]);
297 free(construct
->server_list
);