home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 14 Text / 14-Text.zip / techov.zip / TECHOVER.TXT
Text File  |  1993-12-26  |  35KB  |  822 lines

  1.  
  2. Hello,
  3.  
  4. Thank you for your interest in POET.  For more information on POET please contact:
  5.  
  6.     POET Software Corporation
  7.     4633 Old Ironsides Drive, Suite #110
  8.     Santa Clara CA 95054
  9.     Sales (408) 970-4640
  10.     Fax (408) 970-4630
  11.  
  12. Best Regards,
  13.  
  14. Brad Sturtevant
  15. POET Software Technical Support
  16. Compuserve: 70402.74
  17. Internet: 70402.74@compuserve.com
  18.  
  19.  
  20.  
  21. POET TECHNICAL OVERVIEW                              April 20, 1993
  22.  
  23.  
  24. POET (Persistent Objects and Extended database Technology) is an 
  25. innovative object-oriented database development system for C++ 
  26. applications.  POET has received a variety of awards, including Computer 
  27. Language's Jolt award for product excellence, Computer Language's 
  28. productivity award, and BYTE Magazine's award of distinction.
  29.  
  30. POET is truly object oriented. It supports fully all aspects of C++ objects, 
  31. including encapsulation, inheritance, polymorphism, object identity, and 
  32. references among objects.  POET also gives you full database functionality, 
  33. including queries, device independent formats, and sharing of objects 
  34. among programs in a multi-user environment.  Database operations 
  35. manage your C++ objects directly without programmer intervention.  
  36. Instead of making you understand our database formats, we have taught 
  37. our database to understand your objects.
  38.  
  39. POET is available on MS-DOS, MS-Windows, MS-NT, Macintosh, OS/2, 
  40. NeXT, SCO, Interactive, Sun, and various other flavors of UNIX.  Both 
  41. single-user and client/server versions are available.  Heterogeneous 
  42. networks are also supported--no matter what computer your application 
  43. runs on, it can use any server on the network.  Because POET uses the 
  44. same database format for all systems, objects stored by one computer can 
  45. be used on any other computer.  
  46.  
  47.  
  48. OBJECTS NEED POET...  
  49.  
  50.  
  51. Applications continue to become more complex, and often require 
  52. immense effort to develop and maintain.  Object oriented techniques let 
  53. the structure of your program closely reflect the structure of the problem 
  54. to be solved.  Related code and data are combined into objects, and C++ 
  55. has rich features for expressing the structural and semantic relationships 
  56. among objects.  Object oriented programs are modular, easy to understand, 
  57. easy to maintain, and easy to extend.  This significantly reduces both 
  58. development and maintenance costs, which explains the rapid growth in 
  59. object-oriented programming.
  60.  
  61. Conventional database systems (relational database, ISAM, b-tree, etc.) 
  62. manage their data in two dimensional tables.  Complex structures must be 
  63. broken up and distributed among these tables, which offer no real support 
  64. for the object oriented programming model.  As a result, many programs 
  65. stop being object oriented whenever they use the database.  The program 
  66. and the database have two different designs, and the program must 
  67. constantly convert back and forth.  This significantly increases both 
  68. program complexity and run time overhead.
  69.  
  70. A conventional database is like a garage which forces you to take your car 
  71. apart and store the pieces in little drawers.  You can do it, but you 
  72. probably don't want to.  POET lets you store even complex C++ objects 
  73. directly, without modification.  Only object oriented databases can store 
  74. complex objects 1:1.
  75.  
  76. POET's database operations preserve all aspects of your C++ objects.  
  77. References among objects are preserved, as is the full polymorphic 
  78. structure of each object.  Only one command is needed to store, read, or 
  79. delete an object, now matter how complex the object is.  For instance, you 
  80. could use one command to store a CAD drawing with many shapes, a document 
  81. with many paragraphs and images, or an invoice with many items. The 
  82. individual shapes, paragraphs, images, or items are objects in their own 
  83. right, and can be processed independently in other parts of your program.
  84.  
  85. Database management with POET requires a fraction of the effort and a 
  86. fraction of the code.  Less code means less work--your programs are easier 
  87. to develop and maintain.
  88.  
  89.  
  90. POET -- A THUMBNAIL SUMMARY
  91.  
  92.  
  93. POET Keywords.  POET extends C++ syntax to allow you to specify 
  94. database attributes directly in your class declarations.
  95.  
  96. POET Precompiler.  The precompiler translates POET's extended C++ 
  97. declaration syntax into ANSI C++ header files which you include in your 
  98. program.  It also adds your class declarations to the class dictionary of 
  99. the database
  100.  
  101. POET Tool Classes.  POET's tool classes provide the C++ interface to the 
  102. database.  In addition, they allow management of sets and query 
  103. specification.
  104.  
  105. POET Run Time System.  The run time system manages the database and 
  106. processes queries.  In multi-user systems it is part of the server; in 
  107. single-user systems it is linked to the application.
  108.  
  109.  
  110. PROGRAMMING WITH POET
  111.  
  112.  
  113. In the next section we would like to illustrate POET programming with an 
  114. example.  We will design an inventory management system for a computer 
  115. supply store and show how it would be implemented with POET.
  116.  
  117.     Scenario : Inventory Management
  118.  
  119. An inventory system must manage a wide variety of data.  Our store sells 
  120. hardware, software, literature, services, and accessories.  We need to 
  121. generate packing lists and invoices which list the items we sell.  Our 
  122. database must keep track of manufacturers, distributors, customers, and 
  123. employees.  The first step in object oriented design is often to list the 
  124. objects in the system and to group related objects.  Delivery notices and 
  125. invoices are both documents.  We will call anything that can be listed on 
  126. an invoice an item.   Manufacturers, customers, and employees all have 
  127. names and addresses.  For our purposes we can call them all persons.
  128.  
  129. Our database will have to manage objects of the following types:
  130.  
  131. Item               Hardware, Software, Literature, Service, Accessory 
  132. Document           Delivery Notice, Invoice
  133. Person             Manufacturer, Distributor, Customer, Employee
  134.  
  135. Representing the individual objects is not enough; we must also represent 
  136. the relationships among objects, and doing this naturally is central to the 
  137. design of the program.  Consider an invoice: An invoice contains the 
  138. address of the customer and a list of items.  Each item refers to its 
  139. manufacturer.  We want to represent these relationships directly in our 
  140. database design.  Direct Integration in C++ 
  141.  
  142.     Direct Integration in C++
  143.  
  144. Because C++ is tightly integrated into the C++ programming language you 
  145. do not need to convert C++ objects for the database.  POET manages your 
  146. C++ objects, and it carefully follows the semantics of C++.  Database 
  147. classes are defined using C++ class declarations with a few simple 
  148. extensions.  POET does not need a separate class definition; your class 
  149. declarations are the only database schema you need.  Your database objects 
  150. are your program objects.  This dramatically simplifies database design.
  151.  
  152. Let's start with the base classes "Person" and "Item".  These classes 
  153. represent the Person and Item sets in the previous diagram.  They will need 
  154. data and functions for input and output.  The declarations below are 
  155. normal C++ class declarations except for one keyword: persistent.  Any 
  156. class declared with the persistent keyword can be stored in the database.
  157.  
  158. persistent class Person
  159. {
  160. private:
  161.     PtString Name;
  162.     PtString Firstname;
  163.     PtString Street;
  164.     ...
  165. public:
  166.     virtual int Input (..);
  167.     virtual int Print (..);
  168. };
  169.  
  170. persistent class Item
  171. {
  172. private:
  173.     int ItemNumber;
  174.     PtString Description;
  175.     ...
  176. public:
  177.     virtual int Input (..);
  178.     virtual int Print (..);
  179. };
  180.  
  181. Now POET has declarations for the set of all Items or the set of all Persons. 
  182. As shown in the diagram, each of these sets has subsets.  A Software is an 
  183. Item, but not all Items are Software.  All items have the data and the 
  184. methods needed to list them on an invoice.  A Manufacturer is a Person, 
  185. but not all Persons are Manufacturers.  All persons have addresses.  How 
  186. do we represent these subsets?
  187.  
  188. C++ represents subsets by using inheritance.  POET ensures that this 
  189. inheritance always works properly for objects stored in the database.  In 
  190. the following declaration, persistent class Software: public Item means that 
  191. a Software is an Item and has all functions and data that any other Item has.
  192.  
  193. persistent class Software : public Item
  194. {
  195. private:
  196.     PtString Release;
  197. public:    
  198.     ...
  199.     virtual int Input ();
  200.     virtual int Print();
  201. };
  202.  
  203. persistent class Hardware : public Item
  204. {
  205. private:
  206.     ...
  207. public:
  208.     virtual int Input();
  209.     virtual int Print();
  210. };
  211.  
  212. persistent class Manufacturer : public Person
  213. {
  214.     ...
  215.     cset<Item*> Products;    
  216.     virtual int Input();
  217.     virtual int Print();
  218. };
  219.  
  220. The "Manufacturer" class contains the statement cset<Item*> Products;.  
  221. This is a container which can hold a set of references to Items.  These 
  222. Items can be "Hardware", "Software", or any other kind of item -- even if 
  223. it is a new kind of Item developed after this declaration was written!
  224.  
  225. The above example shows how POET derives the structure of your objects 
  226. and the relationships among them by reading your C++ class declarations.  
  227. You simply add  POET's keywords.  Now let's see how the resulting 
  228. database definition is integrated into your program.
  229.  
  230.     The POET Precompiler
  231.  
  232. Unfortunately, no C++ compiler in the world understands our language 
  233. extensions.  Therefore, we have written a precompiler which produces code 
  234. that can be compiled with any ANSI 2.0 C++ compiler.
  235.  
  236. Persistent class declarations are usually placed in files with the .hcd 
  237. extension.  Our precompiler produces a header file with the .hxx extension.  
  238. You include this file in your source files.
  239.  
  240. Of course, the POET precompiler does a lot more than this behind the 
  241. curtains.  It manages the class dictionary of the database to ensure that 
  242. all of your class declarations are registered an up to date.  It also 
  243. produces code to tell the POET run time system how to manage your objects.
  244.  
  245.     Less Code, Less Work
  246.  
  247. Since POET can manage both your objects and their relationships without 
  248. programmer intervention, your programs are smaller and simpler.  POET 
  249. applications are easy to write.  A single line in a POET program is often 
  250. equivalent to many lines of code in traditional database systems.
  251.  
  252. Suppose our program has just changed the name and business form of a 
  253. manufacturer and added a few items to their product line.  Now we need to 
  254. save these changes.  In conventional systems 
  255. these objects are stored in a series of two-dimensional tables (Persons, 
  256. Manufacturers, Item, Software) and your program must know how to 
  257. change your objects into the rows of these tables.  In POET you need only 
  258. one line: pManufacturer->Store();  POET's precompiler always generates a 
  259. Store() member function for any persistent class, so you don't have to 
  260. bother with the details.  The object is completely stored, and the 
  261. references to the items in the product line are automatically updated.
  262.  
  263. Your application code is much shorter and easier to understand.  Less code 
  264. also means fewer programming bugs.  Moreover, since the class dictionary 
  265. resides in the server, you simply send exchange complete objects with the 
  266. server instead of all the rows of individual tables needed for a 
  267. conventional system.  This reduces the communications overhead for 
  268. client/server applications.
  269.  
  270. Of course, you need an open database before you can store an object.  The 
  271. following code is all you need to connect to a server, open the database, 
  272. and store an object:
  273.  
  274. main()
  275. {
  276.      // A PtBase manages the connection to the database.
  277.      PtBase base;
  278.      base.Connect ("Local");
  279.      base.Open ("test");
  280.      // Create a manufacturer and read its data
  281.      Manufacturer * pManufacturer = new Manufacturer (base);
  282.      pManufacturer->Input();
  283.      pManufacturer->Store();
  284.      base.Close();
  285.      base.DisConnect();
  286. }
  287.  
  288. That's all the code you need!
  289. pManufacturer->Store() is the member function that the POET precompiler 
  290. automatically creates to store a persistent object.  You need some way to 
  291. input the data; in this example we assume you have written a member 
  292. function to do this, and pManufacturer->Input() calls this function.
  293.  
  294. PtBase is a POET class that manages the connection to the database.  
  295. base.Connect() and base.DisConnect() are used to establish and break the 
  296. connection to the server.  In the single- user version you use the server 
  297. name "Local".  base.Open() and base.Close() open and close the database.
  298.  
  299.     POET's Object Management Model
  300.  
  301. You have already seen that any C++ class declaration can be made 
  302. persistent simply by adding one keyword to its class declaration.  The 
  303. precompiler translates your persistent class declarations into ANSI 2.0 
  304. C++ code.  Once the database is open, storing a persistent object requires 
  305. one line of code.  However, database programming is not a matter of 
  306. storing individual objects.
  307.  
  308. A database system must provide a clear and consistent programming model 
  309. for expressing and managing the relationships among objects.  This is 
  310. where POET really shines.  When you program in POET you program in 
  311. C++.  POET carefully follows the semantics of C++ to provide powerful 
  312. database functionality using the programming model that every C++ 
  313. programmer already knows.  C++ inheritance, polymorphism, and pointer 
  314. references provide POET with an elegant model for database 
  315. programming.  All the classes you need to manage the database are 
  316. provided, and are used like any other C++ class library.
  317.  
  318. AllSets: Every Object for a Given Class
  319.  
  320. Whenever the POET precompiler encounters a persistent class declaration 
  321. it creates a set to hold all objects of this type.  This set is called an 
  322. AllSet, and the name of the AllSet depends on the name of the class.  In 
  323. our example we have defined the classes "Person", "Manufacturer", "Item", 
  324. "Hardware", and "Software".  The POET precompiler would generate the 
  325. AllSets "PersonAllSet", "ManufacturerAllSet", 
  326. 'ItemAllSet", "HardwareAllSet", and "SoftwareAllSet" to hold objects for 
  327. these classes.  When you store the object it is added to the appropriate 
  328. classes. Since C++ objects can belong to several classes, a POET object 
  329. may belong to several AllSets.  
  330.  
  331. Of course, an object can belong to more than one set.  In our design every 
  332. "Manufacturer" is also a "Person".  Whenever a Manufacturer is stored it 
  333. will be added to both the ManufacturerAllSet and the PersonAllSet.
  334.  
  335. POET's AllSets, like all other sets, use the same inheritance as the objects 
  336. they contain.  since a "Manufacturer" is a "Person", a ManufacturerAllSet 
  337. is a PersonAllSet.  If you have a function that browses a PersonAllSet then 
  338. you can also use this function with a ManufacturerAllSet.
  339.  
  340. Reading Objects
  341.  
  342. When POET creates an AllSet it automatically derives it from PtAllSet, 
  343. giving it a variety of methods for managing objects of a given class.  
  344. Suppose you want to read the first Person from the database.  You simply 
  345. call the Get() method of the PersonAllSet, telling it you want the first 
  346. person:  POET reads the first Person object from the database and builds 
  347. this object in your program's memory.  In the code below pPerson points to 
  348. this first object:
  349.  
  350. PersonAllSet * AllPersons = new PersonAllSet( base );
  351. Person * pPerson = 0;
  352. ...
  353. AllPersons->Get( pPerson );     // read object from database
  354. ...
  355. pPerson->Print();
  356.  
  357. When you read an object from the database it behaves just like the object 
  358. that was stored.  Its member functions, data, and references are identical 
  359. to the original object.
  360.  
  361.     Objects and Polymorphism
  362.  
  363. If you ask two musicians to play a song, one may start squeezing an 
  364. accordion while the other strums a guitar.  They are both musicians,  but 
  365. they are different kinds of musicians and they respond to the same request 
  366. in different ways.  If they did not know how to play a song, though, they 
  367. would not be musicians at all.
  368.  
  369. Similarly, in C++ objects derived from the same base class may call 
  370. completely different functions in response to the same member function 
  371. call.  This is known as polymorphism, and any C++ function can be used 
  372. polymorphically if it is declared virtual and occurs in both a base class 
  373. and derived classes.
  374.  
  375. In practice, polymorphism can often simplify code.  For instance, in our 
  376. example we need to be able to compute tax for each item on an invoice.  
  377. However, taxes are computed differently for different kinds of items.  In 
  378. the States there is no sales tax for services, but sales tax is charged for 
  379. hardware or software.  The easiest way to deal with this is to ask each kind 
  380. of item to compute its own tax.  If we want to compute the total tax for an 
  381. invoice we could do it like this:
  382.  
  383. double TotalTax = 0.0;
  384. Item * pItem;
  385. long i;
  386.  
  387. for (i=0; Items.Get(pItem, i, PtSTART) == 0; i++)
  388. {    
  389.     TotalTax += pItem->ComputeTax();
  390.     Items->Unget(pItem);   // removes the item from memory
  391. }
  392.  
  393. Because C++ supports polymorphism, each kind of Item can have its own 
  394. virtual ComputeTax() function, and we do not need to know the derived 
  395. type to call this function.  If the object is of type Hardware then 
  396. hardware::ComputeTax() will be called, if it is of type Service then 
  397. Service::ComputeTax() will be called.  In fact, if a new tax category is 
  398. introduced in the future then we can create a new kind of Item with a new 
  399. ComputeTax() function--the above code will call it correctly without 
  400. change and without recompiling!
  401.  
  402. Note that you can write your C++ objects to the database and retrieve them 
  403. without affecting polymorphism.  When you read an object it has precisely 
  404. the same member functions that it had when it was stored.
  405.  
  406.     Navigation
  407.  
  408. The objects in your program can refer to each other, and so can the objects 
  409. in your database.  For instance, an invoice has a list of Items, and each 
  410. item has a Manufacturer.  Following the references among objects is called 
  411. navigation.
  412.  
  413. Suppose we want to print a description of the Customer for the second 
  414. Invoice in the database or print a description for the manufacturer of the 
  415. third item on this invoice.  In a normal C++ program you would do this by 
  416. following pointers in memory.  You may be surprised to know that you can 
  417. also do this with 
  418. objects that you read from the database!
  419.  
  420. When POET stores an object which has pointers it automatically converts 
  421. these into database references. If you read this object from the database 
  422. then POET loads the referenced objects and sets your pointers 
  423. appropriately.  Sets of references are also resolved automatically.  To 
  424. follow the relationships in your database, you simply follow the pointers 
  425. in your C++ programs.  This makes it quite easy to make hypertext-style 
  426. programs which follow the references in a database.
  427.  
  428. For our example, let's assume that an invoice has a pointer to the customer 
  429. and a set of pointers to Items.  An Item has a pointer to its manufacturer:
  430.  
  431. persistent class Invoice
  432. {
  433.     ...
  434.     Customer *pCustomer;
  435.     cset <Item*> Items;
  436.     ...
  437. };
  438.  
  439. persistent class Item
  440. {
  441.     ...
  442.     Manufacturer *pManufacturer;
  443. };
  444.  
  445. The pointers and sets of pointers in the above declarations will be resolved 
  446. automatically by POET whenever objects of these classes are read from the 
  447. database.  This makes navigation quite simple:
  448.  
  449. ...
  450. InvoicesAllSet *Invoices = new InvoicesAllSet(base);
  451. Invoice *pInvoice;
  452.  
  453. if (Invoices.Get(pInvoice, 1, PtSTART) == 0)   // get the second invoice
  454. {
  455.     pInvoice->pCustomer->Print();   // print the customer
  456.     Item *pItem;
  457.     if (Items.Get(pItem, 2, PtSTART) == 0)   // get  the third item
  458.         pItem->pManufacturer->Print();   // print the manufacturer
  459. }
  460.  
  461. What if the referenced object is deleted?  POET has referential integrity: 
  462. it knows that the referenced object is gone, so it initializes the pointer 
  463. to zero and returns a warning.   What if you have large objects or large 
  464. sets of references that you do not want loaded into memory?  POET also 
  465. supports other kinds of references that do not load the object until the 
  466. programmer asks for it.
  467.  
  468.     Queries
  469.  
  470. Queries allow you to find all objects that contain specific values. Suppose 
  471. you want to list all customers whose names start with "A*".  Query objects 
  472. are used to specify queries.  The POET precompiler generates a query 
  473. specification class for every persistent class it encounters.  The query 
  474. specification class generated for Customer is called CustomerQuery.  If you 
  475. want to state that the Name field should start with A, you can do this using 
  476. the SetName function.  You can also tell the query how to sort the result 
  477. set; for instance, we can also sort by Name.  CustomerAllSet has a member 
  478. function called Query which takes your query specification and builds a set 
  479. of matching objects.  The code might look like the following:
  480.  
  481. CustomerAllSet * AllCustomers = new CustomerAllSet (base);
  482. CustomerSubSet * Result = new CustomerResultSet;
  483. CustomerQuery Query;
  484. Customer * pCustomer = 0;
  485.  
  486. // Specify Query: All customers beginning with "A*" in ascending order.
  487. Query.SetName("A*", PtMATCHES);
  488. Query.SortByName(PtACSENDING);
  489.  
  490. AllCustomers-> Query(Query, Result);
  491.  
  492. Result->Get(pCustomer);
  493.  
  494. The results of the query are placed in a set.  You can read this set using 
  495. Get(), just as you would with an AllSet.  In fact, all sets are derived from 
  496. the same base class, PtObjectSet, so you can write one browser that can be 
  497. used for result sets, AllSets, or any other sets in your program.
  498.  
  499.     Intelligent Client / Server Architecture
  500.  
  501. POET is available in both single-user and multi-user versions.  The multi-
  502. user version of POET uses a client/server architecture.  Application 
  503. programs can run on any computer on the network.  Access to the database 
  504. is done by making requests to one central process, the database server. The 
  505. server manages multi-user access and ensures that the database is kept 
  506. consistent.  Because the server runs on the computer where the database is 
  507. stored it can access objects quickly, without network overhead.  This 
  508. computer is typically much more powerful than the computers that the 
  509. client applications run on, which also improves system performance.  
  510. Furthermore, since only the results of queries are sent to the clients 
  511. network overhead is reduced significantly.
  512.  
  513. Multi-user databases need to provide features to ensure that updates made 
  514. by different processes do not make the database inconsistent.  POET 
  515. provides traditional features like locking and transactions.  It also it 
  516. offers more innovative features--a program can ask the server to notify it 
  517. when one of its objects is modified by another process, or to notify it 
  518. when certain events occur during processing.
  519.  
  520.     Locking
  521.  
  522. A program can lock an object to ensure that no other process performs 
  523. certain actions on that object.  Different kinds of locks prohibit different 
  524. kinds of actions, such as reading, writing, deleting, or setting locks on 
  525. the object.  A program can also lock a set, which means that a lock is set 
  526. on all objects in the set.  A lock can also be set implicitly when an object 
  527. is read from a set.
  528.  
  529.     Transactions
  530.  
  531. Transactions are used to ensure that a series of operations either succeed 
  532. completely or fail completely without making any changes to the database.
  533.  
  534. Every PtBase has a transaction manager which is accessed using the 
  535. member function Transaction().  When you start a series of logically 
  536. related operations you call the Begin() function of the transaction manager.  
  537. Now you can perform any series of database operations.  As far as your 
  538. program is concerned the database acts as though all of these changes have 
  539. actually been made, but in reality nothing has been written to the database.  
  540. If operations succeed you can call the Commit() function to write all 
  541. changes to the database.  If not, you simply call the Abort() function; the 
  542. database now looks just like it did when 
  543. you called Begin().
  544.  
  545. PtBase base;
  546. Manufacturer * pMan = new Manufacturer (base);
  547. Customer * pCust = new Customer (base)
  548.  
  549. pMan->Input();
  550. pCust->Input();
  551.  
  552. //  We want to store both objects.  If one of the objects is locked then
  553. //  store might fail. If it fails for one object, should fail for both.
  554. base->Transact()->Begin();
  555. if ((pMan->Store()  != 0) || (pCust->Store() != 0))
  556.      base->Transact()->Abort();
  557. else
  558.      base->Transact()->Commit();
  559.  
  560. Does your program have many levels of nested logic?  No problem.  
  561. Transactions can also be nested.  Each Abort() or Commit() applies to the 
  562. current transaction level.
  563.  
  564. Incidentally, POET also has a second kind of transaction that is invisible 
  565. to the user.  Any operation which changes a database is performed using our 
  566. file-level transaction manager.  This ensures that changes either succeed 
  567. completely or fail completely, and protects the integrity of your database.
  568.  
  569.     Watch & Notify
  570.  
  571. Sometimes it is perfectly acceptable for other processes to modify the 
  572. objects you are using, but you want to ensure that your process always has 
  573. the most recent version.  POET allows you to set a watch on object or set 
  574. of objects; this means that the database will inform you whenever they are 
  575. accessed or modified by another process.  You can also ask POET to 
  576. update the object in your memory if it is modified by another program.  
  577. POET does this automatically without further program intervention.
  578.  
  579. Suppose our inventory program is running on many different computers, 
  580. and changes are being made to the database.  If an item is discontinued 
  581. then we may no longer sell it.  We want to ensure that all programs using 
  582. the database are informed instantly.  The traditional approach is to force 
  583. all applications to reread items from the database if they may have changed.  
  584. This increases the number of database accesses that are needed, slowing 
  585. down the programs and increasing the network traffic.  Worse, the 
  586. programmer has to ensure that the item is reread at many different points 
  587. in the program.  Any part of the code that uses an object in memory can 
  588. cause errors if it is critical to use the most recent version of the object 
  589. and the programmer forgets to reread it.
  590.  
  591. In POET you can use the Watch() method to set a watch on an object or set 
  592. of objects.  UnsetWatch() removes the watch.  The PtWatchSpec class is 
  593. used to specify the operations that you want to know about, and the 
  594. PtMethodRef class is used to specify the action that POET should take if 
  595. this operation is performed by another program.  The server can notify 
  596. clients when an object is modified in the database.  You can tell POET to 
  597. update the object in your memory or to call a function in your program 
  598. when this occurs.
  599.  
  600. ....
  601. pDistributor->Display();
  602. //  Define the watch specification: if anybody updates the
  603. //  distributor in the database, the POET server should call
  604. //  our application's target function
  605. PtMethodRef Target ( pDistributor, (PtFunc) &Distributor::Display()):
  606. PtWatchSpec WatchSpec(PtWATCH_UPDATE, PtDEEP, Target);
  607. //  Install the watch for the object. 
  608. pDistributor->Watch (&WatchSpec);
  609.  
  610. Let's assume we have two clients using the same database on a network.  
  611. Client 1 executes the code in the previous example.  Client 2 modifies the 
  612. distributor and stores it.  This is what happens:
  613.  
  614. Time   Client 1                        Client 2
  615.  
  616. 1      Installs watch using code 
  617.        from above example
  618. 2                                      modifies and stores
  619.                                        the product line for a 
  620.                                        distributor
  621.  
  622. 3      The POET server notices that 
  623.        the watched object has been 
  624.        modified, updates the distributor 
  625.        in this client's RAM, and calls 
  626.        the target function.
  627.  
  628.  
  629.     Event Handling
  630.  
  631. An application is usually blocked while a database operation is performed.  
  632. If the operation takes a long time then the application may need to gain 
  633. control from time to update the screen, process user input, or allow the 
  634. user to cancel the operation.
  635.  
  636. Event handling allows you to gain control when a database operation 
  637. begins, ends, or when a certain number of objects have been processed.  
  638. You simply give POET the address of a function which it calls when these 
  639. events occur.  POET examines the return value of your function to see if 
  640. it should continue.
  641.  
  642. In our example the application opens a window when the operation begins 
  643. and periodically checks to see if the Cancel button has been pressed.  If 
  644. so, it aborts the database operation.  When the operation is completed the 
  645. window is closed.
  646.  
  647. The event handler can only call functions that are member functions of 
  648. classes derived from PtCallback.  In our example we declare a class called 
  649. ActionWindow.  It has three member functions to handle the window when 
  650. processing begins, during processing, and when the operation is finished.
  651.  
  652.  
  653. class ActionWindow : public PtCallback
  654. {
  655. public:
  656.  
  657.     int OpenWindow()
  658.     {
  659.         WindowSystem->OpenWindow(&MessageWindow);
  660.         ...
  661.         return PtEXCCONTINUE;  // continue database operation
  662.     }
  663.  
  664.     int CancelButton(int percent)
  665.     {
  666.         WindowSystem->Message(&MessageWindow, "%d percent finished",
  667.             percent);
  668.         ...
  669.         if ( ! CANCELBUTTON )
  670.             return PtEXCCONTINUE;    // continue database operation
  671.         else
  672.             return PtEXCABORT;           // abort database operation
  673.     }
  674.  
  675.     int CloseWindow()
  676.     {
  677.         WindowSystem->CloseWindow(&MessageWindow);
  678.         ...
  679.         return PtEXCCONTINUE;
  680.     }
  681.  
  682. } myActionWindow;
  683.  
  684.  
  685. Every PtBase has an exception manager which lets you install callback 
  686. functions.  We will use three exception manager functions:
  687.  
  688. SetActionStarting()--Installs the callback function that will be called 
  689. when a database operation begins.
  690.  
  691. SetActionPending()--Installs the callback function that will be called 
  692. periodically during database processing.
  693.  
  694. SetActionTerminated()--Installs the callback function that will be called 
  695. when a database operation is terminated.
  696.  
  697. Because C++ member functions need to know the address of their objects 
  698. when they are called, you must specify both the object and the member 
  699. function when installing a callback function:
  700.  
  701. ActionWindow myActionWindow;
  702.  
  703. base->GetExcMgr()->SetActionStarting (&myActionWindow, (PtFunc)
  704.     &ActionWindow::OpenWindow);
  705. base->GetExcMgr()->SetActionPending(&myActionWindow, (PtFuncInt)
  706.     &ActionWindow::CancelButton);
  707. base->GetExcMgr()->SetActionTerminated(&myActionWindow, (PtFunc)
  708.     &ActionWindow::CloseWindow);
  709.  
  710. That's all there is to it.  Your functions will be called automatically 
  711. when a database operation starts, during processing, and when the 
  712. operation completes.
  713.  
  714.  
  715. POET: An Overview
  716.  
  717.  
  718.     C++ Language Support
  719.  
  720. o   Tight semantic integration with C++.
  721. o   Any C++ object or structure can be made persistent by adding the 
  722.     persistent keyword.
  723. o   Storing and reading a C++ object does not change its state or behavior.
  724. o   Full support for C++ encapsulation, object identity,  inheritance, and 
  725.     polymorphism.
  726. o   C++ pointers and references are automatically converted to database 
  727.     references when storing objects.
  728. o   Database references are automatically converted to C++ pointers and 
  729.     references when reading objects.
  730. o   All database definition is done through a small extension to C++ 
  731.     declaration syntax.
  732.  
  733.     Database Functionality
  734.  
  735. o   Navigation
  736. o   Queries
  737. o   Sorting
  738. o   Indexes
  739. o   Single-user operation
  740. o   Multi-user operation using client/server architecture
  741. o   Flexible locking for objects and sets
  742. o   Nested transactions
  743. o   Watch & notify for objects and sets
  744. o   Event handling
  745. o   Database size limited only by hard disk size
  746.  
  747.     C++ Language Extensions
  748.  
  749. o   Persistence
  750. o   Indexes
  751. o   Transient data elements in persistent classes
  752. o   Sets
  753. o   Dependent objects
  754.  
  755.     PTXX-Precompiler
  756.  
  757. o   Automatically converts extended C++ class declarations into 
  758.     ANSI 2.0 code
  759. o   Registers classes in the class dictionary
  760. o   Automatically generates POET Tool Classes
  761. o   Provides class versioning
  762.  
  763.     Predefined C++ Classes
  764.  
  765. o   Predefined classes for date, time, strings, and BLOBS 
  766.     (binary large objects) can save you development time
  767.  
  768.     Portability
  769.  
  770. o   All platforms are source-code compatible
  771. o   Any POET database may be read by any computer
  772. o   Full support for heterogeneous networks
  773.  
  774.     Platforms
  775.  
  776. o   Available for MS-DOS / MS-Windows (Borland C++, Microsoft C++, 
  777.     Zortech C++), OS/2 (Borland C++), Novell, Macintosh (MPW), and 
  778.     various Unix systems, including NeXT (NeXTStep), SCO (Liant C++), 
  779.     and Sun OS (Sun C++).
  780.  
  781.  
  782. POET Keywords
  783.  
  784.  
  785. o   persistent--Defines database classes.  Instances of a persistent 
  786.     class can be stored in the POET database.
  787. o   transient--Defines non-persistent members of a persistent class.  
  788.     Transient members are not stored in the database.
  789. o   depend--Defines dependent sub-objects.
  790. o   indexdef, useindex--Defines indices.  If available, indices are 
  791.     automatically used for query optimization.
  792. o   ondemand<type>--Defines special references among objects. Ondemand 
  793.     references are explicitly loaded after object is read.
  794. o   cset<type>, lset<type>, hset<type>--Define object containers that 
  795.     may or may not swap objects to disk
  796.  
  797.  
  798. POET Tool Classes
  799.  
  800.  
  801. o   PtBase--Used for database management.
  802. o   PtObject--Management of persistence and database characteristics.
  803. o   PtAllSet<type>--Provides access to all objects of a given class.
  804. o   PtSet<type>--Sets which can be used for one to many relationships 
  805.     among objects or to hold the results of a query.
  806. o   PtOndemand<type>--An optimization class for references to objects 
  807.     which are to be explicitly loaded.
  808. o   PtQuery<type>--A class to define and hold query specifications.
  809.  
  810.  
  811. POET Data Types
  812.  
  813.  
  814. o   int, long, char, float, double--All of the standard C++ data types 
  815.     are supported.
  816. o   class[n]--Arrays are fully supported.
  817. o   PtString--A variable length string is provided.
  818. o   PtDate--Date type.
  819. o   PtTime--Time type.
  820. o   PtBlob--BLOBs--Binary Large OBjects
  821.  
  822.