About Duffbert...

Duffbert's Random Musings is a blog where I talk about whatever happens to be running through my head at any given moment... I'm Thomas Duff, and you can find out more about me here...

Email Me!

Search This Site!

Custom Search

I'm published!

Co-author of the book IBM Lotus Sametime 8 Essentials: A User's Guide
SametimeBookCoverImage.jpg

Purchase on Amazon

Co-author of the book IBM Sametime 8.5.2 Administration Guide
SametimeAdminBookCoverImage.jpg

Purchase on Amazon

MiscLinks

Visitor Count...



View My Stats

« Interesting twist on the Nigerian 419 scam... | Main| Removing unused field names from your Notes application design... »

What Are the Components of a Note ID?

Category Software Development

Ran across this gem in the Knowledgebase the other day...  good reading if you've ever wondered what makes up a Note ID value...

What Are the Components of a Note ID?

Document Number:  7002668

When we troubleshoot the issues related to mail routing/replication, it is helpful to know how a note ID is formed.


This document describes note IDs in detail and explains how different Notes tasks (replicator and so on) use the components of a note ID and how API programs can use them.


Note:  Much of this information is also contained in the Notes C API 5.0 User Guide and Notes C API 4.6 Reference Manual.


The parts of a note ID are:

  • UNID (Universal Note ID) - Identifies all the copies of a note, regardless of location or time.  In other words, every replica of a note has the same UNID, and the UNID does not change when a note is modified.
  • OID (Originator ID) - Identifies a particular revision of a note, regardless of location.  In other words, every replica of a note has the same OID, but the OID changes when the note is modified.
  • GNID (Global Note ID) - Identifies a particular note in a particular database.  The GNID does not change as the note is modified.  The GNIDs of replica copies of a note will probably be different, since the various copies will occupy different positions in their databases.
  • NID (Note ID) - Identifies a particular note in a given database.  The NID does not contain information about the database being referred to, and it does not change when the note is modified.
  • IID (Instance ID) - Identifies a particular revision of a note in a given database.  The IID does not contain information about the database being referred to.  The IID changes when the note is modified.
  • GIID (Global Instance ID) - Identifies a particular revision of a note in a particular database.  The GIID contains information about the database being referred to.  The GIID changes when the note is modified.

You can examine the ID information for a particular document from the Notes user interface.  Select the document in a view or open it, then select File - Document Properties.  Notes displays the "Document Properties" InfoBox.  On the information page, Notes displays the header data associated with this document, including the dates and times the document was created and modified and the note ID information.  


The note ID information is displayed by Notes as three lines consisting of key characters and hex digits.  For a typical data note, it looks like this:


ID: OF0000039D:3836C29F-ON85255DC9:0056FB94

   SD00255DF4:0057B8FA-SN00000003

   DB85255CD9:00567287-NT0000C092


These three lines contain the Originator ID (OID), the Universal Note ID (UNID), the Global Note ID (GID), and the Note ID (NID) of the open or selected document.



The Universal Note ID (UNID) and the Originator ID (OID)


The first two lines of the ID constitute the complete Originator ID for the note.  In turn, the Originator ID consists of the Universal Note ID (the whole first line) plus the sequence number and the sequence time (the second line)
:


Originator ID (OID) =

ID: OF0000039D:3836C29F-ON85255DC9:0056FB94

   SD00255DF4:0057B8FA-SN00000003

   DB85255CD9:00567287-NT0000C092



Universal Note ID (UNID) =

ID: OF0000039D:3836C29F-ON85255DC9:0056FB94

   SD00255DF4:0057B8FA-SN00000003

   DB85255CD9:00567287-NT0000C092



Sequence Time =

ID: OF0000039D:3836C29F-ON85255DC9:0056FB94

   SD00255DF4:0057B8FA-SN00000003

   DB85255CD9:00567287-NT0000C092



Sequence Number =

ID: OF0000039D:3836C29F-ON85255DC9:0056FB94

   SD00255DF4:0057B8FA-SN00000003

   DB85255CD9:00567287-NT0000C092



The first two parts of the Originator ID (and the Universal Note ID) consist of a File member and a Note member.  The first line of the ID information in the  Document Properties InfoBox consists of the letters "OF" ("Originator ID - File"), followed by sixteen hex digits, followed by a hyphen, followed by the letters "ON" ("Originator ID - Note"), followed by sixteen more hex digits.  The sixteen hex digits after the "OF" and before the hyphen constitute the File member of the OID.  The sixteen hex digits after the hyphen and the "ON" constitute the Note member of the OID.


