Пример #1
0
void IndexBuilder::writeSnapshots(Reader &reader, KZip &zip)
{
	static const qint64 SNAPSHOT_INTERVAL_MS = 1000; // snapshot interval in milliseconds
	static const int SNAPSHOT_MIN_ACTIONS = 200; // minimum number of actions between snapshots

	paintcore::LayerStack image;
	net::LayerListModel layermodel;
	canvas::StateTracker statetracker(&image, &layermodel, 1);

	MessageRecord msg;
	int snapshotCounter = 0;
	QElapsedTimer timer;
	timer.start();
	while(true) {
		if(_abortflag.load())
			return;

		msg = reader.readNext();
		if(msg.status == MessageRecord::END_OF_RECORDING)
			break;
		else if(msg.status == MessageRecord::INVALID)
			continue;

		protocol::MessagePtr m(msg.message);
		if(m->isCommand()) {
			statetracker.receiveCommand(m);
			++snapshotCounter;
		}

		// Save a snapshot every SNAPSHOT_INTERVAL or at every marker. (But no more often than SNAPSHOT_MIN_ACTIONS)
		// Note. We use the actual elapsed rendering time to decide when to snapshot. This means that (ideally),
		// the time it takes to jump to a snapshot is at most SNAPSHOT_INTERVAL milliseconds (+ the time it takes to load the snapshot)
		if(m_index.snapshots().isEmpty() || ((timer.hasExpired(SNAPSHOT_INTERVAL_MS) || m->type() == protocol::MSG_MARKER) && snapshotCounter>=SNAPSHOT_MIN_ACTIONS)) {
			qint64 streampos = reader.filePosition();
			emit progress(streampos);
			canvas::StateSavepoint sp = statetracker.createSavepoint(-1);

			QBuffer buf;
			buf.open(QBuffer::ReadWrite);
			{
				QDataStream ds(&buf);
				sp.toDatastream(ds);
			}

			int snapshotIdx = m_index.m_snapshots.size();
			zip.writeFile(QString("snapshot-%1").arg(snapshotIdx), buf.data());
			m_index.m_snapshots.append(SnapshotEntry(streampos, reader.currentIndex()));

			snapshotCounter = 0;
			timer.restart();
		}
	}
}