1: #include "parms.h" 2: #include "structs.h" 3: 4: #ifdef RCSIDENT 5: static char rcsid[] = "$Header: resp.c,v 1.7 85/01/18 15:38:30 notes Rel $"; 6: #endif RCSIDENT 7: 8: /* 9: * putresp (io, text, status, noteno, anon) 10: * 11: * writes out a response to noteno in the last position. 12: * returns 0 to indicate note has been deleted, 13: * otherwise it returns the response number it inserted. 14: * 15: * 16: * delresp(io, noteno, resprec, resphys) 17: * 18: * Deletes PHYSICAL response located at resprec (record id) 19: * resphys (internal subscript), updates note's response count 20: * 21: * 22: * getfrsp(io) gets the next free response index -- simple free list chained 23: * off first two bytes of file, currently. 24: * 25: */ 26: 27: long lseek (); /* declare for type checking */ 28: 29: putresp (io, where, status, noteno, adate, auth, note, lockit, theid, addid, fromsys, 30: addtime, rcvdtime) 31: /* all input params */ 32: struct io_f *io; 33: struct daddr_f *where; 34: struct note_f *note; 35: struct when_f *adate; 36: struct auth_f *auth; 37: struct id_f *theid; 38: char *fromsys; 39: /* addtime - whether to modify time stamps - useed for compression */ 40: struct when_f *rcvdtime; /* time to mark as written */ 41: { 42: int i, 43: phys, /* physical subscript number */ 44: lastin; /* address of resp record in memory */ 45: struct resp_f resp; 46: 47: if (lockit) 48: locknf (io, DSCRLOCK); /* entirely critical */ 49: getdscr (io, &io -> descr); 50: if (io -> descr.d_stat & NFINVALID) 51: { 52: closenf (io); 53: opennf (io, 0); 54: getdscr (io, &io -> descr); /* and updated descriptor */ 55: if (lockit) 56: unlocknf (io, DSCRLOCK); 57: return 0; 58: } 59: getnrec (io, noteno, note); 60: if ((note -> n_stat & DELETED) != 0) /* is note gone? */ 61: { 62: /* 63: * see, it could be deleted by someone else in the 64: * mean time... 65: */ 66: if (lockit) 67: unlocknf (io, DSCRLOCK); /* not so critical now */ 68: return 0; /* putresp failed */ 69: } 70: if (note -> n_rindx < 0) /* is there an attached response record ? */ 71: { 72: lastin = note -> n_rindx = getfrsp (io); /* no, make one */ 73: resp.r_first = 1; 74: resp.r_last = 0; /* counts */ 75: resp.r_previous = (-1); /* no previous */ 76: resp.r_next = (-1); /* no next */ 77: for (i = 0; i < RESPSZ; i++) 78: resp.r_stat[i] = 0; /* mark all as undeleted at start */ 79: } 80: else 81: getrrec (io, lastin = note -> n_rindx, &resp); /* get first resp record */ 82: i = phys = 0; /* logical/phys records start here */ 83: /* 84: * should update this to take advantage of r_first and r_last 85: * as it would speed up writing responses in long note strings. 86: */ 87: while (i < note -> n_nresp) /* until we get to end */ 88: { 89: if (phys >= RESPSZ) /* off end? -- need next recd */ 90: { 91: phys = 0; /* beginning of next one */ 92: getrrec (io, lastin = resp.r_next, &resp); /* next recd */ 93: } 94: if ((resp.r_stat[phys] & DELETED) == 0) 95: i++; /* count this entry if undeleted */ 96: phys++; /* always count these */ 97: } 98: /* 99: * could have gone off end with last phys++ 100: */ 101: if (phys >= RESPSZ) 102: { 103: phys = 0; 104: resp.r_next = getfrsp (io); 105: putrrec (io, lastin, &resp); /* out w/modified link */ 106: resp.r_previous = lastin; /* back ptr */ 107: lastin = resp.r_next; 108: resp.r_next = (-1); /* helps debugging */ 109: resp.r_first = note -> n_nresp + 1; /* front and */ 110: resp.r_last = resp.r_first - 1; /* last. */ 111: /* 112: * r_last is bumped just before the putrrec() below. 113: */ 114: for (i = 0; i < RESPSZ; i++) 115: { 116: resp.r_stat[i] = 0; /* mark all as undeleted */ 117: } 118: } 119: note -> n_nresp++; /* one more response! */ 120: resp.r_addr[phys] = *where; 121: if (addtime) 122: gettime (&resp.r_rcvd[phys]); 123: else 124: copydate (rcvdtime, &resp.r_rcvd[phys]); /* use supplied */ 125: copydate (adate, &resp.r_when[phys]); /* copy date over */ 126: copyauth (auth, &resp.r_auth[phys]); /* and author */ 127: strmove (fromsys, resp.r_from[phys]); /* who gave it to us */ 128: if (addid) /* generate unique id */ 129: { 130: #ifdef SHAREDATA 131: strmove (System, resp.r_id[phys].sys); /* load sys name */ 132: #else ! SHAREDATA 133: strmove (io -> descr.d_id.sys, resp.r_id[phys].sys); 134: #endif SHAREDATA 135: 136: resp.r_id[phys].uniqid = ++(io -> descr.d_id.uniqid); 137: #if defined(UNIQPLEX) 138: resp.r_id[phys].uniqid += UNIQPLEX * io -> descr.d_nfnum; 139: /* mpx in the nf number */ 140: #endif defined(UNIQPLEX) 141: } 142: else 143: { /* use the supplied unique id */ 144: strmove (theid -> sys, resp.r_id[phys].sys); 145: resp.r_id[phys].uniqid = theid -> uniqid; 146: } 147: resp.r_stat[phys] = status; 148: if (addtime) /* timestamp ? */ 149: { 150: gettime (¬e -> n_lmod); /* last modified entire note */ 151: gettime (&io -> descr.d_lastm); /* last modified entire file */ 152: } 153: resp.r_last++; /* 1 more there */ 154: putrrec (io, lastin, &resp); 155: putnrec (io, noteno, note); 156: putdscr (io, &io -> descr); /* order of these three keeps disk consistent */ 157: if (lockit) 158: unlocknf (io, DSCRLOCK); 159: io -> nrspwrit++; /* add count of writes */ 160: return note -> n_nresp; /* success */ 161: } 162: 163: 164: /* 165: * getfrsp() 166: * 167: * get the next open response block. 168: */ 169: getfrsp (io) struct io_f *io; 170: { 171: int i; /* will contain the free pointer */ 172: x (lseek (io -> fidrdx, 0L, 0) < 0, "getfrsp: seek I"); 173: x (read (io -> fidrdx, &i, sizeof i) < sizeof i, "getfrsp: read"); 174: i++; /* next free */ 175: x (lseek (io -> fidrdx, 0L, 0) < 0, "getfrsp: seek II"); 176: x (write (io -> fidrdx, &i, sizeof i) < sizeof i, "getfrsp: write"); 177: return i - 1; 178: } 179: 180: 181: /* 182: * delresp() 183: * 184: * delete a PHYSICAL response. This takes the actual place 185: * the response lives in rather than the logical response 186: * number. 187: * 188: * Updates r_first and r_last for the rest of the response 189: * chain. 190: */ 191: delresp (io, noteno, resprec, resphys, lockit) 192: struct io_f *io; 193: { 194: struct resp_f resp; 195: struct note_f note; 196: register int i; /* follows resp chain */ 197: 198: if (lockit) 199: locknf (io, DSCRLOCK); /* all critical */ 200: getrrec (io, resprec, &resp); 201: if ((resp.r_stat[resphys] & DELETED) == 0) 202: { 203: /* 204: * makes sure that someone hasn't zapped at same time 205: */ 206: resp.r_stat[resphys] |= DELETED; /* deleted */ 207: resp.r_last--; /* fix count */ 208: /* 209: * if r_first > r_last, we have an empty block. 210: * unfortunate waste of space that is rectified 211: * by compression later. 212: */ 213: putrrec (io, resprec, &resp); 214: while ((i = resp.r_next) >= 0) /* for rest of chain */ 215: { 216: getrrec (io, i, &resp); /* get it */ 217: resp.r_first--; 218: resp.r_last--; /* fix indices */ 219: putrrec (io, i, &resp); /* and replace */ 220: } 221: getnrec (io, noteno, ¬e); /* update the note */ 222: --note.n_nresp; 223: putnrec (io, noteno, ¬e); 224: getdscr (io, &io -> descr); /* count deletes */ 225: io -> descr.d_delresp++; /* used by compress */ 226: putdscr (io, &io -> descr); 227: } 228: if (lockit) 229: unlocknf (io, DSCRLOCK); 230: return; 231: }