Skip to content

Copying Domino Databases and Documents

Chapter 5-2
Copying Domino Databases and Documents

This chapter describes example programs that access some of the parts of a Domino database. The examples access database header information and notes without reading their internal structure.


COPYDB: Making a Replica Copy of a Database

The sample program COPYDB makes a replica copy of a Domino database. It demonstrates how to create a new database and how to access the various components of a database. The source code for copydb.c is in the directory samples\basic\copydb.

COPYDB first creates a new database, then copies all the parts of the source database -- including the replication settings, the access control list, and all the notes -- to the new database. By copying these parts, COPYDB creates a new database that is a replica copy of the original. Once it has created the database, COPYDB sets the title of the new database to the user-specified value.


Creating a New Database

COPYDB either prompts for the filename of the database to be copied, the filename for the resulting database copy, and the title of the resulting database, or gets this information from the command line arguments. After processing this information, COPYDB calls NSFDbCreate to create a new database.

The newly created database is completely empty. It has no title, no access control list (everyone is a manager), no icon, no forms, no views, and no documents. Also, the database is closed. To copy various parts of the source database to the new database, COPYDB calls NSFDbOpen to open the new database.

copydb.c: Creating and Opening the Copied Database

 if (error = NSFDbCreate (output_path, DBCLASS_NOTEFILE, FALSE))
  {
  NSFDbClose (input_handle);
  API_RETURN (ERR(error));
  }


  if (error = NSFDbOpen (output_path, &output_handle))
  {
  NSFDbClose (input_handle);
  API_RETURN (ERR(error));
  }


NSFDbCreate takes three parameters: a path name, a database class, and an overwrite flag.

COPYDB uses the path name specified as the path name parameter to NSFDbCreate. To create a copy database that resides on your local machine, specify a path name argument of the form:

    [directory\]filename[.ext]


Omit the directory if it is the Domino or Notes data directory and the file extension if it is .nsf. To create a database that resides on a remote server, use the C API function OSPathNetConstruct to create a path name that includes the network path to the database.

COPYDB uses the symbolic value DBCLASS_NOTEFILE as the database class. DBCLASS_NOTEFILE specifies that the new database is an ordinary Domino database.

The overwrite flag tells NSFDbCreate whether to overwrite an existing Domino database with the same file name, if one exists. COPYDB specifies FALSE to prevent NSFDbCreate from overwriting an existing Domino database.



Copying the Replication Settings

After creating the destination database, COPYDB copies three parts of the source database to the destination database: the replication settings, the access control list, and all the notes.

The replication settings for a database reside in a data structure of type DBREPLICAINFO. The replication settings include the database replica ID. Giving the new database the same replica ID as the source database means that the new database can replicate with the source.

Note that COPYDB copies the replication settings before copying the notes. It does this because the replica ID of the database affects the IDs of notes copied into the database. By copying the replication settings first, the notes copied later become replica copies of the notes in the source database.

COPYDB first calls the function NSFDbReplicaInfoGet to get the replication settings from the source database. Then it calls NSFDbReplicaInfoSet to set the replication settings in the new database.

copydb.c: Copying the Replication Settings

  DBHANDLE       input_handle;   / handle of input database  /
 DBHANDLE       output_handle;  / handle of output database /
 DBREPLICAINFO  replica_info;   / db replication info    /
 STATUS         error;      
/ return status from API calls /

  if (error = NSFDbReplicaInfoGet (input_handle, &replica_info))
  {
  NSFDbClose (input_handle);
  NSFDbClose (output_handle);
  API_RETURN (ERR(error));
  }


  if (error = NSFDbReplicaInfoSet (output_handle, &replica_info))
  {
  NSFDbClose (input_handle);
  NSFDbClose (output_handle);
  API_RETURN (ERR(error));
  }


Your program can initialize the DBREPLICAINFO structure directly instead of calling NSFDbReplicaInfoGet. Do this if you do not want the new database to be able to replicate with the source database, or if you need to set or clear other Replication Settings options. If the replica ID you set in the destination does not match the ID of the source, the destination database is not a replica of the source database.

Note that the replication history is separate from the replication settings.


Copying the Access Control List (ACL)

After creating the destination database, setting the title, and copying the replication settings, COPYDB copies the Access Control List from the source database to the destination database.

COPYDB uses the C API function NSFDbCopyACL, which copies a complete user access control list from one database to another, to copy an ACL that was already defined in the source database to the new database.

