void startSnapshot(int indexCnt, int[] freeIndexes, DBChangeSet changeSet, TaskMonitor monitor)
			throws CancelledException, IOException {
		if (activeFile != null) {
			throw new AssertException("Snapshot already in progress");
		}
		recovered = false;
		++snapshotIndex;
		if (snapshotIndex == 2) {
			snapshotIndex = 0;
		}

		// Prevent duplicate snapshot times
		long t = (new Date()).getTime();
		if ((t - lastSnapshotTime) < 1) {
			try {
				Thread.sleep(2);
			}
			catch (InterruptedException e) {
			}
			t = (new Date()).getTime();
		}

		boolean success = false;
		try {
			newSnapshot = !snapshotFiles[snapshotIndex].exists();
			try {
				activeFile = new RecoveryFile((LocalBufferFile) bufferMgr.getSourceFile(),
					snapshotFiles[snapshotIndex], newSnapshot);
			}
			catch (IOException e) {
				if (newSnapshot) {
					throw e;
				}
				// Assume an invalid file - remove bad snapshot and create a new file
				snapshotFiles[snapshotIndex].delete();
				newSnapshot = true;
				activeFile = new RecoveryFile((LocalBufferFile) bufferMgr.getSourceFile(),
					snapshotFiles[snapshotIndex], newSnapshot);
			}
			activeFile.setIndexCount(indexCnt);
			activeFile.setFreeIndexList(freeIndexes);
			oldIndexSet = new IntSet(activeFile.getBufferIndexes());
			if (changeSet != null) {
				activeFile.setParameter(CHANGE_SET_REQUIRED_PARM, 1);
				changeFiles[snapshotIndex].delete();
				DBHandle csh = new DBHandle();
				try {
					changeSet.write(csh, true);
					csh.saveAs(changeFiles[snapshotIndex], true, monitor);
				}
				finally {
					csh.close();
				}
			}
			else {
				activeFile.setParameter(CHANGE_SET_REQUIRED_PARM, 0);
			}
			success = true;
		}
		finally {
			if (!success && activeFile != null) {
				activeFile.close();
				activeFile = null;
				snapshotFiles[snapshotIndex].delete();
				changeFiles[snapshotIndex].delete();
			}
		}
		buffersSaved[snapshotIndex] = 0;
		buffersIgnored[snapshotIndex] = 0;
		buffersRemoved[snapshotIndex] = 0;
	}
Open a recovery file for an updated snapshot
@param indexCnt the total number of allocated indexes within the corresponding source buffer file.
@param freeIndexes a list of indexes which are currently free/empty.
@param changeSet an optional database-backed change set which reflects changes
made since the last version.
@param monitor
@throws IOException
@throws CancelledException
Ghidra/Framework/DB/src/main/java/db/buffers/RecoveryMgr.java