Archive for the 'FAQ' Category
Q: “Our application kicks off with a menu where icons are clicked to invoke windows which have their own transaction to the database. How does an application connect to a VOSS virtual space and automatically disconnect when the menu is closed?”
A: To clarify terminology: “connecting” to a virtual space means making the image aware of its existence, requiring a pathname; “log-on” to a virtual space means opening the files in that image and registering that image’s log-on in the space’s dictionary of current accesses (using the ImageID set when VOSS is installed in the image) by the system’s private log-on transaction. There’s no need to log-off after every transaction, but the two operations could be combined like this:
| vom customers departments |
[ [ vom := VOManager newForExistingSpace: ‘c:\vospaces\myspace’. “connect”
vom isNil ifTrue: [^self].
vom open ifFalse: [^self]. “log-on”
[ customers := vom rootDictionary at: ‘customers’.
departments := vom rootDictionary at: ‘departments’
] atomicReadOnly.
…
…
…
] ensure:
[ vom notNil ifTrue: [vom close; disconnect]]
] forkAt: (Processor userBackgroundPriority).
Q: “I created 10,000 objects in one transaction and then updated all of them in another transaction. How big can I make the cache?”
A: For performance reasons it’s important to set the maximum cache size big enough to accommodate the number of objects in your largest transaction. The reason for this is that whilst the cache will always expand, even beyond its set maximum size, to hold all the objects in all the currently open transactions, whilst it is larger than the max size it is significantly slower. This is because each time an object is added to the cache, when at its max size, it searches for the least recently used unlocked object (not included in any transaction) and removes it; this is a linear search from the tail end of the cache and is thus long and fruitless when there are no unlocked objects left in it.
The cache can be set to any size compatible with available physical memory; the memory occupied is displayed in the Control Panel when ByteSizeCalculation is enabled, though in normal use this should be disabled because the calculation takes time.
If the first transaction after log-on virtualizes 10000 objects there will be a lot of disk activity; this is because the pre-allocation cache (pac) is initialized to 25 new objects and when these have all been allocated during the growing (application-in-control) phase of a transaction, subsequent new virtualizations require disk writes and therefore file flushing to maintain file integrity. Whenever a transaction commits after having had to create new virtual objects in excess of the pac size it remembers this and expands the pac by this number as part of the transaction commit, so the next transaction to create 10000 new objects will be able to get them all from the pac, saving all that disk activity. Unallocated objects still in the pac at log-off are discarded, i.e. they become instant garbage, which is harmless.
This excessive disk activity on the first transaction can be avoided by a pac initialization transaction after log-on and before the first big application transaction, in order to grow the pac within the scope of one transaction flush instead of 10000 flushes, like this:
| vom customers departments |
[ vom := VOManager newForExistingSpace: ‘c:\vospaces\myspace’.
vom isNil ifTrue: [^self].
vom open ifFalse: [^self].
vom cacheMaxSize: 11000.
vom storageManager pacSize: 10000 “set required pac size”.
[Array newVirtualIn: vom] atomic. “dummy transaction to trigger pac growth”
[ customers := vom rootDictionary at: ‘customers’.
departments := vom rootDictionary at: ‘departments’
] atomicReadOnly.
…
…
…
] forkAt: (Processor userBackgroundPriority).
Q: “What is the rootDictionary of a virtual space, and should all object accesses go through it?”
A: The rootDictionary is a VirtualDictionary created automatically when a virtual space is created, and is the only object immediately accessible by an image after log-on, it is returned by the message VOManager>>rootDictionary.
In principle (though unusually) there could be several completely independent databases in one virtual space, so each database should be anchored in the rootDictionary using a VirtualDictionary to hold the root objects of the database, which are typically the main VirtualDictionarySets of domain objects requiring multi-key access, e.g. Customers, Departments etc. On startup, the application should get these root objects and assign them to instance variables (e.g. ‘customers’ ‘departments’) in some static object in the application so that they are directly accessible to the application, to avoid the rootDictionary becoming a bottleneck for concurrent transactions.