copydb.c: Copying the Access Control List

  DBHANDLE  input_handle;   / handle of input database  /
 DBHANDLE  output_handle;  / handle of output database /
 STATUS    error;          / return status from API calls /


  if (error = NSFDbCopyACL (input_handle, output_handle))
  {
  NSFDbClose (input_handle);
  NSFDbClose (output_handle);
  API_RETURN (ERR(error));
  }



In the C API Reference, there is a note class called NOTE_CLASS_ACL. This type of note contains information about the database access control list. However, the note is not the access control list itself. The access control list is stored in the database header.


Copying the Notes

After copying the replication settings and the access control list, COPYDB copies all the notes from the source database to the destination.

COPYDB does not use the function NSFDbCopy to copy all the notes, since such copies are not guaranteed to be replicas of the original notes. Instead, the program uses NSFDbGetModifiedNoteTable to obtain an ID Table of all notes in the database. The program then calls IDScan to obtain each NOTEID and NSFDbCopyNote to copy each note -- including all forms, views, filters, and documents -- from one database to the other.

NSDbGetModifiedNoteTable retrieves only those notes that were created or modified since the specified cutoff time. This parameter is a TIMEDATE structure, a Domino- and Notes-specific binary representation of a time and date. The definition of the TIMEDATE structure is shown below. To read and write TIMEDATE structures, use the API functions that are designed to do so.

typedef struct {     / a single time/date /
 DWORD Innards[2];  / Innards[0] - Ticks within day (in 10 msec units) /
/ Innards[1] - Days since "origin" /
} TIMEDATE;


COPYDB specifies a cutoff time/date of TIMEDATE_WILDCARD (ANYDAY\ALLDAY). This special constant specifies that no cutoff date should be used, so NSFDbGetModifiedNoteTable retrieves all notes, regardless of their creation or modification date.

NSFDbGetModifiedNoteTable restricts the set of notes it copies according to a note class mask. The HCL C API for Domino and Notes defines a number of note classes, including documents, forms, and views. The Reference defines the special constant NOTE_CLASS_ALL as the note class mask that includes all classes of notes. COPYDB specifies NOTE_CLASS_ALL so that all notes are copied.

copydb.c: Copying the Notes

  DBHANDLE  input_handle;   / handle of input database  /
 DBHANDLE  output_handle;  / handle of output database /

  DBID      input_dbid;     / dbid of input database /
 DBID      output_dbid;    / dbid of output database /

  TIMEDATE  last_time;      / returned from
                              NSFDbGetModifiedNoteTable
/
 HANDLE    idtable_p;      / handle to id table /
 DWORD     num_scanned, num_entries;
 NOTEID    note_id;
 TIMEDATE  start_time;     / time/date of notes to copy /
 STATUS    error;          / return status from API calls /

 
TimeConstant (TIMEDATE_WILDCARD, &start_time);

   NSFDbIDGet (input_handle, &input_dbid);
  NSFDbIDGet (output_handle, &output_dbid);


/ Get the NoteID table for all notes in the input database /
  if (error = NSFDbGetModifiedNoteTable (input_handle,
                                         NOTE_CLASS_ALL,
                                         start_time, &last_time,
                                         &idtable_p) )
     if (error == ERR_NO_MODIFIED_NOTES)
        printf ("There are no documents in the Database.\n");
     else
        {
        IDDestroyTable (idtable_p);
        NSFDbClose (input_handle);
        NSFDbClose (output_handle);
        API_RETURN (ERR(error));
        }
  num_scanned = 0L;
  num_entries = IDEntries (idtable_p);
  if (num_entries)
     while (IDScan (idtable_p, (FLAG)(num_scanned++ == 0), &note_id) )

         if (error = NSFDbCopyNote (input_handle, NULL,
                                   &replica_info.ID, note_id,
                                   output_handle, &output_dbid,
                                   &replica_info.ID, NULL,
                                   NULL) )
           {
           IDDestroyTable (idtable_p);
           NSFDbClose (input_handle);
           NSFDbClose (output_handle);
           API_RETURN (ERR(error));
           }
  IDDestroyTable (idtable_p);



   printf("\nDatabase copied");
  fflush(stdout);



After this sequence of C API functions, the new database is complete. It has the same replication settings, ACL, icon, policy and help documents, views, forms, filters, and data notes as the input database. The new database has the same title as the original database. You have the option to change the title of the new database.

Changing the Database Title

Starting with Domino and Notes Release 4, you set the title of a new database after completing the notes copying process. COPYDB sample performs the following steps:

  • Call NSFDbInfoGet to get the database information buffer.
  • Call NSFDbInfoModify to change the title of the output database in its information buffer.
  • Call NSFDbInfoSet to set the database information buffer.


COPYDB uses the database title specified by the user as the title of the new database.