OID.File =

ID: OF0000039D:3836C29F-ON85255DC9:0056FB94

   SD00255DF4:0057B8FA-SN00000003

   DB85255CD9:00567287-NT0000C092



OID.Note =

ID: OF0000039D:3836C29F-ON85255DC9:0056FB94

   SD00255DF4:0057B8FA-SN00000003

   DB85255CD9:00567287-NT0000C092



The header file, nsfdata.h, contains the following definition of the ORIGINATORID data structure and the UNIVERSALNOTEID data structure:



typedef struct {
    DBID File;        /* Unique (random) number */
                      /* (Even though this field is called "File," */
                      /*  it doesn't have anything to do with the file!) */
    TIMEDATE Note;    /* Original Note Creation time/date */
                      /* (THE ABOVE 2 FIELDS MUST BE FIRST - UNID */
                      /*  COPIED FROM HERE ASSUMED AT OFFSET 0) */
    DWORD Sequence;   /* LOW ORDER: sequence number, 1 for first version */
                      /* HIGH ORDER WORD: flags, as above */
    TIMEDATE SequenceTime;/* time/date when sequence number was bumped */
} ORIGINATORID;


#define OID ORIGINATORID


typedef struct {
    DBID File;        /* Unique (random) number */
                      /* (Even though this field is called "File," */
                      /*  it doesn't have anything to do with the file!) */
    TIMEDATE Note;    /* Original Note Creation time/date */
} UNIVERSALNOTEID;


#define UNID UNIVERSALNOTEID



The Originator ID (OID) for a note identifies all replica copies of the same note.  The OID is composed of two parts: the Universal Note ID (UNID) and the sequence number and sequence time.  The UNID universally identifies all instances of the same note.  Taken together, the sequence number and the sequence time distinguish different revisions of the same note from one another.  


The Universal note ID (UNID) identifies a note across all servers.  However, the UNID lacks the information necessary to directly access the note in a given database.  The UNID is used to reference a specific note from another note.  The "$REF" (FIELD_LINK) field of a response note contains the UNID of its parent.  Similarly, DocLinks(see the NOTELINK structure in nsfdata.h) contains the UNID of the linked-to note plus the ID of the database where the linked-to note can be found.  The important characteristic of the UNID is that it continues to identify a note even after the note is updated.



The UNID, the OID, and the Replicator


The Universal Note ID (the first half of the Originator ID) uniquely identifies all versions and all copies of the same note.  Two notes are replica copies of each other if they share the same UNID.   Therefore, different versions and all replica copies of the same note have the same UNID.  A corollary of this rule is that one database must not contain two notes with the same UNID.  If the replicator finds two notes with the same UNID in the same database, it generates an error message in the log and does not replicate the document.


The full Originator ID, on the other hand, uniquely identifies one particular version of a note.  In other words, all replica copies of the same version of a note have the same OID.  However, a modified version of a replica copy of a particular note will have a different OID, because Notes increments the sequence number when a note is edited and also sets the sequence time to the timedate when the sequence number was incremented.  Therefore, when one replica copy of a note remains unchanged but another copy is edited and modified, the UNIDs of the two notes remain the same but the sequence number and sequence times (and therefore the OIDs) are different.


The Notes replicator uses the UNID to match the notes in one database with their respective replica copies in other databases.  For example, if database A is replicating with database B, and database A contains a note with a particular UNID but database B does not, the replicator creates a copy of that note and add it to database B.  


If database A contains a note with a particular UNID and database B contains a note with the same UNID, the replicator concludes that these two notes are replica copies of one another.  In this case, the replicator goes on to examine the sequence number and sequence time of the two notes.  If the sequence number and sequence time are the same for both notes, then the replicator concludes that the two notes are up to date with one another, and no action is required.  On the other hand, if either the sequence number or the sequence time -- or both -- differ between two notes, the replicator must decide which one is more recent and update the older note with the most recent version.


If one note has been updated but the other note has not, the sequence number of the first note will be greater than that of the second.  The replicator handles this case by overwriting the second note with the first, bringing the two databases into synchronization.


Replication Conflicts


