sm_statd.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 435 行
C
435 行
# ifndef lintstatic char *sccsid = "@(#)sm_statd.c 4.1 (ULTRIX) 7/2/90";# endif not lint/**************************************************************** * * * Licensed to Digital Equipment Corporation, Maynard, MA * * Copyright 1985 Sun Microsystems, Inc. * * All rights reserved. * * * ****************************************************************//**//* * Modification history: * ~~~~~~~~~~~~~~~~~~~~ * * revision comments * -------- ----------------------------------------------- * * 18-Jan-88 fries * Added Header and Copyright notice. * * */#include <stdio.h>#include <sys/types.h>#include <sys/file.h>#include <sys/dir.h>#include <rpc/rpc.h>#include <rpcsvc/sm_inter.h>#include <errno.h>#include "sm_statd.h"#define MAXPGSIZE 8192#define SM_INIT_ALARM 15extern int debug;extern int errno;extern char STATE[20], CURRENT[20], BACKUP[20];int LOCAL_STATE;struct name_entry { char *name; int count; struct name_entry *prev; struct name_entry *nxt;};typedef struct name_entry name_entry;name_entry *find_name();name_entry *insert_name();name_entry *record_q;name_entry *recovery_q;char hostname[MAXNAMLEN];sm_notify(ntfp)stat_chge *ntfp;{ if(debug) printf("sm_notify: %s state =%d\n", ntfp->name, ntfp->state); send_notice(ntfp->name, ntfp->state);}/* * called when statd first comes up; it searches /etc/sm to gather * all entries to notify its own failure */statd_init(){ int cc, fd; char buf[MAXPGSIZE]; long base; int nbytes; struct direct dir, *dirp; char *bufp; int len; name_entry *nl; char from[MAXNAMLEN], to[MAXNAMLEN], path[MAXNAMLEN]; FILE *fp, *fopen(); int err; if(debug) printf("enter statd_init\n"); gethostname(hostname, MAXNAMLEN); if((fp = fopen(STATE, "a+")) == NULL) { fprintf(stderr, "fopen(stat file) error\n"); exit(1); } if(fseek(fp, 0, 0) == -1) { perror("fseek"); fprintf(stderr, "\n"); exit(1); } if((cc = fscanf(fp, "%d", &LOCAL_STATE)) == EOF) { if(debug >= 2) printf("empty file\n"); LOCAL_STATE = 0; } if(LOCAL_STATE % 2 == 0) LOCAL_STATE = LOCAL_STATE +1; else LOCAL_STATE = LOCAL_STATE + 2; if(fseek(fp, 0, 0) == -1) { perror("fseek"); fprintf(stderr, "\n"); exit(1); } fprintf(fp, "%d", LOCAL_STATE); fflush(fp); if(fsync(fileno(fp)) == -1) { perror("fsync"); fprintf(stderr, "\n"); exit(1); } fclose(fp); if(debug) printf("local state = %d\n", LOCAL_STATE); if((mkdir(CURRENT, 00777)) == -1) { if(errno != EEXIST) { perror("mkdir current"); fprintf(stderr, "\n"); exit(1); } } if((mkdir(BACKUP, 00777)) == -1) { if(errno != EEXIST) { perror("mkdir backup"); fprintf(stderr, "\n"); exit(1); } } /* get all entries in CURRENT into BACKUP */ if((fd = open(CURRENT, O_RDONLY, 00200)) == -1) { perror("open current directory"); fprintf(stderr, "\n"); exit(1); } if((cc = getdirentries(fd, buf, 8192, &base)) == -1) { perror("getdirentries"); fprintf(stderr, "\n"); exit(1); } bufp = buf; len = 0; while( cc > 0) { bufp = bufp + len; dirp = (struct direct *)bufp; len = dirp -> d_reclen;/* printf("len = %d\n", len); printf("d_name = %s\n", dirp->d_name);*/ if(strcmp(dirp->d_name, ".") != 0 && strcmp(dirp->d_name, "..") != 0) { /* rename all entries from CURRENT to BACKUP */ strcpy(from , CURRENT); strcpy(to, BACKUP); strcat(from, "/"); strcat(to, "/"); strcat(from, dirp->d_name); strcat(to, dirp->d_name); if(rename(from, to) == -1) { perror("rename"); fprintf(stderr, "\n"); exit(1); } if(debug >= 2) printf("rename: %s to %s\n", from ,to); } cc = cc - len; } if(close(fd) == -1) { perror("close current directory\n"); fprintf(stderr, "\n"); exit(1); } /* get all entries in BACKUP into recovery_q */ if((fd = open(BACKUP, O_RDONLY, 00200)) == -1) { perror("open backup directory"); fprintf(stderr, "\n"); exit(1); } if((cc = getdirentries(fd, buf, 8192, &base)) == -1) { perror("getdirentries"); fprintf(stderr, "\n"); exit(1); } bufp = buf; len = 0; while( cc > 0) { bufp = bufp + len; dirp = (struct direct *)bufp; len = dirp -> d_reclen; if(strcmp(dirp->d_name, ".") != 0 && strcmp(dirp->d_name, "..") != 0) { /* get all entries from BACKUP to recovery_q */ if((err = statd_call_statd(dirp->d_name))!=0 ) { insert_name(&recovery_q, dirp->d_name); } else { /* remove from BACKUP directory */ strcpy(path, BACKUP); strcat(path, "/"); strcat(path, dirp->d_name); if(debug >= 2) printf("remove monitor entry %s\n", path); if(unlink(path) == -1) { perror(path); fprintf(stderr, "\n"); exit(1); } } } cc = cc - len; } if(close(fd) == -1) { perror("close current directory\n"); fprintf(stderr, "\n"); exit(1); } /* notify statd */ if(recovery_q != NULL) alarm(SM_INIT_ALARM);}xdr_notify(xdrs, ntfp)XDR *xdrs;stat_chge *ntfp;{ if(!xdr_string(xdrs, &ntfp->name, MAXNAMLEN+1)) { return(FALSE); } if(!xdr_int(xdrs, &ntfp->state)) { return(FALSE); } return(TRUE);}statd_call_statd(name)char *name;{ stat_chge ntf; int err; ntf.name =hostname; ntf.state = LOCAL_STATE; if(debug) printf("statd_call_statd at %s\n", name); if((err = call_tcp(name, SM_PROG, SM_VERS, SM_NOTIFY, xdr_notify, &ntf, xdr_void, NULL, 0)) == (int) RPC_TIMEDOUT || err == (int) RPC_SUCCESS) { return(0); } else { fprintf(stderr, "statd cannot talk to statd at %s\n", name); return(-1); }}sm_try(){ name_entry *nl, *next; if(debug >= 2) printf("enter sm_try: recovery_q = %s\n", recovery_q->name); next = recovery_q; while((nl = next) != NULL) { next = next->nxt; if(statd_call_statd(nl->name) == 0) { /* remove entry from recovery_q */ delete_name(&recovery_q, nl->name); } } if(recovery_q != NULL) alarm(SM_INIT_ALARM);}char *xmalloc(len)unsigned len;{ char *new; if((new = (char *)malloc(len)) == 0) { perror("malloc"); fprintf(stderr, "\n"); return(NULL); } else { bzero(new, len); return(new); }}/* * the following two routines are very similar to * insert_mon and delete_mon in sm_proc.c, except the structture * is different */name_entry *insert_name(namepp, name)name_entry **namepp;char *name;{ name_entry *new; new = (name_entry *) xmalloc(sizeof(struct name_entry)); new->name = xmalloc(strlen(name) + 1); strcpy(new->name, name); new->nxt = *namepp; if(new->nxt != NULL) new->nxt->prev = new; *namepp = new; return(new);}delete_name(namepp, name)name_entry **namepp;char *name;{ name_entry *nl; nl = *namepp; while(nl != NULL) { if(strcmp(nl->name, name) == 0) {/*found */ if(nl->prev != NULL) nl->prev->nxt = nl->nxt; else *namepp = nl->nxt; if(nl->nxt != NULL) nl->nxt->prev = nl->prev; free(nl->name); free(nl); return; } nl = nl->nxt; } return;}name_entry *find_name(namep, name)name_entry *namep;char *name;{ name_entry *nl; nl = namep; while(nl != NULL) { if(strcmp(nl->name, name) == 0) { return(nl); } nl = nl->nxt; } return(NULL);}record_name(name, op)char *name;int op;{ name_entry *nl; int fd; char path[MAXNAMLEN]; if(op == 1) { /* insert */ if((nl = find_name(record_q, name)) == NULL) { nl = insert_name(&record_q, name); /* make an entry in current directory */ strcpy(path, CURRENT); strcat(path, "/"); strcat(path, name); if(debug >= 2) printf("create monitor entry %s\n", path); if((fd = open(path, O_CREAT, 00200)) == -1){ fprintf(stderr, "open: \n"); perror(path); fprintf(stderr, "\n"); if(errno != EACCES) exit(1); } else { if(debug >= 2) printf("%s is created\n", path); if(close(fd)) { perror("close"); fprintf(stderr, "\n"); exit(1); } } } nl->count++; } else { /* delete */ if((nl = find_name(record_q, name)) == NULL) { return; } nl->count--; if(nl->count == 0) { delete_name(&record_q, name); /* remove this entry from current directory */ strcpy(path, CURRENT); strcat(path, "/"); strcat(path, name); if(debug >= 2) printf("remove monitor entry %s\n", path); if(unlink(path) == -1) { perror(path); fprintf(stderr, "\n"); exit(1); } } } }sm_crash(){ name_entry *nl, *next; if(record_q == NULL) return; next = record_q; /* clean up record queue */ while((nl = next) != NULL) { next = next->nxt; delete_name(&record_q, nl->name); } if(recovery_q != NULL) { /* clean up all onging recovery act*/ if(debug) printf("sm_crash clean up\n"); alarm(0); next = recovery_q; while( (nl = next) != NULL) { next = next ->nxt; delete_name(&recovery_q, nl->name); } } statd_init();}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?