bits32 writeIndexLevel(struct chromInfo **chromArray, int chromCount, bits32 indexOffset, int level, FILE *f) /* Write out a non-leaf level. */ { /* Calculate number of nodes to write at this level. */ int slotSizePer = xToY(blockSize, level); // Number of chroms per slot in node int nodeSizePer = slotSizePer * blockSize; // Number of chroms per node int nodeCount = (chromCount + nodeSizePer - 1)/nodeSizePer; /* Calculate sizes and offsets. */ int bytesInBlock = (2*sizeof(UBYTE) + sizeof(bits16) + blockSize * (2*sizeof(bits32))); bits32 levelSize = nodeCount * bytesInBlock; bits32 endLevel = indexOffset + levelSize; bits32 nextChild = endLevel; UBYTE isLeaf = FALSE; UBYTE reserved = 0; int i,j; for (i=0; i<chromCount; i += nodeSizePer) { /* Calculate size of this block */ bits16 countOne = (chromCount - i + slotSizePer - 1)/slotSizePer; if (countOne > blockSize) countOne = blockSize; /* Write block header. */ writeOne(f, isLeaf); writeOne(f, reserved); writeOne(f, countOne); int slotsUsed = 0; int endIx = i + nodeSizePer; if (endIx > chromCount) endIx = chromCount; for (j=i; j<endIx; j += slotSizePer) { struct chromInfo *chrom = chromArray[j]; writeOne(f, chrom->genomeOffset); writeOne(f, nextChild); nextChild += bytesInBlock; ++slotsUsed; } assert(slotsUsed == countOne); for (j=countOne; j<blockSize; ++j) { bits32 genomeOffsetPad=0; bits32 binFileOffsetPad=0; writeOne(f, genomeOffsetPad); writeOne(f, binFileOffsetPad); } } return endLevel; }
static bits32 writeIndexLevel(bits16 blockSize, void *itemArray, int itemSize, long itemCount, bits32 indexOffset, int level, void (*fetchKey)(const void *va, char *keyBuf), bits32 keySize, bits32 valSize, FILE *f) /* Write out a non-leaf level. */ { char *items = itemArray; /* Calculate number of nodes to write at this level. */ long slotSizePer = xToY(blockSize, level); // Number of items per slot in node long nodeSizePer = slotSizePer * blockSize; // Number of items per node long nodeCount = (itemCount + nodeSizePer - 1)/nodeSizePer; /* Calculate sizes and offsets. */ long bytesInIndexBlock = (bptBlockHeaderSize + blockSize * (keySize+sizeof(bits64))); long bytesInLeafBlock = (bptBlockHeaderSize + blockSize * (keySize+valSize)); bits64 bytesInNextLevelBlock = (level == 1 ? bytesInLeafBlock : bytesInIndexBlock); bits64 levelSize = nodeCount * bytesInIndexBlock; bits64 endLevel = indexOffset + levelSize; bits64 nextChild = endLevel; UBYTE isLeaf = FALSE; UBYTE reserved = 0; long i,j; char keyBuf[keySize+1]; keyBuf[keySize] = 0; for (i=0; i<itemCount; i += nodeSizePer) { /* Calculate size of this block */ long countOne = (itemCount - i + slotSizePer - 1)/slotSizePer; if (countOne > blockSize) countOne = blockSize; bits16 shortCountOne = countOne; /* Write block header. */ writeOne(f, isLeaf); writeOne(f, reserved); writeOne(f, shortCountOne); /* Write out the slots that are used one by one, and do sanity check. */ int slotsUsed = 0; long endIx = i + nodeSizePer; if (endIx > itemCount) endIx = itemCount; for (j=i; j<endIx; j += slotSizePer) { void *item = items + j*itemSize; memset(keyBuf, 0, keySize); (*fetchKey)(item, keyBuf); mustWrite(f, keyBuf, keySize); writeOne(f, nextChild); nextChild += bytesInNextLevelBlock; ++slotsUsed; } assert(slotsUsed == shortCountOne); /* Write out empty slots as all zero. */ int slotSize = keySize + sizeof(bits64); for (j=countOne; j<blockSize; ++j) repeatCharOut(f, 0, slotSize); } return endLevel; }