Replication conflicts arise from concurrent edits of the same note.  If a user updates a note in database A and, before the change replicates to database B, another user updates the replica copy of that note in database B, the two notes have the same sequence number but different sequence times.  In this case, the replicator generates a replication conflict because this represents a concurrent edit of the same note.


The replicator handles replication conflicts by generating a replica conflict document.  The document with the later sequence time becomes the conflict winner and the document with the earlier sequence time becomes the conflict loser.  The conflict winner is copied to the database containing the loser, and the conflict loser is turned into a response document to the winner.


The replicator generates the conflict loser (black diamond) document in the database initially holding the document with the earlier sequence time.  The replicator copies the winning document from the winning database into the losing database.  This winning document keeps its OID intact.  Then the replicator turns the losing document into a new document by generating a distinct OID and adding the special item "$Conflict" (VIEW_CONFLICT_ITEM) to the document.  This $Conflict item causes a black diamond to appear in the left-hand margin of any view that displays the conflict loser.  The replicator also turns the losing document into a response document by adding to it a $REF item that contains the UNID of the winning document.


NOTE: The conflict loser (black diamond document) may not always appear on both servers immediately after replication completes. When the server holding the document that will be the winner initiates the replication, the conflict loser does not appear on the winning server immediately after replication, but does appear on the losing server. This happens because the replicator generates the conflict loser (black diamond document) only on the server initially holding the losing document.


Specifically, when server B initiates replication with server A, B first pulls changes from A, and then A pulls changes from B. When B pulls from A, B sees the conflicting document on A, determines that B's version is the winner, and does not bring the conflicting document over from A to B.  The justification for this is that B already has the winner, so B does not need to bring over the loser.  Then A pulls from B, sees the conflicting document on B, and determines that B's version is the winner.  Therefore, A makes its own version into a replica conflict loser (black diamond) document and brings B's version over to A as the replica conflict winner.  This satisfies the requirement that when replication is complete, both copies of the database present the same version of the document as the most up-to-date (winning) version of the document.  However, the conflict loser (black diamond) does not yet appear on B.  The next time B replicates with A the replica conflict loser (black diamond) document will come back to B and both copies of the database will be synchronized.



Global Note ID (GNID) and NOTEID (NID)


The Global Note ID (GNID) is composed of two parts: the Database ID and the Note ID (NID).  Since the GNID identifies both the database and the note in the database, it uniquely identifies a particular copy of a note across all databases.


The GNID appears in the bottom line of the ID information displayed by the Design - Document Properties InfoBox.  The first part of the GNID corresponds to the File member of the  GLOBALNOTEID structure.  The second part corresponds to the NoteID member.



Global Note ID (GNID) =

ID: OF0000039D:3836C29F-ON85255DC9:0056FB94

   SD00255DF4:0057B8FA-SN00000003

   DB85255CD9:00567287-NT0000C092



Database ID (GNID.File) =

ID: OF0000039D:3836C29F-ON85255DC9:0056FB94

   SD00255DF4:0057B8FA-SN00000003

   DB85255CD9:00567287-NT0000C092


Note ID (GNID.NoteID) =

ID: OF0000039D:3836C29F-ON85255DC9:0056FB94

   SD00255DF4:0057B8FA-SN00000003

   DB85255CD9:00567287-NT0000C092



The third line of ID information in the Design - Document Properties InfoBox consists of the letters "DB" (which stands for "Data Base"), followed by sixteen hex digits, followed by a hyphen, followed by the letters "NT" ("NoTe"), followed by eight more hex digits.  The sixteen hex digits after the "DB" and before the hyphen constitute the File member of the GNID.  The eight hex digits after the "NT" constitute the Note ID member of the GNID.



Global Note ID (GNID)


Unlike the OID, the GNID does not distinguish between different versions of the same note.  Since the NoteID field is relative to the file that contains the note, the GNIDs of replica notes will most likely be different.


The Database ID (the File member of the GNID) contains the replica ID of the database.  The API header file, nsfdata.h, defines the DBID data structure as a TIMEDATE:


#define DBID TIMEDATE


The 8-byte DBID contains the TIMEDATE on which the database was originally created.  You can verify that the File member of the GNID, as displayed on the third line of the ID information in the File - Document Properties InfoBox, agrees with the Replica ID, displayed on the information page of the File - Database - Properties InfoBox.  Since all replica copies of a particular database have the same DBID, all notes in all replica copies of a particular database have the same GNID.File.


