|
/* Gamelon(tm) File I/O Library Sample Code C++ Language */ /* (C)19941996 Menai Corporation(tm) Released for public use */
/* Example 12. How to create and use an Index object */ /* 12a. Creating and opening an Index object */
/* An Index object is created by a WritePrimaryIndex() * * function, like any other object, except that it cannot * * be assigned OID keys as part of the creation routine. * * A primary index supports only one target file, which is * * identified as part of the WritePrimaryIndex() function. * * An Index can be opened for use after it has been * * created. Note that the Cursor which opens an Index * * must have focus on that Index object this is not * * always the situation after the Cursor has created the * * Index object, because the file alteration may have been * * an Insert() or Append(), which ordinarily leaves the * * Cursor with focus on an adjacent object. */
/* Beginning file layout: * * { } * * [#1][#2][#3]{#4} */
/* The programmer wishes to include the objects in this * * file in an Index object which will be placed at the * * beginning of the file. Here is the sequence of steps: */
#include <stdlib.h> #include <iostream.h> #include "gfcursor.hpp"
int main(void) { int valid; CURSOR * c1 = new CURSOR("f1.g"); c1>eCursorQueryValid(&valid); if (!valid) exit(1); c1>eCursorMoveIn(); /* At this point, Cursor c1 has focus on the first object, with OID #1. */ c1>eAltInsert(); c1>eObjWritePrimaryIndex("f1.g"); c1>eCursorMovePrior(); /* Now, Cursor c1 gets moved so that it gains focus on the new Index object. The file structure looks like this: { } [Index(f1)][#1][#2][#3]{#4}
Finally, in preparation for use of the Index object, Cursor c1 opens the index: */ c1>eIndexOpen();
/* At this point the Index is identified with the same file in which it exists, and if queried for the target filename Cursor c1 would report that filename. It is time to place some OID keys into the empty Index. */
/* 12b. Directly placing OIDs into an Index by using Include() */
/* Starting with the existing file structure, the * * programmer (who knows the OIDs in advance) now places * * the OIDs into the Index through Cursor c1: */
c1>eIndexInclude(1UL); c1>eIndexInclude(2UL); c1>eIndexInclude(3UL); c1>eIndexInclude(5UL); /* These actions place the OIDs into the index in the following order: 1, 2, 3, 5. But, wait! The programmer made a mistake in typing #4 as #5. No error will appear, because the presence in the supported file of an object bearing a particular OID is not checked until the first attempt is made to access any object through the Index. When that first attempt is made, the invalid OID will be purged automatically from the Index. The programmer can check the success of the inclusions as follows: */ unsigned long oid; if(!c1>eIndexSeekFirst()) do { c1>eIndexQueryCurrent(&oid); cout << oid << endl(); } while (!eIndexSeekNext()) /* This routine will disclose the OIDs in order, and the programmer can see that one was a mistaken entry. Here is an alternative routine, which (if inserted before the "do" loop would purge the bad number before reporting the inclusions this requires the creation of a second Cursor, which attempts a Move() to an object with the arbitrary OID of 1 (which may or may not be present) using the Index and thereby forces validation of the presence of the objects bearing supported OIDs: */ // CURSOR * c2 = new CURSOR("f1.g"); // c2>eCursorQueryValid(&valid); // if (!valid) //exit(1); // c2>eCursorMoveTo(1); // now use loop shown above
/* 12c. Indirectly placing OIDs into an Index by using Attach() */
/* Just for practice, the programmer decides to add a new * * object to the file and to the Index at the same time. * * To do this, Cursor c2 is moved to the PostLast position * * in the file and c1 the Index Cursor is attached * * to it: from this time until c2 is detached from c1 (or * * one of the Cursors is destroyed, or c1 closes the * * Index) any alterations made by c1 which involve an OID * * will cause that OID to be added to the Index (unless it * * is already present). */
CURSOR * c2 = new CURSOR("f1.g"); c2>eCursorQueryValid(&valid); if (!valid) exit(1); c2>eCursorMoveIn(); c2>eCursorMovePostLast(); c1>eIndexAttachTo(c2); /* unsigned long variable oid was declared earlier */ oid = 0; c2>eAltInsert(); c2>eObjApplyIdentity(&oid); /* which is OID 10 */ c2>eObjWrite("Summertime"); /* Result (assuming that the programmer purged the bad OID #5): { } [Index:1,2,3,10][#1][#2][#3]{#4}[#10]
Just to clean up, the programmer now detaches Index Cursor c1 from Cursor c2: */ c1>eIndexDetachFrom(c2);
/* 12d. Indirectly placing OIDs into an Index by using Register() */
/* This example shows how all OIDrelated alterations to * * an object can be recorded in an Index, regardless which * * Cursor makes the alteration. In order to keep the * * sample file small, the objects bearing OIDs #1 and #2 * * are removed from the file in this sequence: this will * * result in their automatic deletion from the Index, as * * noted below. * * Cursor c1 is still open on the Index, and Cursor c2 is * * still in PostLast position. The programmer begins the * * sequence by Registering object #4 to the Index, by * * moving Cursor c2 to that object and then calling * * Register(): */
c2>eCursorMoveTo(4UL); c1>eIndexRegister(c2); /* Now Cursor c2 can do other work. It begins by getting rid of two objects and then moving inside of object #4 to add new objects: */ c2>eCursorMoveTo(1UL); c2>eAltRemove(); c2>eAltRemove(); /* Remember that when an object is removed from a file, the Cursor that takes the action must have focus on that object; and after the removal, the Cursor will try to move to the next object (failing which it will seek a prior object). In this case, object #2 was next to #1, so #2 was automatically in focus; consequently, it was only necessary to call Remove() a second time. Now the programmer can get on to the main purpose of this example: the addition of new objects inside object #4, resulting in the automatic addition of those objects to the Index. We assume that the Gamelon File I/O Library began assigning new OIDs starting with #10. */ c2>eCursorMoveTo(4UL); c2>eCursorMoveIn(); c2>eCursorMovePostLast(); c2>eAltInsert(); c2>eObjApplyIdentity(); /* which is OID 11 */ c2>eObjWrite('x'); c2>eAltInsert(); c2>eObjApplyIdentity(); /* which is OID 12 */ c2>eObjWrite('y'); c2>eAltInsert(); c2>eObjApplyIdentity(); /* which is OID 13 */ c2>eObjWrite('z'); /* Each of these OIDs has reached the Index directly, without the need to force an arbitrary search, because the physical location in the file of the newlyadded object was already known at the time that its OID was added to the Index. Here is the result of the changes: { } [Index:1,2,3,10,11,12,13][#3]{#4 }[#10] [#11][#12][#13]
Note that #2 and #1 are still in the Index, though not in the file. These OIDs will disappear automatically the next time that a search is made for an indexed object that was removed from the file or that was added to the Index by use of Include(OID): the reason is that in both of these circumstances the Index has no physical location for the objects, and none will be found when the next search occurs in this case because the objects have been removed from the file. */
/* 12e. Moving a Cursor to an object using an OID alone */
/* This capability has been illustrated already, in the * * preceding section. Note that Cursor c2 was moved * * successively to the objects bearing OIDs #1 and #2. A * * move such as these, made without assistance of an * * Index, can only be made within the same file. */
/* 12f. Moving a Cursor to an object using an OID and an Index */
/* To avoid the limitation of moving only within the same * * file, and to avoid the slowness sometimes encountered * * in moving an Cursor without the help of an Index, the * * Gamelon File I/O Library includes functions which allow * * a Cursor to designate one or more indexes to be used to * * assist the move. Since a primary index (the only kind * * supported internally by the Library as of this writing) * * supports only one file, it may be necessary to use the * * assistance of more than one Index if the target object * * might be found in any of several files. * * In this example we assume that file f2 contains (among * * other things) an index of objects within file f1. * * Cursors c1 and c2 are already open on file f1. Now, to * * try out this capability, the programmer opens file f2 * * with Cursors c3 and c4, opens the Index with c3 and * * then moves c4 to the last object in file f1. Note that * * this move requires that f1 be open in the same access * * mode as file f2 (and it is both are opened in Shared * * mode by default). Note also that the move will not * * close file f2, because Cursor c3 is still open on it. */
/* An existing file f2 is assumed, with the following * * structure: * * { } * * [Index(f1):10,11,12,13]{} */
/* From this file structure, it might be assumed that the * * Index contains only OIDs of objects generated at this * * local computer and added to file f1, because we have * * shown low numbers being applied as OIDs to objects in * * the above examples. * * As always, the programmer creates the cursors, checks * * their validity and moves it to the desired location: */ CURSOR * c3 = new CURSOR("f2.g"); c3>eCursorQueryValid(&valid); if (!valid) exit(1); c3>eCursorMoveIn(); CURSOR * c4 = new CURSOR("f2.g"); c4>eCursorQueryValid(&valid); if (!valid) exit(1); c4>eCursorMoveIn(); /* Since there are objects within file f2, Cursor c3 gains focus on the first object, which is the Index that supports file f1. The programmer now opens the Index with c3 and moves c4 to the object bearing OID #10. */ c3>eIndexOpen(); c4>eCursorMoveTo(4UL, c3); /* The result is that c4 moves to the last object in file f1, which is the object bearing OID #10. */
/* 12g. Using Indexes and Associate() to help move a Cursor */
/* When there is a need to use multiple indexes, or when * * the same index will be used repeatedly, the Library * * provides a way to Associate one or more indexes with a * * particular cursor. To try out this capability, the * * programmer moves Cursor c4 back to file f2 (which is * * still open with Cursor c3), and then associates Index * * Cursors c1 and c3 (which are in different files!). * * Finally, Cursor c4 moves to the object bearing OID #3, * * which is found in the Index accessed through c1. */ c4>eCursorMoveTo(c3); /* note that the move does not make c4 open the index object */ c4>eCursorAssociate(c3); c4>eCursorAssociate(c1); c4>eCursorMoveTo(3UL, NULL); /* NULL: use Associated indexes */ /* The result is that Cursor c4 moves to the second object in file f1, which is the object bearing OID #3. The Null Cursor was specified as a means of invoking use of the previouslyAssociated Cursors c1 and c3. Our programmer has now finished this lengthy example, so all that remains to do is to clean up, which requires the deletion of Cursors c1, c2, c3 and c4. Note that the deletion of Cursors c1 and c3 will automatically close the Indexes which they held open, and the deletion of the final Cursor open on each file will close that file. */ delete c1; delete c2; delete c3; delete c4; } /* end of main() */ |
||||||||||||||
| |
||||||||||||||
|
Home | Product | Consulting | Programming | Reviews | Company | Site Map | Guest Book |
||||||||||||||
|
Menai Corporation, 1010 El Camino Real, Suite 300, Menlo Park, California 94025-4335 |
||||||||||||||
|
Copyright © 1996-98 Menai Corporation. All Rights Reserved. Menai, Gamelon and gamelon(stylized) are worldwide trademarks of Menai Corporation, registered in the United States of America, and the .[g] logo is a worldwide trademark of Menai Corporation. All other trademarks are owned by their respective owners. |
||||||||||||||