static char rcsver[] = "$Id: buffs.c,v 2.2 1999/07/12 23:14:08 gorelick Exp $"; /** ** $Source: /tes/src/vanilla/RCS/buffs.c,v $ ** ** $Log: buffs.c,v $ ** Revision 2.2 1999/07/12 23:14:08 gorelick ** *** empty log message *** ** ** Revision 2.1 1999/02/10 04:00:50 gorelick ** *** empty log message *** ** ** Revision 2.0 1998/12/22 22:47:04 gorelick ** release version ** ** Revision 2.0 1998/12/18 01:26:03 gorelick ** release version ** ** Revision 1.7 1998/12/18 01:04:48 gorelick ** *** empty log message *** ** ** Revision 1.6 1998/12/01 22:42:06 gorelick ** *** empty log message *** ** ** Revision 1.5 1998/11/18 00:13:47 gorelick ** extensive loop optimzations ** ** Revision 1.4 1998/11/13 23:33:24 gorelick ** *** empty log message *** ** ** Revision 1.3 1998/11/12 22:58:55 gorelick ** first release version ** **/ #include #include #include #include "header.h" #ifndef MAP_PRIVATE #define MAP_PRIVATE 0 #endif /* Creates a new TBLBUFF object for a given table object. User * supplies the record count for the buffer and the overlap count. * IMPORTANT: The overlap count MUST be at least two times the size of * the largest possible keyblock. */ PTR RefillTblBuff(TBLBUFF *b) { int fd; FRAGMENT *frag; char *fname; if (b->buf != NULL) { munmap(b->buf, b->len); if (b->varbuf) { munmap(b->varbuf, b->varlen); b->varbuf = NULL; } #ifdef DEBUG fname = (char *)b->tbl->files->ptr[b->fileidx]; fprintf(stderr, "Unmapping %s\n", fname); #endif b->fileidx++; } if (b->fileidx >= b->tbl->files->number) { return(NULL); } fname = (char *)b->tbl->files->ptr[b->fileidx]; frag = LoadFragment(fname, b->tbl); b->len = frag->sbuf.st_size; #ifdef _WINDOWS fd = open(fname, O_RDONLY | O_BINARY); #else fd = open(fname, O_RDONLY); #endif #ifdef DEBUG fprintf(stderr, "mapping: %s\n", fname); #endif b->buf = mmap(NULL, b->len, PROT_READ, MAP_PRIVATE, fd, 0); close(fd); b->curr = b->buf + frag->offset; b->end = b->buf + b->len; b->reclen = b->tbl->label->reclen; return(b->curr); } PTR GiveMeVarPtr(PTR raw, TABLE *table, int offset) { TBLBUFF *b = table->buff; struct stat sbuf; char *fname, buf[256], *p; int fd; if (b->varbuf == NULL) { fname = ((char **)(table->files->ptr))[b->fileidx]; strcpy(buf, fname); p = &buf[strlen(buf)-4]; strcpy(p, ".var"); if (stat(buf, &sbuf) != 0) { p = &buf[strlen(buf)-4]; strcpy(p, ".VAR"); /* try capital case */ if (stat(buf, &sbuf) != 0) {; fprintf(stderr, "Unable to open var file: %s\n", buf); return(NULL); } } #ifdef _WINDOWS fd = open(buf, O_RDONLY | O_BINARY); #else fd = open(buf, O_RDONLY); #endif if (fd < 0) { fprintf(stderr, "Unable to open var file: %s\n", buf); return(NULL); } b->varlen = sbuf.st_size; b->varbuf = mmap(NULL, b->varlen, PROT_READ, MAP_PRIVATE, fd, 0); close(fd); } /* Saadat -- Feb 15, 1999 */ if (offset >= b->varlen){ fprintf(stderr, "Variable Pointer after EOF: File: %s. Aborting...", buf); abort(); } return(b->varbuf+offset); } short ConvertVaxVarByteCount(PTR raw, VARDATA *vdata) { char buf[4]; short s; memcpy(buf, raw, 2); s = ((short *)MSB2(buf))[0]; return(s); } TBLBUFF * NewTblBuff(TABLE *t) { TBLBUFF *b = calloc(1,sizeof(TBLBUFF)); b->tbl = t; if (RefillTblBuff(b) == NULL) return(NULL); return(b); } /* Returns the first record in a table. This will ONLY WORK if it's the * first operation performed on the table. Calling this function after * we've done find's on the table will give useless results. */ PTR GetFirstRec(TABLE * t) { if (t->buff == NULL) { t->buff = NewTblBuff(t); } return t->buff->curr; } /** **/ PTR find_jump(TABLE * t, FIELD * f, DATA d, PTR beg, PTR end) { TBLBUFF *b = t->buff; int refill = 0; if (beg == NULL) { beg = GetFirstRec(t); b = t->buff; } if (end == NULL) { end = b->end; refill = 1; } while (1) { while (beg < end && CompareData(ConvertFieldData(beg,f),d,f) < 0) { beg += b->reclen; #ifdef DEBUG fprintf(stderr, "find_jump[1], "); fprintf(stderr, "%d / %d %s\n", (beg - b->buf)/b->reclen, (end - b->buf)/b->reclen, b->tbl->files->ptr[b->fileidx]); #endif } if (beg == end) { if (refill) { if ((beg = RefillTblBuff(b)) == NULL) return(NULL); end = b->end; #ifdef DEBUG printf("find_jump[2], refill %s\n", (char *)b->tbl->files->ptr[b->fileidx]); #endif continue; } else { return(NULL); } } #ifdef DEBUG fprintf(stderr, "find_jump[3], match "); fprintf(stderr, "%d %s\n",(beg - b->buf)/b->reclen, b->tbl->files->ptr[b->fileidx]); #endif return(beg); } } PTR find_until(TABLE * t, FIELD * f, PTR beg, PTR end) { TBLBUFF *b = t->buff; DATA d = ConvertFieldData(beg, f); PTR e; if (end == NULL) end = b->end; while ((beg += b->reclen) < end && EquivalentData(ConvertFieldData(beg, f), d, f)) { #ifdef DEBUG fprintf(stderr, "find_until: "); fprintf(stderr, "%d %s\n",(beg - b->buf)/b->reclen, b->tbl->files->ptr[b->fileidx]); #endif } return(beg); } /* */ PTR find_select(TABLE * t, PTR beg, PTR end) { DATA d; SELECT **s; int i, n, count = 0; TBLBUFF *b = t->buff; int refill = 0; PTR last = NULL; if (t->selects == NULL) return(beg); s = (SELECT **)t->selects->ptr; n = t->selects->number; if (end == NULL) { end = b->end; refill = 1; } i = 0; while (1) { while (beg < end) { d = ConvertFieldData(beg, s[i]->field); if (CompareData(d, s[i]->low, s[i]->field) < 0 || CompareData(d, s[i]->high, s[i]->field) > 0) { beg += b->reclen; continue; } /* selection matched */ if (beg != last) { last = beg; count = 0; } i = (i+1)%n; if (++count == n) { #ifdef DEBUG fprintf(stderr, "find_select[2]: match, "); fprintf(stderr, "%d %s\n",(beg - b->buf)/b->reclen, b->tbl->files->ptr[b->fileidx]); #endif return(beg); } } if (refill) { if ((beg = RefillTblBuff(b)) == NULL) return(NULL); end = b->end; #ifdef DEBUG fprintf(stderr, "find_select[3]: refill %s\n", b->tbl->files->ptr[b->fileidx]); #endif } else { return(NULL); } } } /** ** Get the maximum value of the next record across all tables. ** This function also moves us across a fragment boundary (and sets up the ** first fragment) when necessary. **/ DATA * maxFieldVal(SLICE * s, int dim, TABLE **tbl, DATA *maxValue) { int i, rv = 0; DATA value; PTR beg; for (i = 0; i < dim; i++) { if (s[i].party_key == NULL) continue; if (s[i].start_rec == NULL) { /* No buffer loaded yet */ s[i].start_rec = GetFirstRec(tbl[i]); } else if (s[i].start_rec == tbl[i]->buff->buf + tbl[i]->buff->len) { /* EOF of current bufer */ if ((beg = RefillTblBuff(tbl[i]->buff)) == NULL) return(NULL); s[i].start_rec = beg; } value = ConvertFieldData(s[i].start_rec, s[i].party_key); if (!rv) { *maxValue = value; rv++; } else if (CompareData(value, *maxValue, s[i].party_key) > 0) *maxValue = value; } return maxValue; }