A View Cache prevents unnecessary database accesses by caching Hierarchical Views and avoids lost update problems by preventing that inconsistent copies of Views are created.
You write a sequence of methods that uses the same ConcreteViews over and over again in a single user transaction.
How do you implement a cache for ConcreteViews?
Performance: Caching ConcreteViews can save you much time. Database access down to the physical disk level costs up to a factor of 100.000 more than an ordinary memory access. Even a well dimensioned database cache will usually not guarantee maximum performance. Databases will normally run in a process separated from user processes. To access the database cache you must access this other process. Process context switches however, are very expensive, even on a host computer. If the database process resides on a remote server, a local cache is even more important.
Correctness: Another aspect is correctness. If you do not control multiple copies of ConcreteViews that may be requested by a coincidental sequence of application kernel methods, you run into lost update problems.
Create one cache of Views per database client process. Base it on a container that maps abstract database keys to pointers to Views.
The ViewCache offers usual cache methods that allow getting a View, registering a View in the cache and flushing the cache. You should separate any concerns of transaction handling from the ViewCache and leave them to the Transaction object. Aspects of how to write a View to the database should be placed in the ConcreteView objects. ConcreteViews are accessed via the abstract View protocol class.
To illustrate the behavior of the ViewCache we will have a deeper look into what happens when executing the following code:
// get the appropriate data
OrderInvoiceView * pInvoice = |
The code is taken from Listing 2 above. Lets presume the OrderInvoiceView identified by the ViewKey anOrder has not yet been loaded. The ViewFactory will first try to ask the ViewCache for the View. As the ViewCache does not hold the required View, the ViewFactory will create a new View and have it loaded with data from the database that match the given ViewKey. The ViewFactory will then register the freshly loaded OrderInvoiceView with the ViewCache and return it.
Correctness: Lost updates are prevented as the same data are never accessed via two copies that do not know each other.
Implementation cost: In object oriented languages, a cache may cheaply be implemented using a hashed container like a map. If the cache must be implemented in other languages like e.g. COBOL there will be considerable implementation costs. COBOL does not have any foundation classes for containers. COBOL also does not posses a pointer concept that allows returning a reference to a cached object. If you decide to use memory copies instead of references you are again faced with a consistency problem.
Performance: The runtime penalty can be neglected compared to the penalty for a single superfluous database access. There is no memory penalty in case references or pointers are used instead of deep copies.
The implementation of the ViewCache may be based on some Map container class.
Class ViewCache { public: static void flush ( void ); static void writeAndFlush ( void ); static void registerView ( ViewKey aKey, View *pView ); static View *getView ( ViewKey aKey ); private: static Cmap<CString,LPCSTR,View *,View *> iCache; }; |
It would be even more elegant to define a cache class template, instantiate that for Views and implement it as a singleton. The header given is sufficient to demonstrate the caches idea.
Some host architectures use a ViewCache called Session Memory. A Session Memory may be streamed to an external data store (like a database blob) to survive the end of a session (process) and to offer transactions that may last for 30 days or more.
A Session Memory may also be used to store more sorts of data than just the database related ConcreteViews. A Session Memory is also often used for dialog data as well as other data that are needed for a process step in a workflow system.
VAA [VAA95] and also LBS2000 use a Session Memory.
Brown and Whitenack describe a Cache Management Pattern [Bro+96] in less detail.
Pointers returned by the getView() method can be made safer using Smart Pointers [Mey96] or the Counted Pointers Idiom [Cop92]
The View Cache concept stems from Object Oriented Access layers. It may be found in various such access layers as the Champs, the EASY or the Hypo [Kel+96a] project at sd&m.
Host based architectures that need to offer long transactions for workflow processing also use the pattern. VAA calls it a Session Memory [VAA95]. The LBS2000 project also uses the pattern.