typedef struct {
      DBID File;                /* Creation Date/Time of NSF where note was created */
      NOTEID NoteID;        /* Note's RRV in this file */
} GLOBALNOTEID;


#define GNID GLOBALNOTEID



Note ID (NID)


The note ID (NID) identifies a note in a database.  The NID is the file position of the Record Relocation Vector (RRV) for the note.  An RRV is a DWORD offset in a file.  Confusion often arises because the note ID is casually referred to as "the Note's RRV in this file."  In fact, the note ID is the offset in the file to the RRV, which in turn points to the record for the note.  An RRV is a  general structure, while a note ID is more specific.  Internal to Notes, various other objects besides notes have an associated RRV.


typedef DWORD RRV;

typedef DWORD NOTEID;


The note ID is guaranteed never to change in one Notes database (.NSF) file, except when the note is deleted.  When the note is deleted, the RRV_DELETED bit is set in the note ID.


#define RRV_DELETED 0x80000000L        /* indicates a deleted note */


Since a note ID is specific to the database file that contains it, replica copies of the same note in other databases will most likely have a different note ID.



INSTANCEID (IID)


The Instance ID identifies an instance of a note in a given database.  Each time a note is modified, Notes stamps the instance ID with the time and date that the update occurred. T he Instance ID consists of the note's modification TIMEDATE and the note ID.


typedef struct {
      TIMEDATE Note;                                /* Note's MODIFICATION date/time */
      NOTEID NoteID;                                /* Note's RRV */
} INSTANCEID;


#define IID INSTANCEID


The modification TIMEDATE (the Note member of the IID) is not the same thing as the Revision Time in the OID.   Database views use the note modification timedate in the IID to determine when to display the unread flags.  You can access the modification timedate by specifying _NOTE_MODIFIED to NSFNoteGetInfo.  The replicator uses the Revision Time in the OID to compare replica copies of notes in different databases.  You access the Revision Time by  specifying _NOTE_OID to NSFNoteGetInfo.


The NoteID member of the IID is the same value found in the NoteID member of the GNID.


NSFNoteUpdate sets the modification timedate every time the note is updated to the .NSF file.  The modification timedate governs the unread flags in views.  For each database icon on the desktop, Notes maintains an ID table of all the unread documents in that database.  This unread ID table contains the timedate when the table was last updated.  If you read a document, VIEW removes the ID from the table and sets the table timedate.  If someone later updates the document, NSFNoteUpdate sets the document modification timedate.  The next time you open the view, Notes will detect that the modification timedate is later than the ID table timedate and will add the ID for the document back into the unread ID table for that database.  This causes VIEW to display an unread marker for that document in the view.


There are several ways for an API program to obtain the IID for a note. Get the note ID from the GNID, a NIFReadEntries buffer, or the ID.NoteID member of a SEARCH_MATCH structure.  Get the modification timedate from the ID.Note member of a SEARCH_MATCH structure or by calling NSFNoteGetInfo and specifying _NOTE_MODIFIED.



GLOBALINSTANCEID (GIID)


The Global Instance ID globally identifies an instance of a note across databases.  It consists of the same members as the Instance ID but adds the database ID as the File member.  The note with the latest modification date is the "most recent" instance.


typedef struct {
      DBID File;                                        /* database Creation time/date */
      TIMEDATE Note;                                /* note Modification time/date */
      NOTEID NoteID;                                /* note ID in database */
} GLOBALINSTANCEID;


#define GIID GLOBALINSTANCEID



API programs can initialize a GIID structure for a note by calling NSFNoteGetInfo twice, first specifying _NOTE_DBID to obtain the File member and then specifying _NOTE_MODIFIED to get the members that correspond to the IID modification timedate.

Comments

Gravatar Image1 - I am looking for information on this error:

Notes error: Database already contains a document with this ID (UNID).

Thanks.

Post A Comment

:-D:-o:-p:-x:-(:-):-\:angry::cool::cry::emb::grin::huh::laugh::lips::rolleyes:;-)

Want to support this blog or just say thanks?

When you shop Amazon, start your shopping experience here.

When you do that, all your purchases during that session earn me an affiliate commission via the Amazon Affiliate program. You don't have to buy the book I linked you to (although I wouldn't complain!). Simply use that as your starting point.

Thanks!

Thomas "Duffbert" Duff

Ads of Relevance...