Using Incremental Saving for .dwg Files

Iakov Shamrai
April 13, 2017

Tags: performance Example

When working with large .dwg files, sometimes a full save can be slow. Teigha has a new incremental file saving feature for .dwg files that saves only modified data, which is faster than a full save for large files that don’t contain a lot of modifications.

Teigha provides two methods to perform the incremental file save:

void OdDbDatabase::save(const OdString& filename, bool saveThumbnailImage = false);
void OdDbDatabase::save(OdStreamBuf* pStreamBuf, bool saveThumbnailImage = false);

Incremental saving using an absolute path

In most cases, you can save your current .dwg database incrementally using the OdDbDatabase::save() method which takes a path as the first parameter. The call is as follows:

pDb->save(targetPath);

The first parameter is a target file absolute path. The path should be equal to another one which can be obtained from the database you want to save. If the absolute path does not match, the method will perform a full save. The second parameter controls the saving of a thumbnail image to the file.

A file will be saved incrementally under the following conditions only:

  • the file is a .dwg file
  • the target file absolute path is equal to the original as described above
  • the file has been saved previously
  • the database version of the file is equal to OdDb::kDHL_CURRENT (latest format)

Also, the method behavior depends on the value of the ISAVEPERCENT system variable. The ISAVEPERCENT value is a percentage of wasted space tolerated in the file. If ISAVEPERCENT is equal to 0, the method will perform a full save. Otherwise, it works as follows:

  • If the actual percentage of wasted space is less than or equal to ISAVEPERCENT, the method will perform the incremental file save.
  • If the actual percentage of wasted space is greater than ISAVEPERCENT, the method will perform a full save.

It is recommended to use the OdDbDatabase::save(…) method when performing a file save operation using the SAVE command. But for SAVEAS, you should use the OdDbDatabase::writeFile(…) method. You can separate corresponding calls when implementing your own application.

See also the OdaMfcApp example application for how to use incremental file saving: Core\Examples\win\OdaMfcApp\OdaMfcAppDoc.cpp

Incremental saving using OdStreamBuf

If you want to save the database incrementally to a temporary file, you should use the second version of the OdDbDatabase::save(…) method that takes a pointer to OdStreamBuf.

You may need this method to save files more safely by using a copy of the original file.

For example, you can use the following steps to process your file.

Copy your original file to the temporary one when the file processing starts:

OdString cmdString("copy \"" + targetPath + "\" \"" + pathToTemp + "\"");
system(cmdString);

To save a currently opened database (which was read from the original file) to the temporary file you created as a copy, open a stream of the temporary file to write.

And then call the OdDbDatabase::save() method using the pointer to the stream as the first parameter:

{
OdStreamBufPtr pTempFile = odSystemServices()->createFile(pathToTemp, Oda::kFileWrite, Oda::kShareDenyReadWrite, Oda::kOpenAlways);

pDb->save(pTempFile, true);
}

Right after a successful save, make sure the temporary file stream is closed, and then if you need you can replace the original file with the temporary file that contains the actual state of your database:

cmdString = "copy \"" + pathToTemp + "\" \"" + targetPath + "\"";
system(cmdString);

After the temporary file becomes unnecessary, you can delete it.

All posts