errstat sp_commit() { struct sp_table *st; struct sp_save *firstmod; objnum obj; errstat err; /* When we get an error writing to the (probably local) bulletsvr, * we can do nothing but panic(). We cannot abort the transaction * because the other members will (presumably?) not have this problem * and hence have accepted the modification. */ /* First see if we have multiple modifications as a result of the last * command. (This may happen as a result of sp_install()). * If so, we must use the intentions module rather than the modlist module * in order to guarantee atomicity. */ st = sp_first_update(); firstmod = (st != NULL) ? st->st_dir->sd_mods : NULL; if ((firstmod != NULL && firstmod->ss_next == NULL) /* just 1 mod */ && (st->st_dir->sd_update == NULL) /* just 1 dir */) { obj = st - _sp_table; assert(sp_in_use(st)); if (st->st_flags & SF_DESTROYING) { MON_EVENT("destroying dir"); (void) remove_dir(obj); } else { /* Note: we don't increase the current seqno of the directory * itself, but use as the new seqnr the (already incremented) * *global* sequence number. * This avoids the possibility of having different incarnations * of the same directory at the same time. */ get_global_seqno(&st->st_dir->sd_seq_no); err = ml_store(obj); if (err != STD_OK && err != STD_NOSPACE) { /* Command not handled by modlist module, or no space in the * modlist itself, or not enough memory. */ if (!ml_in_use()) { /* Try to modify it, when possible and efficient. * Otherwise write it out as a whole. */ err = write_new_dir(obj, 1); } else { /* Write it as a whole and remove it from the mod list */ err = ml_write_dir(obj); } } switch (err) { case STD_OK: sp_free_mods(st); break; case STD_NOSPACE: /* The directory would become to big. This error should be * consistent to all members, because they have the same * data and use the same buffer sizes. */ scream("dir %ld would become too big", (long) obj); sp_abort(); /* undoes the modification */ return err; default: /* must panic; see above */ panic("sp_commit: cannot write dir %ld (%s)", (long) obj, err_why(err)); } } } else { /* There are multiple updates or no updates at all */ capability curcaps[NBULLETS]; capability newcaps[NBULLETS]; capability filesvrs[NBULLETS]; struct sp_table *next_st; int nintents, avail; /* First make sure we have room for all of the intentions. */ avail = intent_avail(); nintents = 0; for (st = sp_first_update(); st != NULL; st = sp_next_update()) { nintents++; } if (nintents > avail) { scream("too many intentions: %d (max %d)", nintents, avail); MON_EVENT("too many intentions"); sp_abort(); return STD_NOSPACE; } fsvr_get_svrs(filesvrs, NBULLETS); for (st = sp_first_update(); st != NULL; st = next_st ) { next_st = sp_next_update(); obj = st - _sp_table; /* Add an updated version of this dir to the intentions list. * All dirs for which we have modifications should be in memory: */ assert(sp_in_use(st)); assert(in_cache(obj)); /* Note: all directories modified in as a result of the current * modification get the same seqno! */ get_global_seqno(&st->st_dir->sd_seq_no); if (!ml_in_use()) { /* Try to modify it, when possible and efficient. * Otherwise write it out as a whole. */ get_dir_caps(obj, curcaps); err = dirf_modify(obj, NBULLETS, curcaps, newcaps, filesvrs); } else { err = dirf_write(obj, NBULLETS, newcaps, filesvrs); } switch (err) { case STD_OK: /* Put the new cap(s) in the intentions list. Don't install * them in the supertable yet: that'll be done after we have * written the intention. It'll also give us the opportunity * to destroy the old versions afterwards. */ intent_add(obj, newcaps); MON_EVENT("added intention"); break; case STD_NOSPACE: /* The directory would become to big. This error should be * consistent to all members, because they have the same * data and use the same buffer sizes. * Remove the intentions and let the transaction fail. */ intent_undo(); scream("dir %ld would become too big", (long) obj); sp_abort(); /* undoes the modifications */ return err; default: /* must panic; see above */ panic("sp_commit: cannot write dir %ld (%s)", (long) obj, err_why(err)); } } if (nintents > 0) { /* Write the intentions created to disk */ super_store_intents(); /* Install the modified directories in the super table and remove * the intention again. If we happen to crash between storing the * intention and executing it, we'll complete it the next time * during recovery. */ intent_make_permanent(); MON_EVENT("executed intention"); } } sp_clear_updates(); sp_end(); return STD_OK; }
/*--------------------------------------------------------------------------*/ main (int argc, char *argv[]) { char option; /* command line option */ char *infile, *outfile, *cur; FILE *fopen (), *in_f, *out_f; extern int getopt (int argc, char *argv[], char *optionS); extern int optind, /* the argv index of the next argument */ opterr; /* set this to zero so that getopt dont print its own error */ extern char *optarg; /* points to the option argument */ struct stat f_info; /* structure for stat */ long secs_now; NumLines = DEFLINES; PageLen = DEFPAGE; NumCols = DEFCOL; NumIndent = DEFINDENT; outfile = NULL; opterr = 0; out_f = stdout; textcolor (YELLOW); /* clrscr ();*/ cprintf (" SPIT V%s", VERSION); cprintf (" -file printer and formatter- "); cprintf ("(c)1987,88 KindelCo Software Systems\n\n"); if (argc == 1) /* if there is nothing on the command line then print docs */ sp_abort (NOERR); textcolor (LIGHTMAGENTA); while ((option = getopt (argc, argv, OPTSTRING)) != EOF) switch (toupper (option)) { case LINE_OPT : NumLines = strtol (optarg, NULL, 0); /* strtol converts a string to a long int. */ cprintf (" spit: Option not implemented yet: /%c.\n", option); sp_abort (CMNDERR); break; case PAGE_OPT : PageLen = strtol (optarg, NULL, 0); cprintf (" spit: Option not implemented yet: /%c.\n", option); sp_abort (CMNDERR); PageLen = strtol (optarg, NULL, 0); break; case WIDE_OPT : if (NumIndent == DEFINDENT) NumIndent = 8; NumCols = 132; wideflg = TRUE; break; case OUT_OPT : outfile = malloc (strlen (optarg)); outfile = optarg; break; case INDENT_OPT : NumIndent = strtol (optarg, NULL, 0); break; case UNKNOWN_OPT : cprintf (" spit: unknown command line option.\n"); sp_abort (CMNDERR); break; case FF_OPT : formflg = TRUE; break; case SINGLE_OPT : singleflg = TRUE; break; default : cprintf (" spit: Option not implemented yet: /%c.\n", option); sp_abort (CMNDERR); break; } if (NumLines >= (PageLen - 8)) { cprintf (" spit: The number of lines must not exceed the page length - 8.\n"); sp_abort (OPTERR); } while (optind < argc) { infile = (char*) malloc (strlen (argv[optind])+2); strcpy (infile, argv [optind++]); if ((in_f = fopen (infile, READ)) == NULL) { cprintf (" spit: can't open input file "); textcolor (WHITE); cprintf ("%s\n", infile); textcolor (LIGHTMAGENTA); sp_abort (INFILEERR); } if (outfile == NULL) { outfile = malloc (4); strcpy (outfile, DEFOUT); } if ((out_f = fopen (outfile, WRITE)) == NULL) { cprintf (" spit: can't open output file "); textcolor (WHITE); cprintf ("%s\n", outfile); textcolor (LIGHTMAGENTA); sp_abort (OUTFILEERR); } cprintf ("Printing "); textcolor (WHITE); cprintf ("%s ", infile); textcolor (LIGHTMAGENTA); cprintf ("..."); if (strlen (infile) > 19) { strcpy (header, infile); cur = header; while (strlen (cur) > 16) *(cur++) = '.'; cur -= 3; strcpy (header, cur); strcat (header, " "); } else { strcpy (header, infile); while (strlen (header) < 20) strcat (header, " "); } strcat (header, "- Revised "); stat (infile, &f_info); /* get file date */ strcat (header, ctime (&f_info.st_mtime)); *strchr (header, '\n') = NULL; strcat (header, " -"); while (strlen (header) < 69) strcat (header, " "); strcat (header, "Page "); strcpy (footer, " - Printed on \0"); time (&secs_now); /* get time in seconds */ strcat (footer, ctime (&secs_now)); /* make it into a string */ *(strchr (footer, '\n')) = NULL; strcat (footer, " -"); sp_io (in_f, out_f); if (fclose (in_f)) cprintf ("Error closing input file."); if (fclose (out_f)) cprintf ("Error closing output file."); cprintf ("\n"); free (infile); } cprintf ("\n"); return; }
/*--------------------------------------------------------------------------*/ main (int argc, char *argv[]) { char option; /* command line option */ char *infile, *outfile; FILE *fopen (), *in_f, *out_f; extern int getopt (int argc, char *argv[], char *optionS); extern int optind, /* the argv index of the next argument */ opterr; /* set this to zero so that getopt dont print its own error */ extern char *optarg; /* points to the option argument */ struct stat f_info; /* structure for stat */ long secs_now; directvideo = FALSE; /* we don't want direct video! */ NumLines = DEFLINES; PageLen = DEFPAGE; NumCols = DEFCOL; NumIndent = DEFINDENT; outfile = NULL; opterr = 0; out_f = stdout; textcolor (YELLOW); cprintf (" SPIT V%s", VERSION); cprintf (" -file printer and formatter- "); cprintf ("(c)1987,88 KindelCo Software Systems\n\n"); if (argc == 1) /* if there is nothing on the command line then print docs */ sp_abort (); textcolor (LIGHTMAGENTA); while ((option = getopt (argc, argv, OPTSTRING)) != EOF) switch (option) { case LINE_OPT : NumLines = strtol (optarg, NULL, 0); /* strtol converts a string to a long int. */ break; case WIDE_OPT : NumCols = 132; NumIndent = 8; wideflg++; break; case OUT_OPT : outfile = malloc (strlen (optarg)); outfile = optarg; break; case INDENT_OPT : NumIndent = strtol (optarg, NULL, 0); break; case UNKNOWN_OPT : cprintf (" spit: bad command line option...\n", option); sp_abort (); break; case FF_OPT : formflg++; break; default : cprintf (" spit: Option not implemented yet.\n"); sp_abort (); break; } infile = malloc (256); while (optind < argc) /* get each input file */ { strcpy (infile, argv [optind]); if ((in_f = fopen (infile, READ)) == NULL) { cprintf (" spit: can't open input file "); textcolor (WHITE); cprintf ("%s\n", infile); textcolor (LIGHTMAGENTA); sp_abort (); } optind--; if (outfile == NULL) { outfile = malloc (4); strcpy (outfile, DEFOUT); } if ((out_f = fopen (outfile, WRITE)) == NULL) { cprintf (" spit: can't open output file "); textcolor (WHITE); cprintf ("%s\n", outfile); textcolor (LIGHTMAGENTA); sp_abort (); } strcpy (header, infile); while (strlen (header) < 20) strcat (header, " "); strcat (header, "- Revised "); stat (infile, &f_info); /* get file date */ strcat (header, ctime (&f_info.st_mtime)); *strchr (header, '\n') = NULL; strcat (header, " -"); while (strlen (header) < 69) strcat (header, " "); strcat (header, "Page "); while (strlen (footer) < 20) strcat (footer, " "); strcat (footer, "- Printed on "); time (&secs_now); /* get time in seconds */ strcat (footer, ctime (&secs_now)); /* make it into a string */ *(strchr (footer, '\n')) = NULL; strcat (footer, " -"); sp_io (in_f, out_f); } cprintf ("\n"); return; }