@Override
	MemoryBlockDB createInitializedBlock(String name, Address startAddr, InputStream is,
			long length, int flags) throws AddressOverflowException, IOException {

		// TODO verify that it is necessary to pre-define all segments in the address map
		updateAddressMapForAllAddresses(startAddr, length);

		List<SubMemoryBlock> subBlocks = new ArrayList<>();
		try {
			DBRecord blockRecord = createMemoryBlockRecord(name, startAddr, length, flags);
			long key = blockRecord.getKey();
			int numFullBlocks = (int) (length / maxSubBlockSize);
			int lastSubBlockSize = (int) (length % maxSubBlockSize);
			long blockOffset = 0;
			for (int i = 0; i < numFullBlocks; i++) {
				subBlocks.add(createBufferSubBlock(key, blockOffset, maxSubBlockSize, is));
				blockOffset += maxSubBlockSize;
			}
			if (lastSubBlockSize > 0) {
				subBlocks.add(createBufferSubBlock(key, blockOffset, lastSubBlockSize, is));
			}
			memBlockTable.putRecord(blockRecord);

			MemoryBlockDB newBlock = new MemoryBlockDB(this, blockRecord, subBlocks);
			cacheNewBlock(newBlock);
			return newBlock;
		}
		catch (IOCancelledException e) {
			// clean up any created DBBufferss
			for (SubMemoryBlock subMemoryBlock : subBlocks) {
				BufferSubMemoryBlock bufferSubMemoryBlock = (BufferSubMemoryBlock) subMemoryBlock;
				subBlockTable.deleteRecord(bufferSubMemoryBlock.getKey());
				bufferSubMemoryBlock.buf.delete();
			}
			throw e;
		}
	}
MemoryMap adapter for version 3.
This version introduces the concept of sub memory blocks and FileBytes
Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/mem/MemoryMapDBAdapterV3.java