Yes, I really did need NotesDocumentCollection.GetNth that one time....
Bob Balaban August 18 2008 02:47:42 AM
Greetings, Geeks!I promised you a follow up to my "Spawn of the Devil" post of a couple of days ago, and this is it. I sincerely hope this will be my last-ever discourse on the GetNth topic.
I wanted to be fair, and mention that there was one time, recently, in fact, when GetNth was the right solution to a problem I was having, and I really needed it.
But, to tell you that story, I have to tell you this: Back when the NotesDocumentCollection class was first created (for Notes 4.0, mid-1990's), it was essentially a LotusScript wrapper for a CAPI data structure called an IDTable. The IDTable "object" is a compressed list of NOTEIDs, which is optimized for two things: efficient storage of a potentially large number of IDs, very fast lookup to determine if a given ID is in the list or not, and ver fast traversal (if you have an ID and want to know the next one, NOT if you have to count N entries from the beginning every time....). Ok, that was three things. IDTable allowed such operations as getting a list of all the documents in a database to be very, very fast (expressed in LotusScript as NotesDatabase.AllDocuments, for example).
The thing about db.AllDocuments (and the CAPI that underlies that function) is that normally it returns an IDTable that contains both actual document IDs, AND the NOTEIDs of any deletion stubs which are also in the database. Originally, the code underlying .AllDocuments stripped out the deletion stubs, leaving only actual data documents IDs, so you could be pretty sure that when iterating over a DocumentCollection, that you would always get a valid NotesDocument (assuming someone else didn't go and delete something on a shared copy of the database between the time when you executed AllDocuments and when you accessed everything in the resulting DocumentCollection).
That all changed sometime in between Notes 5 and Notes 7 (I don't know exactly when, I was off doing other things...), and deletion stubs are no longer stripped out. Now when you want to iterate over all the documents in a database using NotesDatabase.AllDocuments, you have to check each NotesDocument instance with either (both is probably a better choice) the NotesDocument.IsDeleted or .IsValid properties before you try to access the document contents. Do I know the difference between the two? No, I do not.
Ok, back to the story. So, there I was, needing to check all documents in a database that happened to have a lot of deleted documents in it. As always, I got a DocumentCollection using Database.AllDocuments, and wrote my NotesDocumentCollection.GetFirst/GetNext loop (I was actually using the COM classes from C#, but they're the same as the LotusScript and Java classes anyway, so that difference is meaningless for the purpsoes of this sad story). Inside the loop I coded a test so that if .IsDeleted was true or .IsValid was false, I could skip the current document and go on to the next one.
HOWEVER (this is the sad part), it turned out that DocumentCollection.GetNextDocument() would fail if the current document was not "valid". (Gasp!) What to do? I thought maybe someone was messing with the database on the server while I was iterating, and that the document had been deleted out from under me. But no! The same thing happened when I ran a test on a local copy of the database. I was stuck, couldn't get the next document, ever.
AHA! But then GetNth came to my rescue. Why? Because, GetNth doesn't NEED the previous document to get the next one, it just counts IDs in the IDTable. Problem solved, worked like a charm. Sure, slower. But how do you measure speed when the "correct" way of doing something runs you into a brick wall? I'll take correct behavior that's a bit slower over a "faster" approach that doesn't work, any day.
(Visit the Binary Tree web site here.)
- Comments [8]
