void moveAddressRange(Address fromAddr, Address toAddr, long length, TaskMonitor monitor)
			throws AddressOverflowException, CancelledException {

		lock.acquire();
		try {
			Address rangeEnd = fromAddr.addNoWrap(length - 1);

			AddressSet addrSet = new AddressSet(fromAddr, rangeEnd);
			ArrayList<FragmentHolder> list = new ArrayList<>();

			AddressRangeIterator rangeIter = fragMap.getAddressRanges(fromAddr, rangeEnd);
			while (rangeIter.hasNext() && !addrSet.isEmpty()) {
				monitor.checkCancelled();
				AddressRange range = rangeIter.next();
				Field field = fragMap.getValue(range.getMinAddress());
				try {
					FragmentDB frag = getFragmentDB(field.getLongValue());
					AddressSet intersection = addrSet.intersect(frag);
					AddressRangeIterator fragRangeIter = intersection.getAddressRanges();
					while (fragRangeIter.hasNext() && !monitor.isCancelled()) {
						AddressRange fragRange = fragRangeIter.next();

						Address startAddr = fragRange.getMinAddress();
						Address endAddr = fragRange.getMaxAddress();

						long offset = startAddr.subtract(fromAddr);
						startAddr = toAddr.add(offset);
						offset = endAddr.subtract(fromAddr);
						endAddr = toAddr.add(offset);

						AddressRange newRange = new AddressRangeImpl(startAddr, endAddr);

						frag.removeRange(fragRange);
						list.add(new FragmentHolder(frag, newRange));
					}
					addrSet = addrSet.subtract(intersection);
				}
				catch (IOException e) {
					errHandler.dbError(e);
					return;
				}

			}

			monitor.checkCancelled();
			fragMap.clearRange(fromAddr, rangeEnd);

			for (FragmentHolder fh : list) {
				monitor.checkCancelled();
				fragMap.paintRange(fh.range.getMinAddress(), fh.range.getMaxAddress(),
					new LongField(fh.frag.getKey()));
				fh.frag.addRange(fh.range);
			}
			treeMgr.updateTreeRecord(record);

			// generate an event...
			getProgram().programTreeChanged(treeID, ProgramEvent.FRAGMENT_MOVED, null,
				new AddressRangeImpl(fromAddr, rangeEnd),
				new AddressRangeImpl(toAddr, toAddr.addNoWrap(length - 1)));

		}
		finally {
			lock.release();
		}
	}
Construct a program tree module manager
@param treeMgr program tree manager
@param rec program tree record
@param openMode the mode this adapter is to be opened for (CREATE, UPDATE, READ_ONLY, UPGRADE).
@param monitor task monitor
@throws IOException if a database IO error occurs
@throws CancelledException if monitor cancelled (upgrade case only)
@throws VersionException if opening an existing program tree and an underlying table 
schema version differs from the expected version.
Ghidra/Framework/SoftwareModeling/src/main/java/ghidra/program/database/module/ModuleManager.java