blob: 568ffffafe79286cde7e35b30abcf2e44b2c7f58 [file] [log] [blame]
nstrazf307d5f2000-09-14 21:54:44 +00001/*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License along
Wanlong Gaofed96412012-10-24 10:10:29 +080020 * with this program; if not, write the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
nstrazf307d5f2000-09-14 21:54:44 +000022 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
31 *
32 */
subrata_modak676ac982009-06-09 17:59:46 +000033/* $Id: zoolib.c,v 1.8 2009/06/09 17:59:46 subrata_modak Exp $ */
Garrett Cooper1e6f5a62010-12-19 09:58:10 -080034/*
nstrazcde46c82001-03-08 19:13:21 +000035 * ZooLib
36 *
37 * A Zoo is a file used to record what test tags are running at the moment.
38 * If the system crashes, we should be able to look at the zoo file to find out
39 * what was currently running. This is especially helpful when running multiple
Garrett Cooper1e6f5a62010-12-19 09:58:10 -080040 * tests at the same time.
nstrazcde46c82001-03-08 19:13:21 +000041 *
42 * The zoo file is meant to be a text file that fits on a standard console.
43 * You should be able to watch it with `cat zoofile`
44 *
45 * zoo file format:
46 * 80 characters per line, ending with a \n
47 * available lines start with '#'
48 * expected line fromat: pid_t,tag,cmdline
49 *
50 */
51
Garrett Cooper80a305e2011-02-23 00:11:13 -080052#include <signal.h>
Wanlong Gao354ebb42012-12-07 10:10:04 +080053#include <stdlib.h> /* for getenv */
nstrazcd87d682000-09-21 20:42:31 +000054#include <string.h>
nstrazf307d5f2000-09-14 21:54:44 +000055#include "zoolib.h"
56
vapier65490702006-06-27 09:37:34 +000057char zoo_error[ZELEN];
58
nstrazd5d51ca2001-02-28 17:41:59 +000059#ifdef __linux__
60/* glibc2.2 definition needs -D_XOPEN_SOURCE, which breaks other things. */
Wanlong Gao354ebb42012-12-07 10:10:04 +080061extern int sighold(int __sig);
62extern int sigrelse(int __sig);
nstrazd5d51ca2001-02-28 17:41:59 +000063#endif
64
Garrett Cooper1e6f5a62010-12-19 09:58:10 -080065/* zoo_mark(): private function to make an entry to the zoo
nstrazcde46c82001-03-08 19:13:21 +000066 * returns 0 on success, -1 on error */
67static int zoo_mark(zoo_t z, char *entry);
68static int zoo_lock(zoo_t z);
69static int zoo_unlock(zoo_t z);
70/* cat_args(): helper function to make cmdline from argc, argv */
71char *cat_args(int argc, char **argv);
nstrazf307d5f2000-09-14 21:54:44 +000072
nstrazcde46c82001-03-08 19:13:21 +000073/* zoo_getname(): create a filename to use for the zoo */
Wanlong Gao354ebb42012-12-07 10:10:04 +080074char *zoo_getname()
nstrazf307d5f2000-09-14 21:54:44 +000075{
Wanlong Gao354ebb42012-12-07 10:10:04 +080076 char buf[1024];
77 char *zoo;
Garrett Cooper1e6f5a62010-12-19 09:58:10 -080078
Wanlong Gao354ebb42012-12-07 10:10:04 +080079 zoo = getenv("ZOO");
80 if (zoo) {
81 snprintf(buf, 1024, "%s/%s", zoo, "active");
82 return strdup(buf);
83 } else {
84 /* if there is no environment variable, we don't know where to put it */
85 return NULL;
86 }
nstrazf307d5f2000-09-14 21:54:44 +000087}
88
nstrazcde46c82001-03-08 19:13:21 +000089/* zoo_open(): open a zoo for use */
Wanlong Gao354ebb42012-12-07 10:10:04 +080090zoo_t zoo_open(char *zooname)
nstrazf307d5f2000-09-14 21:54:44 +000091{
Wanlong Gao354ebb42012-12-07 10:10:04 +080092 zoo_t new_zoo;
nstrazf307d5f2000-09-14 21:54:44 +000093
Wanlong Gao354ebb42012-12-07 10:10:04 +080094 new_zoo = (zoo_t) fopen(zooname, "r+");
95 if (!new_zoo) {
96 if (errno == ENOENT) {
97 /* file doesn't exist, try fopen(xxx, "a+") */
98 new_zoo = (zoo_t) fopen(zooname, "a+");
99 if (!new_zoo) {
100 /* total failure */
101 snprintf(zoo_error, ZELEN,
102 "Could not open zoo as \"%s\", errno:%d %s",
103 zooname, errno, strerror(errno));
104 return 0;
105 }
106 fclose(new_zoo);
107 new_zoo = fopen(zooname, "r+");
108 } else {
109 snprintf(zoo_error, ZELEN,
110 "Could not open zoo as \"%s\", errno:%d %s",
111 zooname, errno, strerror(errno));
112 }
nstrazf307d5f2000-09-14 21:54:44 +0000113 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800114 return new_zoo;
nstrazf307d5f2000-09-14 21:54:44 +0000115}
116
Wanlong Gao354ebb42012-12-07 10:10:04 +0800117int zoo_close(zoo_t z)
nstrazf307d5f2000-09-14 21:54:44 +0000118{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800119 int ret;
nstrazf307d5f2000-09-14 21:54:44 +0000120
Wanlong Gao354ebb42012-12-07 10:10:04 +0800121 ret = fclose(z);
122 if (ret) {
nstrazcde46c82001-03-08 19:13:21 +0000123 snprintf(zoo_error, ZELEN,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800124 "closing zoo caused error, errno:%d %s",
125 errno, strerror(errno));
126 }
127 return ret;
128}
129
130static int zoo_mark(zoo_t z, char *entry)
131{
132 FILE *fp = (FILE *) z;
133 int found = 0;
134 long pos;
135 char buf[BUFLEN];
136
137 if (fp == NULL)
nstrazcde46c82001-03-08 19:13:21 +0000138 return -1;
nstrazf307d5f2000-09-14 21:54:44 +0000139
Wanlong Gao354ebb42012-12-07 10:10:04 +0800140 if (zoo_lock(z))
nstrazcde46c82001-03-08 19:13:21 +0000141 return -1;
Wanlong Gao354ebb42012-12-07 10:10:04 +0800142
143 /* first fit */
144 rewind(fp);
145
146 do {
147 pos = ftell(fp);
148
149 if (fgets(buf, BUFLEN, fp) == NULL)
150 break;
151
152 if (buf[0] == '#') {
153 rewind(fp);
154 if (fseek(fp, pos, SEEK_SET)) {
155 /* error */
156 snprintf(zoo_error, ZELEN,
157 "seek error while writing to zoo file, errno:%d %s",
158 errno, strerror(errno));
159 return -1;
160 }
161 /* write the entry, left justified, and padded/truncated to the
162 * same size as the previous entry */
163 fprintf(fp, "%-*.*s\n", (int)strlen(buf) - 1,
164 (int)strlen(buf) - 1, entry);
165 found = 1;
166 break;
167 }
168 } while (1);
169
170 if (!found) {
171 if (fseek(fp, 0, SEEK_END)) {
172 snprintf(zoo_error, ZELEN,
173 "error seeking to end of zoo file, errno:%d %s",
174 errno, strerror(errno));
175 return -1;
176 }
177 fprintf(fp, "%-*.*s\n", 79, 79, entry);
nstrazf307d5f2000-09-14 21:54:44 +0000178 }
Wanlong Gao354ebb42012-12-07 10:10:04 +0800179 fflush(fp);
nstrazcde46c82001-03-08 19:13:21 +0000180
Wanlong Gao354ebb42012-12-07 10:10:04 +0800181 if (zoo_unlock(z))
182 return -1;
183 return 0;
184}
nstrazcde46c82001-03-08 19:13:21 +0000185
Wanlong Gao354ebb42012-12-07 10:10:04 +0800186int zoo_mark_cmdline(zoo_t z, pid_t p, char *tag, char *cmdline)
187{
188 char new_entry[BUFLEN];
nstrazcde46c82001-03-08 19:13:21 +0000189
Wanlong Gao354ebb42012-12-07 10:10:04 +0800190 snprintf(new_entry, 80, "%d,%s,%s", p, tag, cmdline);
191 return zoo_mark(z, new_entry);
192}
193
194int zoo_mark_args(zoo_t z, pid_t p, char *tag, int ac, char **av)
195{
196 char *cmdline;
197 int ret;
198
199 cmdline = cat_args(ac, av);
200 ret = zoo_mark_cmdline(z, p, tag, cmdline);
201
202 free(cmdline);
203 return ret;
204}
205
206int zoo_clear(zoo_t z, pid_t p)
207{
208 FILE *fp = (FILE *) z;
209 long pos;
210 char buf[BUFLEN];
211 pid_t that_pid;
212 int found = 0;
213
214 if (fp == NULL)
215 return -1;
216
217 if (zoo_lock(z))
218 return -1;
219 rewind(fp);
220
221 do {
222 pos = ftell(fp);
223
224 if (fgets(buf, BUFLEN, fp) == NULL)
225 break;
226
227 if (buf[0] == '#')
228 continue;
229
230 that_pid = atoi(buf);
231 if (that_pid == p) {
232 if (fseek(fp, pos, SEEK_SET)) {
233 /* error */
234 snprintf(zoo_error, ZELEN,
235 "seek error while writing to zoo file, errno:%d %s",
236 errno, strerror(errno));
237 return -1;
238 }
239 if (ftell(fp) != pos) {
240 printf("fseek failed\n");
241 }
242 fputs("#", fp);
243 found = 1;
244 break;
245 }
246 } while (1);
247
248 fflush(fp);
249
250 /* FIXME: unlock zoo file */
251 if (zoo_unlock(z))
252 return -1;
253
254 if (!found) {
255 snprintf(zoo_error, ZELEN,
256 "zoo_clear() did not find pid(%d)", p);
257 return 1;
258 }
259 return 0;
nstrazcde46c82001-03-08 19:13:21 +0000260
261}
262
Wanlong Gao354ebb42012-12-07 10:10:04 +0800263pid_t zoo_getpid(zoo_t z, char *tag)
nstrazcde46c82001-03-08 19:13:21 +0000264{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800265 FILE *fp = (FILE *) z;
266 char buf[BUFLEN], *s;
267 pid_t this_pid = -1;
nstrazcde46c82001-03-08 19:13:21 +0000268
Wanlong Gao354ebb42012-12-07 10:10:04 +0800269 if (fp == NULL)
270 return -1;
nstrazcde46c82001-03-08 19:13:21 +0000271
Wanlong Gao354ebb42012-12-07 10:10:04 +0800272 if (zoo_lock(z))
273 return -1;
nstrazcde46c82001-03-08 19:13:21 +0000274
Wanlong Gao354ebb42012-12-07 10:10:04 +0800275 rewind(fp);
276 do {
277 if (fgets(buf, BUFLEN, fp) == NULL)
278 break;
nstrazcde46c82001-03-08 19:13:21 +0000279
Wanlong Gao354ebb42012-12-07 10:10:04 +0800280 if (buf[0] == '#')
281 continue; /* recycled line */
nstrazcde46c82001-03-08 19:13:21 +0000282
Wanlong Gao354ebb42012-12-07 10:10:04 +0800283 if ((s = strchr(buf, ',')) == NULL)
284 continue; /* line was not expected format */
nstrazcde46c82001-03-08 19:13:21 +0000285
Wanlong Gao354ebb42012-12-07 10:10:04 +0800286 if (strncmp(s + 1, tag, strlen(tag)))
287 continue; /* tag does not match */
nstrazcde46c82001-03-08 19:13:21 +0000288
Wanlong Gao354ebb42012-12-07 10:10:04 +0800289 this_pid = atoi(buf);
290 break;
291 } while (1);
nstrazcde46c82001-03-08 19:13:21 +0000292
Wanlong Gao354ebb42012-12-07 10:10:04 +0800293 if (zoo_unlock(z))
294 return -1;
295 return this_pid;
nstrazcde46c82001-03-08 19:13:21 +0000296}
297
Wanlong Gao354ebb42012-12-07 10:10:04 +0800298int zoo_lock(zoo_t z)
nstrazcde46c82001-03-08 19:13:21 +0000299{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800300 FILE *fp = (FILE *) z;
301 struct flock zlock;
302 sigset_t block_these;
303 int ret;
Garrett Cooper1e6f5a62010-12-19 09:58:10 -0800304
Wanlong Gao354ebb42012-12-07 10:10:04 +0800305 if (fp == NULL)
306 return -1;
nstrazcde46c82001-03-08 19:13:21 +0000307
Wanlong Gao354ebb42012-12-07 10:10:04 +0800308 zlock.l_whence = zlock.l_start = zlock.l_len = 0;
309 zlock.l_type = F_WRLCK;
nstrazcde46c82001-03-08 19:13:21 +0000310
Wanlong Gao354ebb42012-12-07 10:10:04 +0800311 sigemptyset(&block_these);
312 sigaddset(&block_these, SIGINT);
313 sigaddset(&block_these, SIGTERM);
314 sigaddset(&block_these, SIGHUP);
315 sigaddset(&block_these, SIGUSR1);
316 sigaddset(&block_these, SIGUSR2);
317 sigprocmask(SIG_BLOCK, &block_these, NULL);
nstrazcde46c82001-03-08 19:13:21 +0000318
Wanlong Gao354ebb42012-12-07 10:10:04 +0800319 do {
320 ret = fcntl(fileno(fp), F_SETLKW, &zlock);
321 } while (ret == -1 && errno == EINTR);
nstrazcde46c82001-03-08 19:13:21 +0000322
Wanlong Gao354ebb42012-12-07 10:10:04 +0800323 sigprocmask(SIG_UNBLOCK, &block_these, NULL);
324 if (ret == -1) {
325 snprintf(zoo_error, ZELEN,
326 "failed to unlock zoo file, errno:%d %s",
327 errno, strerror(errno));
328 return -1;
329 }
330 return 0;
nstrazcde46c82001-03-08 19:13:21 +0000331
332}
333
Wanlong Gao354ebb42012-12-07 10:10:04 +0800334int zoo_unlock(zoo_t z)
nstrazcde46c82001-03-08 19:13:21 +0000335{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800336 FILE *fp = (FILE *) z;
337 struct flock zlock;
338 sigset_t block_these;
339 int ret;
Garrett Cooper1e6f5a62010-12-19 09:58:10 -0800340
Wanlong Gao354ebb42012-12-07 10:10:04 +0800341 if (fp == NULL)
342 return -1;
nstrazcde46c82001-03-08 19:13:21 +0000343
Wanlong Gao354ebb42012-12-07 10:10:04 +0800344 zlock.l_whence = zlock.l_start = zlock.l_len = 0;
345 zlock.l_type = F_UNLCK;
nstrazcde46c82001-03-08 19:13:21 +0000346
Wanlong Gao354ebb42012-12-07 10:10:04 +0800347 sigemptyset(&block_these);
348 sigaddset(&block_these, SIGINT);
349 sigaddset(&block_these, SIGTERM);
350 sigaddset(&block_these, SIGHUP);
351 sigaddset(&block_these, SIGUSR1);
352 sigaddset(&block_these, SIGUSR2);
353 sigprocmask(SIG_BLOCK, &block_these, NULL);
nstrazcde46c82001-03-08 19:13:21 +0000354
Wanlong Gao354ebb42012-12-07 10:10:04 +0800355 do {
356 ret = fcntl(fileno(fp), F_SETLKW, &zlock);
357 } while (ret == -1 && errno == EINTR);
nstrazcde46c82001-03-08 19:13:21 +0000358
Wanlong Gao354ebb42012-12-07 10:10:04 +0800359 sigprocmask(SIG_UNBLOCK, &block_these, NULL);
nstrazcde46c82001-03-08 19:13:21 +0000360
Wanlong Gao354ebb42012-12-07 10:10:04 +0800361 if (ret == -1) {
362 snprintf(zoo_error, ZELEN,
363 "failed to lock zoo file, errno:%d %s",
364 errno, strerror(errno));
365 return -1;
366 }
367 return 0;
nstrazf307d5f2000-09-14 21:54:44 +0000368}
369
Wanlong Gao354ebb42012-12-07 10:10:04 +0800370char *cat_args(int argc, char **argv)
nstrazf307d5f2000-09-14 21:54:44 +0000371{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800372 int a, size;
373 char *cmd;
nstrazf307d5f2000-09-14 21:54:44 +0000374
Wanlong Gao354ebb42012-12-07 10:10:04 +0800375 for (size = a = 0; a < argc; a++) {
376 size += strlen(argv[a]);
377 size++;
378 }
nstrazf307d5f2000-09-14 21:54:44 +0000379
Wanlong Gao354ebb42012-12-07 10:10:04 +0800380 if ((cmd = (char *)malloc(size)) == NULL) {
381 snprintf(zoo_error, ZELEN,
382 "Malloc Error, %s/%d", __FILE__, __LINE__);
383 return NULL;
384 }
nstrazf307d5f2000-09-14 21:54:44 +0000385
Wanlong Gao354ebb42012-12-07 10:10:04 +0800386 *cmd = '\0';
387 for (a = 0; a < argc; a++) {
388 if (a != 0)
389 strcat(cmd, " ");
390 strcat(cmd, argv[a]);
391 }
nstrazf307d5f2000-09-14 21:54:44 +0000392
Wanlong Gao354ebb42012-12-07 10:10:04 +0800393 return cmd;
nstrazf307d5f2000-09-14 21:54:44 +0000394}
nstrazcde46c82001-03-08 19:13:21 +0000395
396#if defined(UNIT_TEST)
397
Wanlong Gao354ebb42012-12-07 10:10:04 +0800398void zt_add(zoo_t z, int n)
nstrazcde46c82001-03-08 19:13:21 +0000399{
Wanlong Gao354ebb42012-12-07 10:10:04 +0800400 char cmdline[200];
401 char tag[10];
nstrazcde46c82001-03-08 19:13:21 +0000402
Wanlong Gao354ebb42012-12-07 10:10:04 +0800403 snprintf(tag, 10, "%s%d", "test", n);
404 snprintf(cmdline, 200, "%s%d %s %s %s", "runtest", n, "one", "two",
405 "three");
Garrett Cooper1e6f5a62010-12-19 09:58:10 -0800406
Wanlong Gao354ebb42012-12-07 10:10:04 +0800407 zoo_mark_cmdline(z, n, tag, cmdline);
nstrazcde46c82001-03-08 19:13:21 +0000408}
Garrett Cooper1e6f5a62010-12-19 09:58:10 -0800409
Wanlong Gao354ebb42012-12-07 10:10:04 +0800410int main(int argc, char *argv[])
nstrazcde46c82001-03-08 19:13:21 +0000411{
412
Wanlong Gao354ebb42012-12-07 10:10:04 +0800413 char *zooname;
414 zoo_t test_zoo;
415 char *test_tag = "unittest";
416 int i, j;
nstrazcde46c82001-03-08 19:13:21 +0000417
Wanlong Gao354ebb42012-12-07 10:10:04 +0800418 zooname = zoo_getname();
nstrazcde46c82001-03-08 19:13:21 +0000419
Wanlong Gao354ebb42012-12-07 10:10:04 +0800420 if (!zooname) {
421 zooname = strdup("test_zoo");
422 }
423 printf("Test zoo filename is %s\n", zooname);
nstrazcde46c82001-03-08 19:13:21 +0000424
Wanlong Gao354ebb42012-12-07 10:10:04 +0800425 if ((test_zoo = zoo_open(zooname)) == NULL) {
426 printf("Error opennning zoo\n");
427 exit(-1);
nstrazcde46c82001-03-08 19:13:21 +0000428 }
Garrett Cooper1e6f5a62010-12-19 09:58:10 -0800429
Wanlong Gao354ebb42012-12-07 10:10:04 +0800430 zoo_mark_args(test_zoo, getpid(), test_tag, argc, argv);
431
432 for (j = 0; j < 5; j++) {
433 for (i = 0; i < 20; i++) {
434 zt_add(test_zoo, i);
435 }
436
437 for (; i >= 0; i--) {
438 zoo_clear(test_zoo, i);
439 }
nstrazcde46c82001-03-08 19:13:21 +0000440 }
Garrett Cooper1e6f5a62010-12-19 09:58:10 -0800441
Wanlong Gao354ebb42012-12-07 10:10:04 +0800442 zoo_clear(test_zoo, getpid());
Garrett Cooper1e6f5a62010-12-19 09:58:10 -0800443
Wanlong Gao354ebb42012-12-07 10:10:04 +0800444 return 0;
nstrazcde46c82001-03-08 19:13:21 +0000445}
446
Garrett Cooper80a305e2011-02-23 00:11:13 -0800447#endif