copydb.c: Setting the Database Title


/ Clear the array for the database information buffer /
  output_db_info[0] = '\0';


/ Get the database information buffer. /
   if (error = NSFDbInfoGet (output_handle, output_db_info))
     {
     NSFDbClose (output_handle);
     API_RETURN(ERR(error));
     }


/ Change the database title in the database information buffer /
  NSFDbInfoModify (output_db_info, INFOPARSE_TITLE, output_title);


/ Set the database information buffer. /
   if (error = NSFDbInfoSet (output_handle, output_db_info))
     {
     NSFDbClose (output_handle);
     API_RETURN(ERR(error));
     }


The database information buffer stores the information about the database title, categories, and design template options in a character array. COPYDB uses the function NSFDbInfoModify to change the database title in this character array, then passes the array as input to NSFDbInfoSet, giving the output database the new title. COPYDB then closes both the input and the output databases.

Updating Database Information in the Icon Note

Anytime a modification is made to the database with NSFDbInfoModify, you must also update the Icon Note, if one exists, with NSFItemSetText. Pass the database information buffer as the third parameter to NSFItemSetText. This synchronizes the database title, categories, class, and design class information in both places. For example, when you create a new database from a template, after you have updated the title in the database information buffer with NSFDbInfoSet, you also need to update it in the Icon note as follows:

/ Update the icon note's title with that from the NTF. /
NOTEHANDLE hIconNote;

if (!NSFNoteOpen(output_handle, NOTE_ID_SPECIAL+NOTE_CLASS_ICON,
                0, &hIconNote))
{

    / Update the FIELD_TITLE ("$TITLE") field if present /
   if (NSFItemIsPresent (hIconNote, FIELD_TITLE, (WORD) strlen (FIELD_TITLE)) )
   {
       NSFItemSetText(hIconNote, FIELD_TITLE, output_db_info, MAXWORD);
       NSFNoteUpdate(hIconNote, 0);
   }

    NSFNoteClose(hIconNote);
}



CPNOTES: Copying a Subset of a Database

Copying Selective Notes in a Database

The sample program CPNOTES shows how to copy notes selectively, using the note classes and modification times.

cpnotes.c: Copy of Notes Using Date Criteria

   TIMEDATE   start_time;  / cutoff time in Domino binary form /
  STATUS     error;       / return status from API calls /


   / Get the current time and date. /
  OSCurrentTIMEDATE (&start_time);


   / Subtract one month from the current time/date. /
  if (TimeDateAdjust(&start_time, 0, 0, 0, 0, -1, 0))
     {
     NSFDbClose (input_handle);
     NSFDbClose (output_handle);
     printf ("\nProblem adjusting time/date.\n");
     API_RETURN (NOERROR);
     }


   / Copy only the documents (data notes) modified in the last month./
  error = NSFDbCopy (input_handle,
           output_handle,
           start_time,
           NOTE_CLASS_DOCUMENT);


In the code above, the C API function TimeDateAdjust modifies a TIMEDATE structure to subtract one month from the current date, so the call to NSFDbCopy copies only data notes modified in the last month.


Using Dates Another Way

Now we'll show another way to modify a character time/date string and use it to copy the help document.

cpnotes.c: Using Dates

   char      timetext[MAXALPHATIMEDATE+1]; / character time/date /
  char      text_pointer;                / pointer to timetext /


   /
Set a character time/date string to the start of 1996. /
  strcpy (timetext, "1/1/96 12:01 AM");

   text_pointer = timetext;

   /
Put the time/date text into Domino binary form. /
  if (error = ConvertTextToTIMEDATE(NULL,
                NULL,
                &text_pointer,
                strlen(timetext),
                &start_time))
     {
     NSFDbClose (input_handle);
     NSFDbClose (output_handle);
     API_RETURN (ERR(error));
     }


   /
Copy the help document if modified since 1/1/96. */
  error = NSFDbCopy (input_handle,
           output_handle,
           start_time,
           NOTE_CLASS_HELP);


This code calls ConvertTextToTIMEDATE to convert a character time/date string into Domino and Notes binary format. The first argument to this function is the optional address of a structure of internationalization settings. This structure affects the interpretation of the character time/date string. Since it is omitted, ConvertTextToTIMEDATE uses the current internationalization settings in effect at the time of the call. The second argument is the optional address of a structure that specifies the syntax of the time/date string. Since it is omitted, ConvertTextToTIMEDATE uses the default syntax.

Note that the third argument is the address of a pointer to the time/date string, not the address of the string.

The call to NSFDbCopy above copies the help document only if it was modified after the beginning of 1996.