TODO IMMEDIATELY: LAFCMS_DL_MSSQLServer::create_content_shape() and LAFCMS_CM_BASE::shape and related functions don't seem to be being used. Remove them if possible. Make com_CMItem a collection with a property to set what it collects. Make the delete options do something. Add an "array" datatype. Add a filter to CMSystem to optionally include all items, items used as labels and items used as field values. TODO LATER: Consider options to make a connection perform lazy writes. This will almost certainly be necessary when writing to a text file. Consider a command to make a connection flush its lazy writes. Change the object caching system to honor an upper bound and/or respond to memory pressure. Add a routine to the SQL Server worker thread to occassionally check the database integrity and place a force_reload command in the journal if anything is amiss. To find objects with nonexistant containers: select one.item_id, one.container_id, two.location_id from lafcms_membership as one left outer join lafcms_membership as two on one.container_id = two.item_id where (NOT (one.container_id = '00000000000000000000000000')) and (two.location_id IS NULL) Add the ability to move objects from one connection to another without changing IDs and such. Make labelling objects get automatically deleted when the link they're labelling is deleted. This must be conditional though. Make the SQL Server class break up big items into multiple segments if they are going to exceed the row size limit. Add a multi-level transaction system. This will require some way to uniquely identify callers -- thread ID may not be sufficient. Add a multi-container JOIN system. Consider UNION and INTERSECT. Change LAFCMS_DL_MSSQLServer to use OLEDB instead of ODBC. Find a way to make saving/deleting ONLY save the relationships between the saving/deleting object and its related objects. That way, if the related objects are being updated, those changes won't be saved when the object is saved/deleted. Consider adding an absolute time-to-live to objects so that, even if they're in constant use, they'll reload themselves occassionally to ensure data integrity. Add a command to the data layer to make it initialize a blank database. Add an XML connection type. Add a text-based query language -- need a good parser generator first. A new class with one fixed attribute: "name" that must be unique across the whole data store plus n Item-style dynamic attribute. The new class should "contain" Items and provide a way to "cast" them to give non-existant attributes default values and mask off other attributes that are outside of the definition. This class will basically function as a database table to support queries and sorting of the contained Items. The new class should return ItemSets from its query/sort feature. Also, it should cache the queries vs. results and tie into the notification system to dump its caches when appropriate. Create a stateful CMItemSet that will represent query results -- this may require adding an update notification system. Add something to CMSystem to set/clear attributes en masse. Add different datatypes to guarantee uniqueness across all items in a container or globally. Add a query system using callback functions. Add auto-incrementing field types. Add auto-setting field types (new GUID, current date/time). Add a sorting procedure to CMSystem. Finalize the testing scripts and ensure they run through everything. DOCUMENTATION! VERSION 1.0.0.0 - 2/23/2005 Incorporated the changes from LAFcommon version 8.0.0.0. Changed the license from the LAF LGPL to the GNU LGPL. Fixed a potential access violation in LAFCMS_CM_BASE::get_object_array_from_id_array() that would attempt to free memory even if there had been an error in allocating it. Fixed a potential access violation in LAFCMS_CM_Item::cmd_nonreciprocate_object_remove() where a counter was not always being initialized. VERSION 0.0.35.0 - 2/5/2004 Removed DllCanUnloadNow() from the library as it was causing problems in production. DllCanUnloadNow() is called by the host process to test if the library can be unloaded. Since the next logical step is to unload the library, DllCanUnloadNow() was calling the thread_stop() routines, which were shutting everything down and preparing for destruct. As it turns out however, IIS 5.0 calls DllCanUnloadNow() without unloading the library. By removing DllCanUnloadNow(), the library cannot be unloaded until the host process calls CoUninitialize(). VERSION 0.0.34.0 - 11/11/2003 Changed com_CMItem::put_Contents, com_CMItem::put_Containers and com_CMItem::put_Associations so passing an empty array or Empty as the new value will clear the object's list of contents, containers or associations, respectively. Changed com_CMItem::put_Contents and com_CMItem::put_Containers to use the array unloading code from com_CMItem::put_Associations, which was more carefully written to guard against bad objects and memory leaks. Fixed a small typo in a SQL statement in LAFCMS_DL_MSSQLServer::cmd_load() that was preventing associations from loading correctly. VERSION 0.0.33.0 - 9/15/2003 Fixed LAFCMS_DL_MSSQLServer::connection_delete() to check if the passed database object is NULL before attempting to close it. Fixed LAFCMS_DL_MSSQLServer::cmd_open_records() and LAFCMS_DL_MSSQLServer::cmd_run_commands() not to put NULL database objects into the object pool. VERSION 0.0.32.0 - 9/2/2003 Changed LAFCMS_Cache, LAFCMS_DL_BASE and LAFCMS_CM_BASE to use a LAF_semaphore as a reference counter instead of using a member variable protected by a CMutexQueue. The semaphore can provide a count of the threads currently holding a reference and it can store the last_accessed timestamp using the get_/set_user_data() functions. Fixed a minor bug in LAFCMS_DL_BASE::object_store_run() that would stop the processing loop as soon as an object was found that did not require deletion. Changed LAFCMS_Cache::update_ref_count() to accept by-reference parameters to return the reference count and the last-accessed timestamp if needed. Changed LAFCMS_CM_BASE::object_store_run(), LAFCMS_DL_BASE::object_store_run() and LAFCMS_Cache::object_store_run() to do the Right Thing wrt the reference count and last-accessed timestamps of the objects in the stores. Removed the unused parameter already_locked from LAFCMS_CM_BASE::update_ref_count() and LAFCMS_DL_BASE::update_ref_count(). Removed the unused parameter caller from LAFCMS_CM_BASE::get_object(). Removed the unused parameter source_exclusively_locked from LAFCMS_CM_BASE::object_array_copy(). Removed the unused parameter connection_already_locked from LAFCMS_CM_System::create_object() and LAFCMS_CM_Item::create_object(). Fixed a small thinko in LAFCMS_CM_Item::get_objects() that was not returning any labeled objects if there were no unlabeled objects when called with a NULL label_object. Fixed a bug in LAFCMS_CM_Item::get_objects() where LAFCMS_CM_BASE::object_array_append() was being called incorrectly. Fixed a pair of bugs in LAFCMS_DL_MSSQLServer::cmd_load() that were leaking memory and (later) causing access violations when loading objects with labeled contents or associations. Interestingly, this bug was already fixed for the case of loading objects with labeled containers. VERSION 0.0.31.0 - 8/20/2003 Incorporated the changes from LAFcommon version 7.0.0.0. Changed LAFCMS_DL_MSSQLServer::journal_monitor() not to exit when a database error occurs, just to continue looping and retrying. Otherwise, if it exits, it will only be restarted if the connection pool monitor thread also restarts, which is much more rare. Fixed LAFCMS_DL_MSSQLServer::cmd_load() to ignore a minor form of database corruption that would abort loading mass-loading objects if an item was found with a location that did not exist in the location table. Changed LAFCMS_CM_BASE::object_store_run() and LAFCMS_DL_BASE::object_store_run() not to hold their object store locks while they examine the list of stored objects. This was causing problems in production when large numbers of items were loading and LAFCMS_CM_BASE::object_store_run() began working. The object creation routines would block on the object store lock while LAFCMS_CM_BASE::object_store_run() was blocked on the individual objects' locks. Rewrote LAFCMS_CM_System::notify_save() to do the Right Thing in all cases -- the old version would not remove local objects from the LAFCMS_CM_System object when they were given containers. It would also never add remotely saved objects to a LAFCMS_CM_System object. Fixed LAFCMS_CM_BASE::get_id() to not try to protect id with object_lock -- that decision was made in version 0.0.28.0 but the function was not updated. Changed LAFCMS_CM_BASE::internal_init() not to clear id. Since that function is called by LAFCMS_CM_BASE::internal_empty(), which can be called when the object is reloaded, clearing the id field can have disasterous results within the object cache when the key disappears. Changed LAFCMS_DL_MSSQLServer::cmd_load() not to overwrite a LAFCMS_CM_System object's id if it already had one. Changed LAFCMS_CM_Item::notify_delete() not to call LAFCMS_CM_Item::get_id(); it now just accesses the id field directly. Simplified the code in LAFCMS_CM_Item::cmd_remove_label() considerably and changed it so it only forces a save when the object has been updated. Changed LAFCMS_CM_Item::cmd_remove_value() so it only forces a save when the object has been updated. Changed LAFCMS_CM_Item::notify_save() to reload the object's data before it modifies the existing object. That way, if the load fails for any reason the old version of the object is still valid. Fixed a serious reference leak in LAFCMS_CM_Item::notify_delete() that would not decrement the reference counters in (on average) half of the objects in the cache when one was deleted remotely. Changed LAFCMS_CM_Item::notify_delete() to be (on average) 50% more efficient when an object is deleted locally by allowing it to skip searching all other objects for references if the deleted object's reference count is already zero. Fixed LAFCMS_CM_BASE::get_object() to return LAFCMS_enum::LAFCMS_error_not_found when the object is not found instead of LAFCMS_enum::LAFCMS_fail_eof. Fixed LAFCMS_CM_Item::cmd_remove_value() to reorder the attributes after one has been deleted. Fixed a potential access violation in LAFCMS_CM_BASE::attribute_array_copy(). Fixed a heap overrun in LAFCMS_CM_BASE::attribute_destroy_and_cover(). Fixed a logic error in LAFCMS_CM_Item::cmd_remove_value() that was causing memory corruption in item attributes. Fixed a logic error in LAFCMS_CM_Item::cmd_check_attribute_objects() that was causing memory corruption by saving items at index -1 in the attribute array. Fixed a bug in LAFCMS_DL_MSSQLServer::cmd_close_connection() that was causing access violations. Changed LAFCMS_DL_MSSQLServer::cmd_run_commands() to accept a parameter of NULL sql statements and just test for the connection being read-only. Changed LAFCMS_DL_MSSQLServer::cmd_load() to detect if the connection is read-only and fall back to the old one-at-a-time loading procedure. The more complex multi-object loading procedure requires the ability to create temporary tables on the database server. Fixed a no-op statement in LAFCMS_Cache::cache_store_run() to do what it was supposed to. Fixed LAFCMS_Cache::~LAFCMS_Cache() to clear the object differently if the lock has already been disabled for destruction. Being disabled indicates that the object is being destroyed by the worker thread, not because the DLL is unloading. When the worker thread destroys a LAFCMS_Cache object, it should release its references to the LAFCMS_CM_BASE objects normally, without discarding them. Added a last_accessed field to LAFCMS_Cache so that a cache must be idle and unreferenced for 24 hours before it is destroyed by the worker thread. Fixed a locking mistake in LAFCMS_DL_MSSQLServer::cmd_load() that would call LAFCMS_CM_Item::create_object() claiming that the connection object was locked when it was not. Changed LAFCMS_DL_MSSQLServer::cmd_load() not to do more work than necessary when creating new objects that don't need to be loaded from the database. Added a virtual function to LAFCMS_DL_BASE named thread_stop that is to be overridden by all its decendents. The override versions should stop all worker threads created by the decendent classes. Changed LAFCMS_DL_global_object_store::thread_stop() to call thread_stop() in each of LAFCMS_DL_BASE's decendent classes. VERSION 0.0.30.0 - 7/21/2003 Fixed a small typo in LAFCMS_enum_defines.h. Fixed LAFCMS_LAFCMS_tm_copy_realloc() to actually use realloc() to allocate memory instead of just assuming the memory is already available. This bug was causing access violations in production. Fixed LAFCMS_LAFCMS_tm_export() to allow for daylight savings time when calculating its time_t value. VERSION 0.0.29.0 - 4/2/2003 Changed LAFCMS_DL_MSSQLServer::cmd_create() to delete an item's associations before reinserting them, to ensure there are no duplicates. Changed both versions of LAFCMS_DL_MSSQLServer::cmd_load() not to load an object's association array with its own ID. VERSION 0.0.28.0 - 3/28/2003 Incorporated the changes from LAFcommon version 6.8.0.0. Fixed LAFCMS_CM_Item::set_attribute(char*,LAFCMS_CM_Item*,LAFCMS_enum::cm_field_types) to use cmd_find_attribute() correctly. Changed LAFCMS_DL_MSSQLServer to use CHAR(26) fields to store LAFCMS_CM_Item IDs instead of VARCHAR(26). Changed LAFCMS_DL_MSSQLServer::create_shape_desc() and LAFCMS_DL_MSSQLServer::create_table_desc() to add 2 bytes to each string length to correctly calculate the row length as SQL Server does it. Modified LAFCMS_CM_BASE and its decendents to make the id member variable a char[] instead of a char*. This guarantees that the address will always be valid. Since the value of id does not change once an object is created, protecting access to it through object_lock is not necessary. This means that object cache searches no longer need to lock each object before their object IDs are compared, providing a tremendous performance improvement on regression_fortysix.asp (worst-case speedup of approximately 550%). Changed LAFCMS_DL_MSSQLServer to use more than 7 significant digits when printing floating point values into SQL INSERT and UPDATE statements. Changed com_globals.* to pass each EnumReturnCode value through a function when compiled in debug mode as LAFCMS_globals.* does. This makes setting breakpoints much easier. Changed LAFCMS_Cache's AVL find and compare functions to lock the objects and directly access their id variables instead of calling get_id(). Fixed LAFCMS_CM_Item::set_attribute_info() to pass the correct attribute to LAFCMS_CM_BASE::attribute_convert(). Fixed LAFCMS_CM_BASE::attribute_convert() to do the Right Thing and return LAFCMS_enum::LAFCMS_error_type_mismatch in case of an error. Fixed LAFCMS_CM_Item::set_attribute_info() to honor the value returned by LAFCMS_CM_BASE::attribute_convert() instead of ignoring it. Fixed get_LastResult() in com_CMItem, com_CMSystem, com_Cache and com_DLConnection not to reset error_message. Duh. Added LAFCMS_enum::LAFCMS_CM_FIELD_cmitem to the list of valid field types in LAFCMS_enum::is_valid_cm_field_type(). Changed LAFCMS' internal date format from time_t to a new data structure. This change will allow LAFCMS to store dates from 1/1/0000 00:00:00.000 to 12/31/16383 23:59:59.999, even when using MS SQL Server as a data store. Changed LAFCMS_DL_MSSQLServer::create_shape_desc() and LAFCMS_DL_MSSQLServer::create_table_desc() to create larger strings in the database in an attempt to reduce the number of tables the system creates in production databases. Added a parameter to LAFCMS_CM_Item::cmd_save() that will allow the caller to give some extra options to the save routine. The only available option is LAFCMS_SAVE_force_commit, which will force cmd_save() to save the object even if its internal flags indicate it doesn't need to be saved. VERSION 0.0.27.0 - 3/14/2003 Fixed LAFCMS_DL_MSSQLServer::cmd_load_multiple_variables() to run LAFCMS_CM_Item::cmd_reorder_attributes() on the objects it loads instead of letting LAFCMS_DL_MSSQLServer::cmd_load() do it. VERSION 0.0.26.0 - 3/13/2003 Incorporated the changes from LAFcommon 6.7.0.0. Changed LAFCMS_CM_BASE::get_object() to return LAFCMS_enum::LAFCMS_error_invalid_value if a non-null string is passed as the target ID that is not of the correct length. Changed the macros LAFCMS_SET_RETURNCODE, LAFCMS_ALLOCATE_MEMORY_PREP, LAFCMS_ALLOCATE_MEMORY, RETURNCODE_TO_HRESULT, VERSIONINFO and LAFCMS_SET_COM_RETURNCODE to require a semicolon after each so that their inclusion in large if/elseif/else structures won't cause logic errors due to typos. Finished implementing LAFCMS_CM_BASE::attribute_convert(). Added get_read_only() and set_read_only() to LAFCMS_DL_BASE to get and set a boolean flag. Added support to LAFCMS_DL_MSSQLServer to automatically detect if the database connection will allow writes, set the read_only flag if it will not and return an error if writes are attempted anyway. Simplified LAFCMS_CM_BASE::attribute_destroy_and_cover() to use memmove() instead of manually copying every attribute data member. Changed LAFCMS_CM_Item::cmd_remove_value() to use LAFCMS_CM_BASE::attribute_destroy_and_cover() instead of incorrectly implementing the same logic. This also closes a reference leak that prevents referenced objects from being deleted from the object cache. Changed LAFCMS_CM_BASE::attribute_array_copy() to call attribute_init() on newly allocated attributes. Changed LAFCMS_CM_BASE::attribute_copy() to call attribute_destroy() on the destination attribute before beginning the copy procedure. Changed LAFCMS_CM_BASE::shape_array_copy() to honor the return code from shape_copy(). Finished adding code to check the outcome of every memory allocation in the system. This will allow the component to gracefully catch out-of-memory conditions and make way for possible future additions that will prod the cache to dump items to free up memory. Renamed LAFCMS_CM_System::get_content() to get_contents(). Added a JNI interface. Now to document it... Changed a number of functions in LAFCMS_CM_Item and LAFCMS_DL_MSSQLServer to index the attributes when they are loaded or changed so lookups by name will happen in O(log(n)) time instead of O(n) time. Fixed LAFCMS_CM_Item::set_attribute() to allow a double attribute to be set when its type is specified as a double. Changed LAFCMS_Cache to provide separate caches through the use of the ID field, similar to what LAFcommon.COMCollection does. Each cache is completely separate. A worker thread removes empty caches. VERSION 0.0.25.0 - 9/24/2002 Incorporated the changes from LAFcommon 6.5.7.0. Fixed LAFCMS_DL_MSSQLServer::cmd_load() to set LAFCMS_CM_Item::saved when loading objects from the database so it will be possible to save them. Changed the available values of LAFCMS_CM_BASE::cm_object_load_statii. missing means that the object is requested but has not yet been found or created. not_found means the object was requested but could not be found. exists means the object was not found during the first search but an attempt to create and load it failed -- it must have been created in the interim and should be searched for again. created means the object was created but has not yet had its ref_count increased and it has not been placed in the object store. loading means the object exists in the object store but its data is being retrieved. loaded means the object's data has been retrieved. ready means the object is ready to be returned to the caller. terminator is only used to mark the end of an array. Fixed LAFCMS_DL_MSSQLServer::cmd_load() in many numerous ways so it will load the objects correctly as advertised. Added LAFCMS_CM_BASE::set_loading_end() to call send_notify_save() in case other callers have grabbed references to the object before it was completely loaded. Changed LAFCMS_DL_MSSQLServer::cmd_load() to call LAFCMS_CM_BASE::set_loading_end() after an object is completely loaded. Removed the creation locks from the object creation functions -- the calls to set_loading_start() accomplish the same goal. Fixed a mutex double locking problem and a heap corruption problem in the non-local origin section of LAFCMS_CM_System::notify_save(). Fixed the SQL in LAFCMS_DL_MSSQLSERVER_FORMAT_DELETE_ITEM_FROM_LOCATION not to try to delete the item if it has no shape. Fixed LAFCMS_DL_MSSQLServer::get_connection_pool() to only try to start LAFCMS_DL_MSSQLServer::journal_monitor() once. Changed LAFCMS_DL_MSSQLServer::connection_create() to run the SQL statement "SET NOCOUNT ON" against all new connections. This command disables an unneeded feature, improves performance and makes cmd_load() function properly. Changed LAFCMS_DL_BASE::object_store_run() and LAFCMS_CM_BASE::object_store_run() to work with a nonexclusive store lock and not grab an exclusive lock until they really need it. Changed LAFCMS_DL_BASE::object_store_run() and LAFCMS_CM_BASE::object_store_run() to not wait on locking individual objects but to proceed as fast as possible through the list. If an object is locked when the thread runs, chances are good it'll check it next time. VERSION 0.0.24.0 - 9/18/2002 Incorporated the changes from LAFcommon 6.5.6.0. Added release_all_refs() to LAFCMS_CM_BASE and its derived classes to provide a way to forcibly release all stored references to other objects in the system without changing the saved content of the objects. This was necessary so the DLL can be unloaded without causing access violations. Changed LAFCMS_Cache::internal_empty() to take an optional flag that will forcibly discard the references it holds to LAFCMS_CM_BASE objects instead of passing them to LAFCMS_CM_BASE::put_object(). This was necessary so the DLL can be unloaded without causing access violations. Finished the mass-loading version of LAFCMS_DL_MSSQLServer::cmd_load(). Modified the macro LAFCMS_TRACE_SQL_STATEMENT to resolve to a function in debug mode instead of an inline expansion. The new function prints the entire SQL statement, not just the first 510 bytes. This slows down the component in but makes debugging much easier. Fixed a set of memory leaks in LAFCMS_DL_MSSQLServer::journal_monitor() that were leaking four strings when the DLL unloaded. Fixed LAFCMS_DL_MSSQLServer::cmd_run_commands() to actually honor the return value from SQLExecDirect(), then stop and rollback if there is an error. Changed LAFCMS_Cache to optionally store a timestamp with each cache entry as an absolute limit to the entry's lifetime. The first access to the entry after that time has passed will cause the entry to expire. VERSION 0.0.23.0 - 9/11/2002 Removed the calls to SetThreadAffinity() that were restricting the component to running on a single processor, even on multi-processor machines. The fixes in 0.0.22.0 made this unnecessary. VERSION 0.0.22.0 - 9/11/2002 Incorporated the changes from LAFcommon 6.5.5.0. Changed LAFCMS_CM_Item::cmd_save() to always notify when a call stack has been created. Corrected a harmless thinko in the RETURNCODE_TO_HRESULT macro that assumed TEXT was always going to be additional_error_text. Changed the third parameter of LAFCMS_Cache::get_data() from void(**)(void**,void*) to void(*)(void**,void*), which makes more sense. Added internal_variant_copy_noalloc() to com_Cache to be called from LAFCMS_Cache::get_data() and copy a VARIANT without allocating memory. Closed a memory leak in LAFCMS_DL_MSSQLServer::cmd_load() caught by BoundsChecker. Closed a serious memory leak in LAFCMS_CM_BASE::object_array_id_array_free() that was not freeing the ID array if the object array was NULL. Fixed a race condition between LAFCMS_CM_object_store::thread_stop(), LAFCMS_CM_object_store::~LAFCMS_CM_object_store() and LAFCMS_CM_BASE::object_store_run() that would unlock thread_delay_lock multiple times without holding the lock. During object destruction when the saved_nodes list is being destroyed, this can cause access violations. This bug was caught by BoundsChecker. Fixed a race condition between LAFDLS_DL_object_store::thread_stop(), LAFDLS_DL_object_store::~LAFDLS_DL_object_store() and LAFDLS_DL_BASE::object_store_run() that would unlock thread_delay_lock multiple times without holding the lock. During object destruction when the saved_nodes list is being destroyed, this can cause access violations. This bug was caught by BoundsChecker. Fixed an access violation in LAFCMS_DL_MSSQLServer::cmd_create() caused when an error code is returned from the table creation portion of the function and tmp_sql is still NULL. Added another catch() block to the functions LAFCMS_DL_MSSQLServer::journal_monitor(), LAFCMS_DL_MSSQLServer::connection_check(), LAFCMS_DL_MSSQLServer::connection_delete() and LAFCMS_DL_MSSQLServer::connection_create() because (apparently) catch(...) does not keep CException objects from being generated. Unless they are deleted, they leak memory. FTSOBG. Fixed a memory leak in LAFCMS_CM_Item::set_attribute() that was caused when an existing string attribute was overwritten with a new value. Fixed a memory leak in LAFCMS_DL_MSSQLServer::create_insert_statement() caught by BoundsChecker that was leaking all of the canonicalized string values and the array to hold the canonicalized values. Fixed a memory leak in LAFCMS_DL_MSSQLServer::cmd_create() that was leaking the saved object's location ID. Fixed LAFCMS_CM_Item::set_attribute() to detect out-of-memory situations. Changed LAFCMS_DL_MSSQLServer::check_connection(), LAFCMS_DL_MSSQLServer::create_connection() and LAFCMS_DL_MSSQLServer::delete_connection() to accept an additional parameter so they can return exception messages if database exceptions occur. VERSION 0.0.21.0 - 9/9/2002 Fixed some free/delete mismatches in com_Cache's accessor functions. VERSION 0.0.20.0 - 9/7/2002 Fixed LAFCMS_CM_Item::cmd_save() to add only containers to its caller stack and to do it without corrupting the stack. Added LAFCMS_check_returncode() to provide a place to set breakpoints when debugging. It does not compile into the project in release mode. Added a new option flag to LAFCMS_CMItem::cmd_save(): LAFCMS_SAVE_do_not_save_linked_objects will force the function to skip saving all of the linked objects unnecessarily. This is most useful from LAFCMS_CMItem::cmd_delete(). VERSION 0.0.19.0 - 9/6/2002 Changed LAFCMS_CM_Item::cmd_save() to always send a save notification. VERSION 0.0.18.0 - 9/5/2002 Added a call to CMutexQueue::disable_for_destruct() in the LAFCMS_CM_BASE- inheriting and LAFCMS_DL_BASE-inheriting classes' destructors. Changed LAFCMS_CM_System::notify_delete() and LAFCMS_CM_System::notify_save() to call LAFCMS_CM_BASE::send_notify_save() when they modify an object. Fixed a pair of memory leaks in LAFCMS_CM_BASE::get_objects() and LAFCMS_DL_BASE::get_objects(); Fixed a small thinko in LAFCMS_CM_BASE::send_notify_save(). Fixed two major problems in LAFCMS_CM_System::notify_save() that were (1) clearing LAFCMS_CM_System objects and reloading them from their connections without holding an exclusive lock and (2) were not resetting the ID to its previous value, which was corrupting the object store. Added LAFCMS_Cache (and com_Cache) to expose a run-time data store that will hold arbitrary data and flush it automatically when the objects the data depends on are updated. VERSION 0.0.17.0 - 9/4/2002 Incorporated the changes from LAFcommon 6.5.4.0. Changed the semantics within the create_object functions so that when an object is created that will obviously be loaded from a data source (i.e. it has a connection and an ID), its create_object function increments its ref_count and inserts it into the object cache before returning it to the caller. The caller should then immediately lock the object and load its content. This is done so that multiple threads will not attempt to load the same object -- subsequent requests for the object will block on the object's mutex. Added global mutexes to the create_object functions so only one object can be created at a time, per object type. This was necessary so that multiple threads would not overrun the cache pre-insert procedure. Added a new mutex to LAFCMS_CM_BASE for the sole purpose of locking access to the ref_count and last_accessed variables instead of using object_lock for that purpose. Adjusting the objects' reference counts was becoming a bottleneck while constant updates were taking place. Added a new (fourth) parameter to update_ref_count() to return the value of last_accessed. Changed all places where ref_count was being directly updated to use update_ref_count() instead. This was necessary so the new lock will work. VERSION 0.0.16.0 - 8/27/2002 Fixed LAFCMS_DL_MSSQLServer::journal_monitor() to update its last_update timestamp after finding a journal entry so it will not continuously replay the same journal entries again and again for an hour. Fixed a small memory leak in LAFCMS_DL_MSSQLServer::journal_monitor(). Fixed three memory leaks in LAFCMS_DL_MSSQLServer::cmd_load(). VERSION 0.0.15.0 - 8/6/2002 Added a parameter to LAFCMS_CM_BASE::get_object() to allow the caller to pass a pointer to itself to prevent deadlocking when calling update_ref_count(). Fixed LAFCMS_CM_Item::cmd_object_add() to allocate space for the object pointer arrays when the IDs of the connected objects have been loaded but the objects have not. Leaving the object pointer arrays NULL was causing object_array_append() to return an error. Fixed LAFCMS_CM_Item::set_attribute() to prevent the caller from assigning an object to an attribute on itself. Maybe someday that will make sense. Fixed LAFCMS_CM_Item::cmd_delete() to set updated and num_attributes to 0. Fixed LAFCMS_CM_BASE::get_object() not to attempt to load objects with requested IDs of improper lengths. If, by some miracle, they exist in the cache, they will be returned. Changed LAFCMS_DL_MSSQLServer::create_shape_desc() and LAFCMS_DL_MSSQLServer::create_table_desc() to keep track of the size of the table it is creating and stop if it cannot squeeze the row length under SQL Server's limit of 8060 bytes. It will make up to three attempts to get the row size correct, first creating VARCHAR fields with lengths up to 5000 characters, second limiting VARCHAR fields to lengths of 1000 characters and last limiting VARCHAR fields to lengths of 100. Changed LAFCMS_DL_MSSQLServer::cmd_run_commands() to call SQLExecDirect() instead of CDatabase::ExecuteSQL(). For some reason, CDatabase::ExecuteSQL() has an 8K rowsize limit and SQLExecDirect() does not. This was preventing very large INSERT statements from executing. VERSION 0.0.14.0 - 7/31/2002 Fixed the SQL statement in LAFCMS_DL_MSSQLSERVER_FORMAT_DELETE_ITEM_FROM_LOCATION to correctly handle the situation where an item ID is not found in the LAFCMS_membership table or for some reason has a NULL location. Fixed a problem in LAFCMS_DL_MSSQLServer::cmd_update() that was calling the wrong versions of LAFCMS_DL_MSSQLServer::cmd_delete() and LAFCMS_DL_MSSQLServer::cmd_create() because the compiler was automatically casting 0 to a char** as the second argument. VERSION 0.0.13.0 - 7/26/2002 Rewrote a good portion of LAFCMS_CM_BASE::object_array_append() and LAFCMS_CM_BASE::object_array_append() to remove the destination_end_index parameter -- it was not needed and was being misused. VERSION 0.0.12.0 - 7/25/2002 Fixed LAFCMS_CM_BASE::object_array_append() to set final_array_size even if there was no work actually done. VERSION 0.0.11.0 - 7/24/2002 Fixed LAFCMS_CM_BASE::get_object() and LAFCMS_DL_MSSQLServer::cmd_load() to be a little closer to the goal of mass loading objects. They also now work in the case of LAFCMS_CM_System::create_object returning recycled objects instead of always returning new ones. VERSION 0.0.10.0 - 7/23/2002 Changed LAFCMS_CM_Item to enforce connection parity when object linking is performed. This means that all objects being linked to or from must (1) have a connection and (2) have the same connection as the other object(s) being linked to or from. Changed LAFCMS_DL_BASE::update_ref_count() to accept a new second parameter to indicate if the object is already locked. Changed LAFCMS_CM_object_store::create_objects to a function definition that expects four parameters. The new third parameter is an int to indicate if the LAFCMS_DL_BASE object is already locked. Changed LAFCMS_CM_Item::create_object() and LAFCMS_CM_System::create_object() only to create an object of the correct type, not to call LAFCMS_DL_BASE::cmd_load() if an ID is specified. Began making changes to LAFCMS_CM_BASE that will allow LAFCMS_DL_BASE-derived classes to load more objects than requested. This will make pre-caching possible as well as working with data sources where random accesses are not possible (text files, etc). Fixed LAFCMS_DL_MSSQLServer::journal_monitor to correctly exit when a connection error occurs and to attempt to restart if it is not running when the next connection pool access is made. Packaged and released LAFCMS as free software! Changed nearly every function in the system to accept and pass around an additional char** parameter with the intent that it finally get passed to the routines in LAFCMS_DL_MSSQLServer that make any database calls. That way, any errors generated by the database layer can be passed back up to someone who can do something about it. VERSION 0.0.9.0 - 7/10/2002 Fixed LAFCMS_CM_BASE::object_array_append() to eliminate duplicates when asked to do so. VERSION 0.0.8.0 - 7/10/2002 Changed LAFCMS_CM_Item to check all its attributes and verify that any objects used as values have not been deleted before conducting any operations that deal with attribute indexes. This change makes referring to attributes by name much faster than referring to them by index. Greatly changed the behavior of LAFCMS_CM_Item::set_attribute_info() to (1) not create new attributes if the specified target is not found, (2) allow the caller to change the type without changing the name and vice-versa, (3) not allow the attribute to be renamed to an already-existing name and (4) allow a caller to change an attribute by name without knowing its index. Changed com_CMItem::put_AttributeType() and com_CMItem::put_AttributeName() to use the new features of LAFCMS_CM_Item::set_attribute_info(). VERSION 0.0.7.0 - 6/27/2002 Incorporated the changes from LAFcommon version 6.5.2.0. Fixed LAFCMS_CM_Item::get_num_objects() to return a count of 0 objects if the given ID array is NULL. Added a new field type that allows LAFCMS_CM_Item objects to be stored as field values. This is essentially a unidirectional, nonreciprocal link between two objects. Fixed LAFCMS_CM_System::notify_save() to add a new LAFCMS_CM_Item object to empty LAFCMS_CM_System objects when they are saved. Changed LAFCMS_CM_BASE::object_store_run() so unsaved LAFCMS_CM_BASE objects will be removed much earlier than saved ones. Setting the max_idle_mins property will override the default saved/unsaved time limits. Deleted objects are always removed immediately. Changed LAFCMS_DL_BASE::object_store_run() so setting the max_idle_mins property will override the default time limit for removal. VERSION 0.0.6.0 - 6/25/2002 Incorporated the changes from LAFcommon version 6.5.1.0. Moved some global constants in LAFCMS_CM_BASE.cpp into a class (LAFCMS_CM_object_store) to make them extendable so when future projects add new classes derived from a child of LAFCMS_CM_BASE, they can be added to the list of classes LAFCMS_CM_BASE::get_object() can return. Moved some of the declarations in LAFCMS_CM_Item from the private section to the protected section to make it possible to derive classes from LAFCMS_CM_Item. Added LAFCMS_CM_object_store::add_object_type() to allow child classes to register themselves so they can be returned by LAFCMS_CM_BASE::get_object(). Added LAFCMS_CM_BASE::realloc_object() to change a LAFCMS_CM_BASE-derived object into a different type of LAFCMS_CM_BASE-derived object. Added LAFCMS_CM_Item::replace_object() to be called by LAFCMS_CM_BASE::realloc_object() to do the work of allocating the new object and moving the data into it. Added LAFCMS_CM_Item::notify_replace() to catch notifications that an object has been replaced. Fixed some small thinkos in LAFCMS_DL_MSSQLServer::cmd_run_commands(), LAFCMS_DL_MSSQLServer::cmd_open_records() and LAFCMS_DL_MSSQLServer::cmd_close_records() that would return the wrong error return code if get_connection_pool() failed. Fixed a tricky race condition in LAFCMS_CM_BASE::get_object() that would return LAFCMS_enum::LAFCMS_error_internal if two threads were trying to load the same object at the same time, instead of blocking one thread until the other had finished creating the object, then returning the object to the other thread. Removed a MAJOR performance bottleneck in com_CMItem and com_CMSystem -- since the most common use of the COM interface is to attach to a previously created object, there is no need to create a new object until it is needed. By deferring the creation of a new internal object until an attempt is made to access its data or methods, most of the contention for the global object pool lock can be removed. This change enabled the Wizards site to go from handling (at most) two clients simultaneously to handling many (10+) clients simultaneously. VERSION 0.0.5.0 - 5/15/2002 Incorporated the changes from LAFcommon version 6.4.0.0. Renamed LAFCMS_CM_Item::get_shape() and LAFCMS_CM_Item::set_shape() to LAFCMS_CM_Item::get_attribute_info() and LAFCMS_CM_Item::set_attribute_info(), respectively. Renamed the COM properties CMItem.ShapeName and CMItem.ShapeType to CMItem.AttributeName and CMItem.AttributeType, respectively. Added a(nother) parameter to LAFCMS_CM_BASE::object_array_copy() to allow the caller to specify the first index to be filled in the destination array. Fixed LAFCMS_CM_BASE::object_array_free() so it would work as advertised. Corrected a horrible (and widespread) misconception that LAFCMS_CM_BASE::object_array_free()'s second parameter indicated the number of objects in the array instead of a flag to indicate if the source was exclusively locked. This was fixed by changing the order of the parameters so the misconception is now true. Added a parameter to LAFCMS_CM_BASE::object_array_free() and LAFCMS_string_array_free() to indicate the first element to free. If the parameter is greater than or equal to zero, the array itself is not freed. Added the ability to use labelling objects for containers, contents and associations. Added a parameter to LAFCMS_CM_BASE::update_ref_count() to indicate if the object is already locked. Added parameters to LAFCMS_CM_BASE::object_array_free(), LAFCMS_CM_BASE::object_array_id_array_free(), LAFCMS_CM_BASE::object_array_copy() and LAFCMS_CM_BASE::object_array_append() to identify the calling (previously exclusively locked) object. Added flags to the contained, containers and associations functions in LAFCMS_CM_Item to allow multiple relationships between two items to be established. Fixed and changed too many other numerous things to list here. VERSION 0.0.4.0 - 3/21/2002 Changed LAFCMS_CM_System::create_object() to search for an object with the same requested connection and return it, instead of creating a new object every time. This is only possible because LAFCMS_CM_System objects are fairly stateless. Changed LAFCMS_CM_BASE::get_object() not to exclusively lock the object store until it needs to insert the new object. This allows object creations to access the object store if necessary. Changed LAFCMS_CM_System::set_connection() to do no work if the new connection is the same as the old connection. Changed com_CMSystem::put_ID() to use its "parameter" parameter as a DLConnection object when it tries to find a new object. Changed com_CMItem::get_ID(), com_CMItem::put_ID(), com_CMSystem::get_ID() and com_CMSystem::put_ID() to accept and return VARIANTs instead of BSTRs. This allows the put_ID() methods to accept a VARIANT of type VT_EMPTY to signal that the target ID is NULL. Changed all the places where return_code is set to a non-success value to use a preprocessor macro instead so the macro can be replaced with an assertion during debugging. Changed LAFCMS_CM_BASE::internal_init() to initialize deleted to 0 so objects won't be immediately garbage collected. Changed LAFCMS_DEFAULT_MAX_IDLE_MINS to allow objects to persist in cache for 12 hours instead of 20 minutes. VERSION 0.0.3.0 - 3/20/2002 Incorporated the changes from LAFcommon version 6.2.0.0. Fixed a bug in LAFCMS_DL_MSSQLServer::journal_monitor() that was fetching the wrong data type from the server for the fields in the recordset. Fixed a bug in LAFCMS_DL_MSSQLServer::journal_monitor() that was not closing the recordset before deleting the database object, causing the database object to attempt to close the recordset itself. Since the recordset's database pointer had already been set to NULL, the recordset was throwing an exception. Added "putref" versions of the Containers, Contents and Associations properties on LAFCMS.CMItem. VERSION 0.0.2.0 -- 3/16/2002 Fixed a debug/release problem in LAFCMS_DL_MSSQLServer::cmd_create() that was smashing the stack by allocating a number of bytes using _alloca() and assuming it had instead allocated that number of char*s. Fixed a pair of debug/release problems in LAFCMS_DL_BASE::get_objects() and LAFCMS_CM_BASE::get_objects() that were allocating memory based on the size of the wrong datatype. Fixed an easily triggerable deadlock situation in LAFCMS_CM_BASE::get_object_array_from_id_array() where calling get_object() from an exclusively locked object will cause the comparison function in the AVL tree to hit a mutex timeout. Fixed a non-trival locking problem in the sequence of an object saving all of its containers, contents and associations when it is saved. The problem is when cmd_save() gets called a number of times down a chain of objects, each object attempts to call send_notify_save() after it's done. However, for each recursively called object, at least one other object is locked somewhere on the stack above it. Thus, calls to get_object() triggered by send_notify_save() will fail with timeouts. The solution is to save a pointer to every object saved and have the top-level caller call send_notify_save() on their behalfs. Fixed a problem with LAFCMS_CM_Item::cmd_delete that was deleting the object's ID without removing it from the object store. Since the store uses the IDs as indexes, this corrupts the store. Modified the LAFCMS_CM_BASE garbage collector to remove deleted objects as soon as possible instead of waiting for their idle timeouts. Fixed a trio of bugs in LAFCMS_CM_Item::set_containers(), LAFCMS_CM_Item::set_contents() and LAFCMS_CM_Item::set_associations() that could cause memory leaks under some circumstances by not counting the number of objects in the array before freeing it, potentially missing elements beyond a mid-array NULL. Fixed a trio of bugs in LAFCMS_CM_Item::set_containers(), LAFCMS_CM_Item::set_contents() and LAFCMS_CM_Item::set_associations() that were calling cmd_nonreciprocate_*_remove() on their object arrays without first guaranteeing that the object array elements had been loaded. Fixed a bug in LAFCMS_CM_BASE::object_array_append() that was not initializing all of the allocated object pointers to NULL if the source array contained objects that already existed in the destination array. VERSION 0.0.1.0 -- 3/15/2002 Initial version.