+ /*NOTREACHED*/
+ }
+}
+
+#ifdef ROLLDEBUG
+int do_sum(block)
+ union u_spcl *block;
+
+{
+ char sum = 0;
+ int i;
+
+ for (i = 0; i < TP_BSIZE; i++) {
+ sum = sum ^ block->dummy[i];
+ }
+ return(sum);
+}
+#endif
+
+void
+rollforward()
+{
+ register struct req *p, *q, *prev;
+ register struct slave *tslp;
+ int i, size, savedtapea, got;
+ union u_spcl *ntb, *otb;
+#ifdef ROLLDEBUG
+ int j;
+#endif
+ tslp = &slaves[SLAVES];
+ ntb = (union u_spcl *)tslp->tblock[1];
+
+ /*
+ * Each of the N slaves should have requests that need to
+ * be replayed on the next tape. Use the extra slave buffers
+ * (slaves[SLAVES]) to construct request lists to be sent to
+ * each slave in turn.
+ */
+ for (i = 0; i < SLAVES; i++) {
+ q = &tslp->req[1];
+ otb = (union u_spcl *)slp->tblock;
+
+ /*
+ * For each request in the current slave, copy it to tslp.
+ */
+#ifdef ROLLDEBUG
+ printf("replaying reqs to slave %d (%d)\n", slp - &slaves[0],
+ slp->pid);
+ j = 0;
+#endif
+
+ for (p = slp->req; p->count > 0; p += p->count) {
+#ifdef ROLLDEBUG
+ printf(" req %d count %d dblk %d\n",
+ j++, p->count, p->dblk);
+ if (p->dblk == 0)
+ printf("\tsum %x\n", do_sum(otb));
+#endif
+ *q = *p;
+ if (p->dblk == 0)
+ *ntb++ = *otb++; /* copy the datablock also */
+ prev = q;
+ q += q->count;
+ }
+ if (prev->dblk != 0)
+ prev->count -= 1;
+ else
+ ntb--;
+ q -= 1;
+ q->count = 0;
+ q = &tslp->req[0];
+ if (i == 0) {
+ q->dblk = 0;
+ q->count = 1;
+ trecno = 0;
+ nextblock = tslp->tblock;
+ savedtapea = spcl.c_tapea;
+ spcl.c_tapea = slp->tapea;
+ startnewtape(0);
+ spcl.c_tapea = savedtapea;
+ lastspclrec = savedtapea - 1;
+ }
+ size = (char *)ntb - (char *)q;
+ if (atomic(write, slp->fd, (char *)q, size) != size) {
+ perror(" DUMP: error writing command pipe");
+ dumpabort();
+ }
+ slp->sent = 1;
+#ifdef ROLLDEBUG
+ printf("after the shift:\n");
+ j = 0;
+ for (p = tslp->req; p->count > 0; p += p->count) {
+ printf(" req %d count %d dblk %d\n",
+ j++, p->count, p->dblk);
+ if (p->dblk == 0) {
+ /* dump block also */
+ }
+ }
+#endif
+ if (++slp >= &slaves[SLAVES])
+ slp = &slaves[0];
+
+ q->count = 1;
+
+ if (prev->dblk != 0) {
+ /*
+ * If the last one was a disk block, make the
+ * first of this one be the last bit of that disk
+ * block...
+ */
+ q->dblk = prev->dblk +
+ prev->count * (TP_BSIZE / DEV_BSIZE);
+ ntb = (union u_spcl *)tslp->tblock;
+ } else {
+ /*
+ * It wasn't a disk block. Copy the data to its
+ * new location in the buffer.
+ */
+ q->dblk = 0;
+ *((union u_spcl *)tslp->tblock) = *ntb;
+ ntb = (union u_spcl *)tslp->tblock[1];
+ }
+ }
+ slp->req[0] = *q;
+ nextblock = slp->tblock;
+ if (q->dblk == 0)
+ nextblock++;
+ trecno = 1;
+
+ /*
+ * Clear the first slaves' response. One hopes that it
+ * worked ok, otherwise the tape is much too short!
+ */
+ if (slp->sent) {
+ if (atomic(read, slp->fd, (char *)&got, sizeof got)
+ != sizeof got) {
+ perror(" DUMP: error reading command pipe in master");
+ dumpabort();
+ }
+ slp->sent = 0;
+
+ if (got != writesize) {
+ quit("EOT detected at start of the tape!\n");
+ }
+ }