public void save(String comment, DBChangeSet changeSet, TaskMonitor monitor)
			throws IOException, CancelledException {

		synchronized (snapshotLock) {
			synchronized (this) {
				if (!(sourceFile instanceof ManagedBufferFile)) {
					throw new IOException("Save not allowed");
				}

				if (corruptedState) {
					throw new IOException("Corrupted BufferMgr state");
				}

				if (lockCount != 0) {
					throw new IOException("Attempted save while buffers are locked");
				}

				if (monitor == null) {
					monitor = TaskMonitor.DUMMY;
				}

				boolean oldCancelState = monitor.isCancelEnabled();

				ManagedBufferFile outFile = null;
				monitor.setMessage("Waiting for pre-save to complete...");
				if (sourceFile instanceof LocalManagedBufferFile) {
					// Use monitor for local saves
					outFile = ((LocalManagedBufferFile) sourceFile).getSaveFile(monitor);
				}
				else {
					// Monitor not supported for remote saves
					monitor.setCancelEnabled(false);
					outFile = ((ManagedBufferFile) sourceFile).getSaveFile();
					monitor.setCancelEnabled(oldCancelState & !monitor.isCancelled());
				}
				if (outFile == null) {
					throw new IOException("Save not allowed");
				}

				boolean success = false;
				try {

					if (comment != null) {
						outFile.setVersionComment(comment);
					}

					doSave(outFile, monitor);
					monitor.setCancelEnabled(false);

					if (changeSet != null) {
						BufferFile changeFile =
							((ManagedBufferFile) sourceFile).getSaveChangeDataFile();
						if (changeFile != null) {
							monitor.setMessage("Saving change data...");
							DBHandle cfh = new DBHandle(outFile.getBufferSize());
							changeSet.write(cfh, false);
							cfh.saveAs(changeFile, true, null);
							cfh.close();
						}
					}
					monitor.setMessage("Completing file save...");
					success = true;
				}
				finally {
					((ManagedBufferFile) sourceFile).saveCompleted(success);
					monitor.setCancelEnabled(oldCancelState & !monitor.isCancelled());
				}

				doSetSourceFile(outFile);
			}
		}
	}
Save the current set of buffers to a new version of the source buffer file.
If the buffer manager was not instantiated with a source file an
IllegalStateException will be thrown.
@param comment if version history is maintained, this comment will be
associated with the new version.
@param changeSet an optional database-backed change set which reflects changes
made since the last version.
@param monitor a cancellable task monitor.  This method will establish the
maximum progress count.
@throws CancelledException if the task monitor cancelled the operation.
@throws IOException if source, cache or destination file access error occurs
Ghidra/Framework/DB/src/main/java/db/buffers/BufferMgr.java