static void info(HXFILE * hp) { HXSTAT st; hxstat(hp, &st); unsigned dpages = _hxf2d(st.npages); unsigned overs = st.npages - dpages - 1; if (!overs) overs = 1; printf("recs=%.0f hash=%08X used=%.0f pages=%.0f ovfl_used=%.0f%%" " load=%.0f,%.0f%% pgsize=%d", st.nrecs, (unsigned)st.hash, st.head_bytes + st.ovfl_bytes, st.npages, st.ovfl_pages * 100 / overs, st.head_bytes * 100 / DATASIZE(hp) / dpages, st.ovfl_bytes * 100 / DATASIZE(hp) / st.ovfl_pages, hp->pgsize); if (hp->uleng) printf(" udata[%d]=%.*s", hp->uleng, hp->uleng, hp->udata); putchar('\n'); }
HXRET _hxcheckbuf(HXLOCAL const*locp, HXBUF const*bufp) { HXFILE *hp = locp->file; if (IS_MAP(hp, bufp->pgno)) { if (!(bufp->data[0] & 1)) return bad_map_self; if (bufp->pgno) { // extended map page. if (bufp->next || bufp->used) return bad_map_head; } else { // root page. if (bufp->used >= DATASIZE(hp) || bufp->used != hp->uleng) return bad_map_head; // Todo: check that HXROOT{pgsize,version} are good. } int lastbit, pos; PAGENO lastmap = locp->npages - 1; lastmap = _hxmap(hp, lastmap - lastmap % HXPGRATE, &lastbit); if (bufp->pgno == lastmap) { // All bits beyond lastbit must be zero. BYTE mask = -2 << (lastbit & 7); for (pos = lastbit >> 3; pos < (int)DATASIZE(hp); ++pos, mask = -1) if (bufp->data[pos] & mask) return bad_overmap; } } else { // DATA page.
static HXRET maps(HXFILE * hp) { HXLOCAL loc; PAGENO pg, last; int bitpos; # define locp (&loc) # define bufp (&loc.buf[0]) ENTER(locp, hp, NULL, 1); locp->mode = F_RDLCK; _hxlock(locp, 0, 0); _hxsize(locp); last = locp->npages - 1; last = _hxmap(hp, last - last % HXPGRATE, &bitpos); printf("last: mpg=%u bit=%d\n", (unsigned)last, bitpos); for (pg = 0; pg <= last;) { int i, n; _hxload(locp, bufp, pg); n = pg == last ? (bitpos + 7) >> 3 : (int)DATASIZE(hp); printf("---- pgno=%u next=%u used=%d recs=%u", pg, bufp->next, bufp->used, bufp->recs); for (i = 0; i < n; ++i) { unsigned b = bufp->data[i] & 0xFF; if (!(i & 15)) printf("\n%7u", (unsigned)pg + i * 8 * HXPGRATE); if (i < bufp->used) fputs(" >>", stdout); else printf(" %02X", b); } putchar('\n'); pg += (DATASIZE(hp) - bufp->used) * 8 * HXPGRATE; } LEAVE(locp, 0); # undef locp }
static int hdrs(HXFILE * hp) { HXLOCAL loc; # define locp (&loc) PAGENO pg; HXBUF *bufp; ENTER(locp, hp, NULL, 1); locp->mode = F_RDLCK; _hxlock(locp, 0, 0); _hxsize(locp); bufp = &locp->buf[0]; printf("npages:%u dpages:%u mask:%u pgsize:%d" " udata[%d]:'%.*s'\n", locp->npages, locp->dpages, locp->mask, hp->pgsize, hp->uleng, hp->uleng, hp->udata); _hxload(&loc, bufp, 0); dx(stdout, bufp->data, ((loc.npages + 31) >> 5) + 15); locp->vprev = calloc(DATASIZE(locp->file) / MINRECSIZE, sizeof(PAGENO)); for (pg = 1; pg < loc.npages; ++pg) { PAGENO *pp = locp->vprev; _hxload(&loc, &loc.buf[0], pg); _hxfindHeads(locp, bufp); printf("%7u next=%u used=%d recs=%u heads:", (unsigned)pg, (unsigned)bufp->next, bufp->used, bufp->recs); while (*pp) printf(" %u", *pp++); putchar('\n'); } LEAVE(locp, 0); #undef locp }
static void load_font(char *type, char *filename) { FILE *fd; int h, i, size, w; unsigned long io = 0; /* silence stupid gcc(1) in the Wall mode */ char *name, *fontmap, size_sufx[6]; const char *a[] = {"", FONT_PATH, NULL}; const char *b[] = {filename, NULL}; const char *c[] = {"", size_sufx, NULL}; const char *d[] = {"", ".fnt", NULL}; vid_info_t vinfo; struct sizeinfo { int w; int h; unsigned long io; } sizes[] = {{8, 16, PIO_FONT8x16}, {8, 14, PIO_FONT8x14}, {8, 8, PIO_FONT8x8}, {0, 0, 0} }; vinfo.size = sizeof(vinfo); if (ioctl(0, CONS_GETINFO, &vinfo) == -1) { revert(); errc(1, errno, "obtaining current video mode parameters"); } snprintf(size_sufx, sizeof(size_sufx), "-8x%d", vinfo.font_size); fd = openguess(a, b, c, d, &name); if (fd == NULL) { revert(); errx(1, "%s: can't load font file", filename); } if (type != NULL) { size = 0; if (sscanf(type, "%dx%d", &w, &h) == 2) { for (i = 0; sizes[i].w != 0; i++) { if (sizes[i].w == w && sizes[i].h == h) { size = DATASIZE(sizes[i]); io = sizes[i].io; font_height = sizes[i].h; } } } if (size == 0) { fclose(fd); revert(); errx(1, "%s: bad font size specification", type); } } else { /* Apply heuristics */ int j; int dsize[2]; size = DATASIZE(sizes[0]); fontmap = (char*) malloc(size); dsize[0] = decode(fd, fontmap, size); dsize[1] = fsize(fd); free(fontmap); size = 0; for (j = 0; j < 2; j++) { for (i = 0; sizes[i].w != 0; i++) { if (DATASIZE(sizes[i]) == dsize[j]) { size = dsize[j]; io = sizes[i].io; font_height = sizes[i].h; j = 2; /* XXX */ break; } } } if (size == 0) { fclose(fd); revert(); errx(1, "%s: can't guess font size", filename); } rewind(fd); } fontmap = (char*) malloc(size); if (decode(fd, fontmap, size) != size) { rewind(fd); if (fsize(fd) != size || fread(fontmap, 1, size, fd) != (size_t)size) { fclose(fd); free(fontmap); revert(); errx(1, "%s: bad font file", filename); } } if (ioctl(0, io, fontmap) == -1) { revert(); errc(1, errno, "loading font"); } fclose(fd); free(fontmap); }
int bdgraphBipartBd ( Bdgraph * const orggrafptr, /*+ Distributed graph +*/ const BdgraphBipartBdParam * const paraptr) /*+ Method parameters +*/ { Bdgraph bndgrafdat; /* Bipartitioning band graph structure */ Gnum bndvertancnnd; /* End of local vertex array, without anchors */ Gnum bndvertlocnbr1; /* Number of band graph vertices in part 1 except anchor 1 */ Gnum bndvertlocnum; Gnum bndvertlvlnum; /* Based number of first band vertex in last layer */ Gnum bndvertlocancadj; /* Flag set when anchor(s) represent unexistent vertices */ Gnum bndvertglbancadj; /* Global adjustment of anchor vertices */ Gnum bndveexlocsum; /* Local sum of veexloctax array cells for band graph */ Gnum bndveexlocsum0; /* Local sum of veexloctax array cells in part 0 for band graph */ Gnum bndedlolocval; Gnum bndfronlocnum; Gnum orgfronlocnum; int * restrict orgflagloctab; Gnum orgvertlocnum; Gnum orgedlolocval; const int * restrict orgprocsidtab; int orgprocsidnbr; int orgprocsidnum; int orgprocsidval; Gnum complocsizeadj0; Gnum commlocloadintn; Gnum commlocloadintn2; /* Twice twice (4 times) the internal communication load of last layer */ Gnum commlocloadextn; Gnum commlocgainextn; Gnum reduloctab[7]; Gnum reduglbtab[7]; DgraphHaloRequest requdat; if (orggrafptr->fronglbnbr == 0) /* If no separator vertices, apply strategy to full (original) graph */ return (bdgraphBipartSt (orggrafptr, paraptr->stratorg)); if (dgraphBand (&orggrafptr->s, orggrafptr->fronlocnbr, orggrafptr->fronloctab, orggrafptr->partgsttax, orggrafptr->complocload0, orggrafptr->s.velolocsum - orggrafptr->complocload0, paraptr->distmax, &bndgrafdat.s, &bndgrafdat.fronloctab, &bndgrafdat.partgsttax, &bndvertlvlnum, &bndvertlocnbr1, &bndvertlocancadj) != 0) { errorPrint ("bdgraphBipartBd: cannot create band graph"); return (1); } bndvertancnnd = bndgrafdat.s.vertlocnnd - 2; reduloctab[0] = 0; /* Assume no memory allocation problem */ bndveexlocsum = bndveexlocsum0 = 0; bndgrafdat.veexloctax = NULL; /* Assume no external gains */ if (orggrafptr->veexloctax != NULL) { if ((bndgrafdat.veexloctax = memAlloc (bndgrafdat.s.vertlocnbr * sizeof (Gnum))) == NULL) { errorPrint ("bdgraphBipartBd: out of memory (1)"); reduloctab[0] = 1; /* Memory error */ } else { Gnum bndvertlocnum; bndgrafdat.veexloctax -= bndgrafdat.s.baseval; for (bndvertlocnum = bndgrafdat.s.baseval; bndvertlocnum < bndvertancnnd; bndvertlocnum ++) { Gnum veexval; veexval = orggrafptr->veexloctax[bndgrafdat.s.vnumloctax[bndvertlocnum]]; bndgrafdat.veexloctax[bndvertlocnum] = veexval; bndveexlocsum += veexval; bndveexlocsum0 += veexval & (((Gnum) bndgrafdat.partgsttax[bndvertlocnum]) - 1); } } } reduloctab[1] = bndgrafdat.s.vendloctax[bndvertancnnd] - bndgrafdat.s.vertloctax[bndvertancnnd] - (orggrafptr->s.procglbnbr - 1); /* Anchor degrees */ reduloctab[2] = bndgrafdat.s.vendloctax[bndvertancnnd + 1] - bndgrafdat.s.vertloctax[bndvertancnnd + 1] - (orggrafptr->s.procglbnbr - 1); bndgrafdat.complocsize0 = bndgrafdat.s.vertlocnbr - (bndvertlocnbr1 + 1); /* Add 1 for anchor vertex 1 */ complocsizeadj0 = orggrafptr->complocsize0 - bndgrafdat.complocsize0; /* -1 less because of anchor 0 */ reduloctab[3] = bndgrafdat.complocsize0; reduloctab[4] = bndvertlocancadj; /* Sum increases in size and load */ reduloctab[5] = bndveexlocsum; reduloctab[6] = bndveexlocsum0; if (MPI_Allreduce (reduloctab, reduglbtab, 7, GNUM_MPI, MPI_SUM, orggrafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphBipartBd: communication error (1)"); return (1); } if (reduglbtab[0] != 0) { bdgraphExit (&bndgrafdat); return (1); } if ((reduglbtab[1] == 0) || /* If graph is too small to have any usable anchors */ (reduglbtab[2] == 0)) { bdgraphExit (&bndgrafdat); return (bdgraphBipartSt (orggrafptr, paraptr->stratorg)); } bndvertglbancadj = reduglbtab[4]; bndgrafdat.veexglbsum = orggrafptr->veexglbsum; /* All external gains preserved */ bndgrafdat.fronlocnbr = orggrafptr->fronlocnbr; /* All separator vertices are kept in band graph */ bndgrafdat.fronglbnbr = orggrafptr->fronglbnbr; bndgrafdat.complocload0 = orggrafptr->complocload0 + bndvertlocancadj; /* All loads are kept in band graph */ bndgrafdat.compglbload0 = orggrafptr->compglbload0 + bndvertglbancadj; bndgrafdat.compglbload0min = orggrafptr->compglbload0min + bndvertglbancadj; /* Tilt extrema loads according to adjustments */ bndgrafdat.compglbload0max = orggrafptr->compglbload0max + bndvertglbancadj; bndgrafdat.compglbload0avg = orggrafptr->compglbload0avg + bndvertglbancadj; /* Tilt average load according to adjustments */ bndgrafdat.compglbload0dlt = orggrafptr->compglbload0dlt; bndgrafdat.compglbsize0 = reduglbtab[3]; bndgrafdat.commglbload = orggrafptr->commglbload; bndgrafdat.commglbgainextn = orggrafptr->commglbgainextn; bndgrafdat.commglbloadextn0 = orggrafptr->commglbloadextn0; bndgrafdat.commglbgainextn0 = orggrafptr->commglbgainextn0; bndgrafdat.bbalglbval = orggrafptr->bbalglbval; bndgrafdat.domndist = orggrafptr->domndist; bndgrafdat.domnwght[0] = orggrafptr->domnwght[0]; bndgrafdat.domnwght[1] = orggrafptr->domnwght[1]; bndgrafdat.levlnum = orggrafptr->levlnum; if (bndgrafdat.veexloctax != NULL) { Gnum bndveexglbanc0; Gnum bndveexglbanc1; bndveexglbanc0 = (orggrafptr->veexglbsum + orggrafptr->commglbgainextn) / 2 - reduglbtab[6]; /* Compute global external gains of anchors */ bndveexglbanc1 = (orggrafptr->veexglbsum - bndveexglbanc0) - reduglbtab[5]; bndgrafdat.veexloctax[bndvertancnnd] = DATASIZE (bndveexglbanc0, bndgrafdat.s.procglbnbr, bndgrafdat.s.proclocnum); /* Spread gains across local anchors */ bndgrafdat.veexloctax[bndvertancnnd + 1] = DATASIZE (bndveexglbanc1, bndgrafdat.s.procglbnbr, bndgrafdat.s.proclocnum); } #ifdef SCOTCH_DEBUG_BDGRAPH2 if (bdgraphCheck (&bndgrafdat) != 0) { errorPrint ("bdgraphBipartBd: internal error (1)"); return (1); } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ if (bdgraphBipartSt (&bndgrafdat, paraptr->stratbnd) != 0) { /* Separate distributed band graph */ errorPrint ("bdgraphBipartBd: cannot separate band graph"); bdgraphExit (&bndgrafdat); return (1); } reduloctab[0] = (Gnum) bndgrafdat.partgsttax[bndvertancnnd]; /* Check if anchor vertices remain in their parts */ reduloctab[1] = (Gnum) bndgrafdat.partgsttax[bndvertancnnd + 1]; reduloctab[2] = complocsizeadj0; reduloctab[3] = 0; /* Assume memory allocation is all right */ if ((orgflagloctab = memAlloc (flagSize (orggrafptr->s.vertlocnnd) * sizeof (int))) == NULL) { /* Eventually keep space for based indices */ errorPrint ("bdgraphBipartBd: out of memory (2)"); reduloctab[3] = 1; } if (MPI_Allreduce (&reduloctab[0], &reduglbtab[0], 4, GNUM_MPI, MPI_SUM, orggrafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphBipartBd: communication error (2)"); return (1); } if (((reduglbtab[0] + reduglbtab[1]) != orggrafptr->s.procglbnbr) || /* If not all anchors of initial same parts in same parts */ ((reduglbtab[0] != 0) && (reduglbtab[0] != orggrafptr->s.procglbnbr)) || (reduglbtab[3] != 0)) { if (orgflagloctab != NULL) memFree (orgflagloctab); bdgraphExit (&bndgrafdat); /* Apply original strategy to full graph */ return (bdgraphBipartSt (orggrafptr, paraptr->stratorg)); } if (dgraphGhst (&bndgrafdat.s) != 0) { /* Compute ghost edge array if not already present */ errorPrint ("bdgraphBipartBd: cannot compute ghost edge array"); return (1); } if (reduglbtab[0] == orggrafptr->s.procglbnbr) { /* If all anchors swapped parts, swap all parts of original vertices */ Gnum orgvertnum; orggrafptr->complocsize0 = orggrafptr->s.vertlocnbr - reduloctab[2] - bndgrafdat.s.vertlocnbr + bndgrafdat.complocsize0; orggrafptr->compglbsize0 = orggrafptr->s.vertglbnbr - reduglbtab[2] - bndgrafdat.s.vertglbnbr + bndgrafdat.compglbsize0; for (orgvertnum = orggrafptr->s.baseval; orgvertnum < orggrafptr->s.vertlocnnd; orgvertnum ++) orggrafptr->partgsttax[orgvertnum] ^= 1; } else { orggrafptr->complocsize0 = reduloctab[2] + bndgrafdat.complocsize0; orggrafptr->compglbsize0 = reduglbtab[2] + bndgrafdat.compglbsize0; } for (bndvertlocnum = bndgrafdat.s.baseval; bndvertlocnum < bndvertancnnd; bndvertlocnum ++) /* Update part array of all vertices except anchors */ orggrafptr->partgsttax[bndgrafdat.s.vnumloctax[bndvertlocnum]] = bndgrafdat.partgsttax[bndvertlocnum]; dgraphHaloAsync (&orggrafptr->s, (byte *) (orggrafptr->partgsttax + orggrafptr->s.baseval), GRAPHPART_MPI, &requdat); /* Share part array of full graph */ commlocloadintn = commlocloadextn = commlocgainextn = 0; bndedlolocval = 1; /* Assume no edge loads */ for (bndvertlocnum = bndgrafdat.s.baseval; bndvertlocnum < bndvertlvlnum; bndvertlocnum ++) { /* For all vertices of band graph save for last layer */ Gnum bndedgelocnum; Gnum bndedgelocnnd; Gnum bndpartval; bndpartval = (Gnum) bndgrafdat.partgsttax[bndvertlocnum]; if (bndgrafdat.veexloctax != NULL) { commlocloadextn += bndgrafdat.veexloctax[bndvertlocnum] * bndpartval; commlocgainextn += bndgrafdat.veexloctax[bndvertlocnum] * (1 - bndpartval * 2); } for (bndedgelocnum = bndgrafdat.s.vertloctax[bndvertlocnum], bndedgelocnnd = bndgrafdat.s.vendloctax[bndvertlocnum]; bndedgelocnum < bndedgelocnnd; bndedgelocnum ++) { Gnum bndvertlocend; Gnum bndpartend; bndvertlocend = bndgrafdat.s.edgegsttax[bndedgelocnum]; bndpartend = bndgrafdat.partgsttax[bndvertlocend]; if (bndgrafdat.s.edloloctax != NULL) bndedlolocval = bndgrafdat.s.edloloctax[bndedgelocnum]; commlocloadintn += (bndpartval ^ bndpartend) * bndedlolocval; /* Internal load is accounted for twice */ } } for ( ; bndvertlocnum < bndvertancnnd; bndvertlocnum ++) { /* For all vertices of last layer, remove internal loads to band vertices once */ Gnum bndedgelocnum; Gnum bndedgelocnnd; Gnum bndpartval; bndpartval = (Gnum) bndgrafdat.partgsttax[bndvertlocnum]; if (bndgrafdat.veexloctax != NULL) { commlocloadextn += bndgrafdat.veexloctax[bndvertlocnum] * bndpartval; commlocgainextn += bndgrafdat.veexloctax[bndvertlocnum] * (1 - bndpartval * 2); } for (bndedgelocnum = bndgrafdat.s.vertloctax[bndvertlocnum], bndedgelocnnd = bndgrafdat.s.vendloctax[bndvertlocnum] - 1; /* "-1" to avoid anchor edges */ bndedgelocnum < bndedgelocnnd; bndedgelocnum ++) { Gnum bndvertlocend; Gnum bndpartend; bndvertlocend = bndgrafdat.s.edgegsttax[bndedgelocnum]; bndpartend = bndgrafdat.partgsttax[bndvertlocend]; if (bndgrafdat.s.edloloctax != NULL) bndedlolocval = bndgrafdat.s.edloloctax[bndedgelocnum]; commlocloadintn -= (bndpartval ^ bndpartend) * bndedlolocval; /* Remove internal loads to band graph vertices once because afterwards they will be accounted for twice */ } } memSet (orgflagloctab, 0, flagSize (orggrafptr->s.vertlocnnd) * sizeof (int)); /* Set vertices as not already considered */ for (bndfronlocnum = orgfronlocnum = 0; bndfronlocnum < bndgrafdat.fronlocnbr; bndfronlocnum ++) { /* Project back separator except for last layer */ Gnum bndvertlocnum; bndvertlocnum = bndgrafdat.fronloctab[bndfronlocnum]; if (bndvertlocnum < bndvertlvlnum) { /* If vertex does not belong to last layer */ Gnum orgvertlocnum; orgvertlocnum = bndgrafdat.s.vnumloctax[bndvertlocnum]; flagSet (orgflagloctab, orgvertlocnum); /* Set vertex as processed */ orggrafptr->fronloctab[orgfronlocnum ++] = orgvertlocnum; } } if (dgraphHaloWait (&requdat) != 0) { errorPrint ("bdgraphBipartBd: cannot complete asynchronous halo exchange"); return (1); } orgedlolocval = 1; /* Assume no edge loads */ commlocloadintn2 = 0; for (bndvertlocnum = bndvertlvlnum; bndvertlocnum < bndvertancnnd; bndvertlocnum ++) { /* For all vertices of last layer */ Gnum orgedgelocnum; Gnum orgedgelocnnd; Gnum orgvertlocnum; GraphPart orgpartval; Gnum orgflagval; orgvertlocnum = bndgrafdat.s.vnumloctax[bndvertlocnum]; orgpartval = bndgrafdat.partgsttax[bndvertlocnum]; orgflagval = 0; /* Assume vertex does not belong to the frontier */ for (orgedgelocnum = orggrafptr->s.vertloctax[orgvertlocnum], orgedgelocnnd = orggrafptr->s.vendloctax[orgvertlocnum]; orgedgelocnum < orgedgelocnnd; orgedgelocnum ++) { Gnum orgvertlocend; Gnum orgpartend; Gnum orgflagtmp; orgvertlocend = orggrafptr->s.edgegsttax[orgedgelocnum]; orgpartend = orggrafptr->partgsttax[orgvertlocend]; orgflagtmp = orgpartval ^ orgpartend; if (bndgrafdat.s.edloloctax != NULL) orgedlolocval = orggrafptr->s.edloloctax[orgedgelocnum]; orgflagval |= orgflagtmp; commlocloadintn2 += orgflagtmp * orgedlolocval; /* Internal load to band and original graph vertices are accounted for twice */ if ((orgflagtmp != 0) && (orgvertlocend < orggrafptr->s.vertlocnnd) && (flagVal (orgflagloctab, orgvertlocend) == 0)) { orggrafptr->fronloctab[orgfronlocnum ++] = orgvertlocend; flagSet (orgflagloctab, orgvertlocend); } } if ((orgflagval != 0) && (flagVal (orgflagloctab, orgvertlocnum) == 0)) orggrafptr->fronloctab[orgfronlocnum ++] = orgvertlocnum; flagSet (orgflagloctab, orgvertlocnum); /* Set vertex as processed anyway */ } commlocloadintn += 2 * commlocloadintn2; /* Add twice the internal load of original graph edges and once the one of band edges (one removed before) */ orggrafptr->complocload0 = bndgrafdat.complocload0 - bndvertlocancadj; orggrafptr->compglbload0 = bndgrafdat.compglbload0 - bndvertglbancadj; orggrafptr->compglbload0dlt = orggrafptr->compglbload0 - orggrafptr->compglbload0avg; orgprocsidnbr = orggrafptr->s.procsidnbr; if (orgprocsidnbr == 0) goto loop_exit; orgvertlocnum = orggrafptr->s.baseval; orgprocsidnum = 0; orgprocsidtab = orggrafptr->s.procsidtab; orgprocsidval = orgprocsidtab[orgprocsidnum ++]; while (1) { /* Scan all vertices which have foreign neighbors */ while (orgprocsidval < 0) { orgvertlocnum -= (Gnum) orgprocsidval; orgprocsidval = orgprocsidtab[orgprocsidnum ++]; } if (flagVal (orgflagloctab, orgvertlocnum) == 0) { /* If vertex not already processed */ Gnum orgedgelocnum; Gnum orgedgelocnnd; GraphPart orgpartval; orgpartval = orggrafptr->partgsttax[orgvertlocnum]; for (orgedgelocnum = orggrafptr->s.vertloctax[orgvertlocnum], orgedgelocnnd = orggrafptr->s.vendloctax[orgvertlocnum]; orgedgelocnum < orgedgelocnnd; orgedgelocnum ++) { if (orggrafptr->partgsttax[orggrafptr->s.edgegsttax[orgedgelocnum]] != orgpartval) { orggrafptr->fronloctab[orgfronlocnum ++] = orgvertlocnum; break; } } } do { if (orgprocsidnum >= orgprocsidnbr) goto loop_exit; } while ((orgprocsidval = orgprocsidtab[orgprocsidnum ++]) >= 0); } loop_exit : memFree (orgflagloctab); reduloctab[0] = commlocloadintn; /* Twice the internal load; sum globally before dividing by two */ reduloctab[1] = commlocloadextn; reduloctab[2] = commlocgainextn; reduloctab[3] = orgfronlocnum; if (MPI_Allreduce (&reduloctab[0], &reduglbtab[0], 4, GNUM_MPI, MPI_SUM, orggrafptr->s.proccomm) != MPI_SUCCESS) { errorPrint ("bdgraphBipartBd: communication error (3)"); return (1); } orggrafptr->fronlocnbr = orgfronlocnum; orggrafptr->fronglbnbr = reduglbtab[3]; orggrafptr->commglbload = (reduglbtab[0] / 2) * orggrafptr->domndist + reduglbtab[1]; orggrafptr->commglbgainextn = reduglbtab[2]; orggrafptr->bbalglbval = (double) ((orggrafptr->compglbload0dlt < 0) ? (- orggrafptr->compglbload0dlt) : orggrafptr->compglbload0dlt) / (double) orggrafptr->compglbload0avg; #ifdef SCOTCH_DEBUG_BDGRAPH2 if (bdgraphCheck (orggrafptr) != 0) { errorPrint ("bdgraphBipartBd: internal error (2)"); return (1); } #endif /* SCOTCH_DEBUG_BDGRAPH2 */ bdgraphExit (&bndgrafdat); return (0); }
static int C_graphScat ( FILE * const stream, SCOTCH_Num procnbr, char * const nameptr) { SCOTCH_Num versval; SCOTCH_Num propval; char proptab[4]; int flagtab[3]; SCOTCH_Num baseval; SCOTCH_Num vertglbnbr; SCOTCH_Num edgeglbnbr; SCOTCH_Num procnum; if (intLoad (stream, &versval) != 1) { /* Read version number */ errorPrint ("C_graphScat: bad input (1)"); return (1); } if (versval != 0) { /* If version not zero */ errorPrint ("C_graphScat: only centralized graphs supported"); return (1); } if ((intLoad (stream, &vertglbnbr) != 1) || /* Read rest of header */ (intLoad (stream, &edgeglbnbr) != 1) || (intLoad (stream, &baseval) != 1) || (intLoad (stream, &propval) != 1) || (propval < 0) || (propval > 111)) { errorPrint ("C_graphScat: bad input (2)"); return (1); } sprintf (proptab, "%3.3d", (int) propval); /* Compute file properties */ flagtab[0] = proptab[0] - '0'; /* Vertex labels flag */ flagtab[1] = proptab[1] - '0'; /* Edge weights flag */ flagtab[2] = proptab[2] - '0'; /* Vertex loads flag */ for (procnum = 0; procnum < procnbr; procnum ++) { char * nametmp; FILE * ostream; SCOTCH_Num vertlocnbr; SCOTCH_Num vertlocnum; SCOTCH_Num edgelocnbr; nametmp = nameptr; if ((fileNameDistExpand (&nametmp, procnbr, procnum, -1) != 0) || ((ostream = fopen (nametmp, "w+")) == NULL)) { errorPrint ("C_graphScat: cannot open file"); return (1); } memFree (nametmp); /* Expanded name no longer needed */ vertlocnbr = DATASIZE (vertglbnbr, procnbr, procnum); if (fprintf (ostream, "2\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n" SCOTCH_NUMSTRING "\t%015d\n" SCOTCH_NUMSTRING "\t%3s\n", /* Write file header */ (SCOTCH_Num) procnbr, (SCOTCH_Num) procnum, (SCOTCH_Num) vertglbnbr, (SCOTCH_Num) edgeglbnbr, (SCOTCH_Num) vertlocnbr, 0, /* Number of edges not yet known */ (SCOTCH_Num) baseval, proptab) == EOF) { errorPrint ("C_graphScat: bad output (1)"); return (1); } for (vertlocnum = edgelocnbr = 0; vertlocnum < vertlocnbr; vertlocnum ++) { SCOTCH_Num degrval; if (flagtab[0] != 0) { /* If must read label */ SCOTCH_Num vlblval; /* Value where to read vertex label */ if (intLoad (stream, &vlblval) != 1) { /* Read label data */ errorPrint ("C_graphScat: bad input (3)"); return (1); } intSave (ostream, vlblval); putc ('\t', ostream); } if (flagtab[2] != 0) { /* If must read vertex load */ SCOTCH_Num veloval; /* Value where to read vertex load */ if (intLoad (stream, &veloval) != 1) { /* Read vertex load data */ errorPrint ("C_graphScat: bad input (4)"); return (1); } intSave (ostream, veloval); putc ('\t', ostream); } if (intLoad (stream, °rval) != 1) { /* Read vertex degree */ errorPrint ("C_graphScat: bad input (5)"); return (1); } intSave (ostream, degrval); edgelocnbr += degrval; for ( ; degrval > 0; degrval --) { SCOTCH_Num edgeval; /* Value where to read edge end */ if (flagtab[1] != 0) { /* If must read edge load */ SCOTCH_Num edloval; /* Value where to read edge load */ if (intLoad (stream, &edloval) != 1) { /* Read edge load data */ errorPrint ("C_graphScat: bad input (6)"); return (1); } putc ('\t', ostream); intSave (ostream, edloval); } if (intLoad (stream, &edgeval) != 1) { /* Read edge data */ errorPrint ("C_graphScat: bad input (7)"); return (1); } putc ('\t', ostream); intSave (ostream, edgeval); } putc ('\n', ostream); } rewind (ostream); if (fprintf (ostream, "2\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n" SCOTCH_NUMSTRING "\t" SCOTCH_NUMSTRING "\n" SCOTCH_NUMSTRING "\t%015lld\n" SCOTCH_NUMSTRING "\t%3s\n", /* Write file header */ (SCOTCH_Num) procnbr, (SCOTCH_Num) procnum, (SCOTCH_Num) vertglbnbr, (SCOTCH_Num) edgeglbnbr, (SCOTCH_Num) vertlocnbr, (long long) edgelocnbr, /* Now we know the exact number of edges */ (SCOTCH_Num) baseval, proptab) == EOF) { errorPrint ("C_graphScat: bad output (2)"); return (1); } fclose (ostream); } return (0); }
Gnum * restrict vertloctax; Gnum * restrict veloloctax; #ifdef SCOTCH_DEBUG_DGRAPH3 Gnum * restrict vlblloctax; #endif /* SCOTCH_DEBUG_DGRAPH3 */ Gnum edgelocnbr; Gnum * restrict edgeloctax; Gnum edgelocnum; Gnum edlolocnbr; Gnum * restrict edloloctax; int cheklocval; Gnum reduloctab[7]; Gnum reduglbtab[7]; vertglbnbr = 1 << hcubdim; vertlocnbr = DATASIZE (vertglbnbr, grafptr->procglbnbr, grafptr->proclocnum); velolocnbr = ((flagval & 1) != 0) ? vertlocnbr : 0; edgelocnbr = vertlocnbr * hcubdim; /* Set local number of arcs */ edlolocnbr = ((flagval & 2) != 0) ? edgelocnbr : 0; for (procngbnum = 0, vertglbnum = 0; /* Compute index of first local vertex */ procngbnum < grafptr->proclocnum; procngbnum ++) vertglbnum += DATASIZE (vertglbnbr, grafptr->procglbnbr, procngbnum); cheklocval = 0; vertloctax = edgeloctax = NULL; if (memAllocGroup ((void **) (void *) &vertloctax, (size_t) ((vertlocnbr + 1) * sizeof (Gnum)), /* Compact vertex array */ #ifdef SCOTCH_DEBUG_DGRAPH3 &vlblloctax, (size_t) (vertlocnbr * sizeof (Gnum)),
//--------------|--------------------------------------------- HXRET hxput(HXFILE * hp, char const *recp, int leng) { HXLOCAL loc, *locp = &loc; if (!hp || leng < 0 || !recp || leng > hxmaxrec(hp) || !(hp->mode & HX_UPDATE) || !hp->test) return HXERR_BAD_REQUEST; if (leng && !hx_test(hp, recp, leng)) return HXERR_BAD_RECORD; if (SCANNING(hp) && hx_diff(hp, recp, RECDATA(_hxcurrec(hp)))) return HXERR_BAD_REQUEST; ENTER(locp, hp, recp, 3); _hxlockset(locp, leng ? HIGH_LOCK : HEAD_LOCK); if (IS_MMAP(hp)) _hxremap(locp); int may_find = 1, loops = HX_MAX_CHAIN; int newsize = leng ? leng + sizeof(HXREC) : 0; HXBUF *currp = &locp->buf[0], *prevp = &locp->buf[1]; // If scanning is on an overflow page, and hxdel might // empty the page, hxput after hxnext can't just jump to // the right page, because (prevp) is not loaded, // so deleting currp would hard. _hxload(locp, currp, SCANNING(hp) && (leng || IS_HEAD(hp->buffer.pgno)) ? hp->buffer.pgno : locp->head); while (1) { int pos, hindpos, skip = 0; PAGENO nextpg = currp->next; if (!--loops) LEAVE(locp, HXERR_BAD_FILE); // Search for the key (an old record to be deleted). // If SCANNING: the file is locked, and the matching // record must be there. pos = !may_find ? -1 : !SCANNING(hp) ? _hxfind(locp, currp, locp->hash, recp, &hindpos) : currp->pgno == hp->buffer.pgno ? hp->currpos : -1; if (pos >= 0) { char *oldp = currp->data + pos; COUNT oldsize = RECSIZE(oldp); int delta = newsize - oldsize; locp->ret = RECLENG(oldp); may_find = 0; assert(!currp->delta); currp->delpos = pos; currp->delta = delta; if (!newsize) { // hxdel or remove after inserted previously. _hxremove(currp, pos, oldsize); currp->recs--; if (SCANNING(hp)) hp->recsize = 0; } else if (FITS(hp, currp, delta, 0)) { // replace if (delta) { memmove(oldp + newsize, oldp + oldsize, currp->used - pos - oldsize); currp->used += delta; STSH(leng, oldp + sizeof(PAGENO)); if (SCANNING(hp)) hp->recsize = newsize; DEINDEX(currp); // force indexify } memcpy(oldp + sizeof(HXREC), recp, leng); STAIN(currp); newsize = 0; } else if (SCANNING(hp)) { // At this point we are stuck: if we delete the old copy of // the record, we are committed to inserting the new copy // somewhere else, but that might require changing links // or even growing the file: a NO-NO during a hxnext scan. LEAVE(locp, HXERR_BAD_REQUEST); } else { // Delete old version and continue (insert elsewhere). _hxremove(currp, pos, oldsize); currp->recs--; } } if (currp->used && !IS_HEAD(currp->pgno) && SHRUNK(prevp)) skip = !_hxshift(locp, locp->head, 0, currp, prevp, NULL); // Insert the new record if it fits. if (newsize && FITS(hp, currp, newsize, 1)) { HXREC hdr; STLG(locp->hash, &hdr.hash); STSH(leng, &hdr.leng); _hxappend(currp, (char *)&hdr, sizeof hdr); _hxappend(currp, recp, leng); currp->recs++; newsize = 0; } // If the current page contains only data of OTHER heads // -- and hence, must be at the END of a chain -- // unlink it from this chain. If the page is empty, // unlink it AND put it in the freemap. if (IS_HEAD(currp->pgno)) { skip = 0; } else if (!currp->used) { skip = 1; _hxputfreed(locp, currp); if (SCANNING(hp) && hp->buffer.pgno == currp->pgno) hp->buffer.used = 0; } else if (currp->next || !SHRUNK(currp)) { skip = 0; } else if (!skip) { // If skip not set by _hxshift above... char const *rp, *ep; FOR_EACH_REC(rp, currp, ep) if (locp->head == _hxhead(locp, RECHASH(rp))) break; skip = rp == ep; // No recs for locp->head in this tail. } if (skip) LINK(prevp, nextpg); else SWAP(prevp, currp); sync_save(locp, currp); if (!newsize && !prevp->next) break; if (!newsize && !may_find && !SHRUNK(prevp)) break; if (prevp->next) { _hxload(locp, currp, prevp->next); continue; } // We are at the end of the chain, and rec not yet inserted. // Unlocking is necessary even if tail is not shared; // it may be hp->tail.pgno in some other process. if (!FILE_HELD(hp) && !IS_HEAD(prevp->pgno)) _hxunlock(locp, prevp->pgno, 1); // _hxshare/_hxfindfree may update the map (root etc). // Split MUST be locked before root, else risk deadlock. _hxlockset(locp, BOTH_LOCK); if (IS_MMAP(hp)) _hxremap(locp); // At this point assert: // - head is locked, split is locked, // - head matches hash, npages matches filesize. // After locking the split, no other process can change // the file size. may_find = 0; COUNT need = IS_HEAD(prevp->pgno) ? newsize : 0; if (!_hxshare(locp, currp, need) && !_hxgetfreed(locp, currp) && !_hxfindfree(locp, currp)) { // _hxgrow will zero samehead if it splits locp->head. PAGENO samehead = locp->head; // _hxgrow will change the file length. A concurrent // hxget/hxdel could miscalculate locp->head as // being the newly-added page. _hxlock(locp, locp->npages, 0); _hxgrow(locp, currp, need, &samehead); DEBUG3("head=%u samehead=%u", locp->head, samehead); if (!samehead) { _hxputfreed(locp, currp); _hxpoint(locp); _hxload(locp, currp, locp->head); loops = HX_MAX_CHAIN; continue; } } // _hxgrow may clobber prevp, so we reload it. Even if // prevp->pgno == locp->head, prevp may contain an // obsolete copy of the head page. The empty page is // always appended to head. _hxshare only returns true // if currp is head and currp->next is 0, so it can't // clobber it. _hxsave(locp, prevp); _hxload(locp, prevp, locp->head); LINK(currp, prevp->next); LINK(prevp, currp->pgno); currp->orig = DATASIZE(hp); // make SHRUNK be true }
//--------------|--------------------------------------------- HXRET hxshape(HXFILE * hp, double overload) { HXLOCAL loc, *locp = &loc; HXBUF *srcp, *dstp, *oldp; int pos, bitpos; PGINFO *atail, *ztail; PAGENO pg, pm, *aprev, *afree, *zfree; double totbytes = 0, fullbytes = 0, fullpages = 0; if (!hp || hp->buffer.pgno || hp->mode & HX_MMAP || !(hp->mode & HX_UPDATE)) return HXERR_BAD_REQUEST; ENTER(locp, hp, NULL, 3); _hxlock(locp, 0, 0); _hxsize(locp); srcp = &locp->buf[0]; dstp = &locp->buf[1]; oldp = &locp->buf[2]; _hxinitRefs(locp); // Populate vnext,vrefs,vtail for tail-merging: ztail = calloc(locp->npages / HXPGRATE + 1, sizeof(PGINFO)); locp->vtail = ztail; for (pg = 1; pg < locp->npages; ++pg) { PGINFO x = _hxpginfo(locp, pg); _hxsetRef(locp, pg, x.pgno); totbytes += x.used; if (x.pgno) // i.e. page.next != 0 ++fullpages, fullbytes += x.used; else if (x.used && !IS_HEAD(pg)) x.pgno = pg, *ztail++ = x; } // Sort vtail by (used), so that smallest+largest (used) // counts can be matched up; simple greedy-fill algorithm. qsort(locp->vtail, ztail - locp->vtail, sizeof *locp->vtail, (cmpfn_t) cmpused); // Combine tail pages where possible: for (atail = locp->vtail, --ztail; atail < ztail;) { if (!_FITS(hp, atail->used, atail->recs, ztail->used, ztail->recs)) { --ztail; continue; } // Merge is always from [atail] to [ztail], to maintain // ([ztail].used >= [ztail-1].used). if (atail->pgno < ztail->pgno) { PGINFO tmp = *atail; *atail = *ztail; *ztail = tmp; } _hxload(locp, srcp, atail->pgno); _hxload(locp, dstp, ztail->pgno); _hxappend(dstp, srcp->data, srcp->used); dstp->recs += srcp->recs; _hxsave(locp, dstp); _hxfindRefs(locp, srcp, srcp->pgno); for (aprev = locp->vprev; *aprev; ++aprev) PUTLINK(locp, *aprev, dstp->pgno); ztail->used += srcp->used; srcp->used = srcp->recs = 0; BUFLINK(locp, srcp, 0); _hxsave(locp, srcp); _hxalloc(locp, srcp->pgno, 0); ++atail; } // Now decide whether to grow or shrink the file. PAGENO overflows = 0; for (pg = 1; pg < locp->npages; ++pg) { if (IS_HEAD(pg)) { int loops = HX_MAX_CHAIN; for (pm = pg; (pm = locp->vnext[pm]); ++overflows) if (!--loops) LEAVE(locp, HXERR_BAD_FILE); } } PAGENO dpages = locp->dpages + overflows; PAGENO goodsize = dpages / (1.0 + overload); DEBUG("%.0f/%.0f=%0.f %.0f %lu/%.2f=%lu => %lu", fullbytes, fullpages, fullbytes / fullpages, totbytes, dpages, overload + 1, goodsize, _hxd2f(goodsize)); // "+1" for the root page goodsize = goodsize ? _hxd2f(goodsize) + 1 : 2; if (locp->npages <= goodsize) { // Increase dpages. // Note that _hxgrow always returns an ALLOCATED // overflow. It would be smarter to clear all the // map bits in one step at the end, the way // hxbuild sets all the map bits in one load/save. PAGENO junk = 0; while (locp->npages < goodsize) { _hxgrow(locp, dstp, DATASIZE(hp), &junk); _hxsave(locp, dstp); _hxalloc(locp, dstp->pgno, 0); } _hxflushfreed(locp, dstp); LEAVE(locp, HXNOTE); } // Build a list of free pgnos assert(sizeof *afree <= sizeof *locp->vtail); afree = zfree = (PAGENO *) locp->vtail; for (pg = pm = 0; pg < locp->npages; pg += HXPGRATE) { if (!VREF(locp, pg) && !IS_MAP(hp, pg)) *zfree++ = pg; } // Since we are decrementing npages BEFORE reading last page, // set locked such that _hxislocked gives correct answer. hp->locked |= LOCKED_BEYOND; // Work backward from end of file, trimming pages. for (; locp->npages > goodsize; --locp->npages) { PAGENO srchead = locp->npages - 1; PAGENO srctail, dsthead, dstneck, dsttail; int loops = HX_MAX_CHAIN; // EASIEST CASE: a map or unreferenced oveflow page if (srchead == zfree[-1] || IS_MAP(hp, srchead)) { assert(!VREF(locp, srchead) && !IS_HEAD(srchead)); --zfree; continue; } // EASIER CASE: an empty head page _hxload(locp, srcp, srchead); if (!srcp->used) continue; // Anything from here on might need 2 free pages if (zfree - afree < 2) break; --VREF(locp, srcp->next); STAIN(srcp); srcp->pgno = *afree++; # if 0 // hxshape does not work with MMAP as yet. if (hp->mmap) memcpy(&hp->mmap[(off_t) srcp->pgno * hp->pgsize], srcp->page, hp->pgsize); # endif _hxalloc(locp, srcp->pgno, 1); _hxsetRef(locp, srcp->pgno, srcp->next); // EASY CASE: an overflow page to relocate: if (!IS_HEAD(srchead)) { _hxsave(locp, srcp); _hxfindRefs(locp, srcp, srchead); for (aprev = locp->vprev; *aprev; ++aprev) PUTLINK(locp, *aprev, srcp->pgno); continue; } // HARD CASE: a head page to desplit: locp->hash = RECHASH(srcp->data); _hxpoint(locp); // recalc (dpages,head) dsthead = locp->head; dstneck = locp->vnext[dsthead]; dsttail = _hxgetRef(locp, dsthead, 0); srctail = _hxgetRef(locp, srchead, 0); // Append srchead to dsttail, or insert chain between // dsthead and vnext[dsthead]. If srctail is shared, // make a copy of * it first. if (dsttail == dsthead || VREF(locp, dsttail) == 1) { dsthead = dsttail; } else if (srctail == srchead) { BUFLINK(locp, srcp, dstneck); } else if (VREF(locp, srctail) == 1) { PUTLINK(locp, srctail, dstneck); } else if (srctail == dsttail) { if (dsttail != dstneck) { srctail = _hxgetRef(locp, srcp->pgno, srctail); if (srctail == srcp->pgno) { BUFLINK(locp, srcp, dstneck); } else { PUTLINK(locp, srctail, dstneck); } } } else { _hxload(locp, oldp, srctail); if (!oldp->used) LEAVE(locp, HXERR_BAD_FILE); _hxfresh(locp, dstp, *afree++); _hxalloc(locp, dstp->pgno, 1); _hxshift(locp, locp->head, srchead, oldp, dstp, dstp); _hxsave(locp, oldp); // This hack prevents the CHECK in _hxlink from // aborting when oldp contains a page that the // next iteration wants to PUTLINK. This ONLY occurs // in this code (I think). // TODO: can this happen in (hxfix,hxshape)?? oldp->pgno = -1; BUFLINK(locp, dstp, dstneck); _hxsave(locp, dstp); if (srcp->next == srctail) { BUFLINK(locp, srcp, dstp->pgno); } else { pg = _hxgetRef(locp, srchead, srctail); PUTLINK(locp, pg, dstp->pgno); } } _hxload(locp, dstp, dsthead); BUFLINK(locp, dstp, srcp->pgno); // Cannot early-out on !SHRUNK here (as "hxput" does); // new chain may have vacancies in two places. while (1) { if (!--loops) LEAVE(locp, HXERR_BAD_FILE); if (_hxshift(locp, locp->head, srchead, srcp, dstp, dstp)) { SWAP(srcp, dstp); } else { BUFLINK(locp, dstp, srcp->next); if (!srcp->used != !VREF(locp, srcp->pgno)) LEAVE(locp, HXERR_BAD_FILE); if (!srcp->used) { BUFLINK(locp, srcp, 0); *--afree = srcp->pgno; _hxalloc(locp, srcp->pgno, 0); } } _hxsave(locp, srcp); if (!dstp->next) break; _hxload(locp, srcp, dstp->next); } _hxsave(locp, dstp); } // npages was overdecremented by one in loop _hxresize(locp, locp->npages + 1); // Zero the freemap for all truncated overflow pages: pg = _hxmap(hp, locp->npages + HXPGRATE - locp->npages % HXPGRATE, &bitpos); _hxload(locp, dstp, pg); DEBUG2("clear map %lu from bit %d onward", pg, bitpos); pos = bitpos >> 3; dstp->data[pos++] &= ~(-1 << (bitpos & 7)); memset(dstp->data + pos, 0, DATASIZE(hp) - pos); STAIN(dstp); _hxsave(locp, dstp); LEAVE(locp, HXOKAY); }