• No results found

Migrating Your Application Between Operational Models

4. Best Practices

4.15 Migrating Your Application Between Operational Models

c-treeACE is designed to simplify the transition between different platforms or operational models. For the most part, changing models is simply a matter of compiling new libraries and re-linking your application.

However, some concepts are specific to one operational model. The transition can be made smoother by reading this section and Chapters 2-4 in the Quick Start and Product Overview

Guide.

4.15.1 Single-user to Multi-user Standalone or Client/Server

Changing from a single-user application to multi-user (either standalone or client/server) introduces the possibility of multi-user interference. This is prevented by proper locking

techniques and/or transaction processing (available with the c-treeACE Server). See Multi-User

Concepts and Data Integrity in the c-treeACE Programmers Reference Guide

(http://docs.faircom.com/doc/ctreeplus/) for more information.

A single-user standalone application can support transaction processing. If switching to multi-user standalone, transaction processing will not be available. Transaction processing is possible when migrating from single-user standalone to multi-user client/server, since both support transaction processing. In fact, this simplifies the locking issue since locking can easily be added to existing transaction processing calls. For example, replacing Begin(ctTRNLOG) with Begin(ctTRNLOG |

ctENABLE). See Adding Transaction Processing (page 54) and Data Integrity in the c-treeACE

Programmers Reference Guide (http://docs.faircom.com/doc/ctreeplus/) for more information.

4.15.2 Multi-user Standalone to Client/Server

A frustrating scenario, relating to users migrating from c-treeACE Multi-User FPUTFGET model to the c-treeACE Server, needs to be discussed. The dilemma relates to users of the c-treeACE Server receiving FCRP_ERR (14) error codes when opening server based files. The message text for the FCRP_ERR (14) error states “File corrupt at open”. Keep in mind that this scenario only exists due to a power loss, a machine being tuned off without stopping the server, or a miscoded program that does not close its files, only when the c-tree developer chooses NOT TO implement transaction control as suggested for the c-treeACE Server.

The FCRP_ERR (14) did not exist in the multi-user mode, so therefore a scenario was created in which customers, who have been running successfully for years, upgrade to the c-treeACE Server for stronger data integrity, start to receive “corrupt data errors”. The error is due to either the user shutting off the power to their server computer or an application not properly closing its files. Under FPUTFGET, the end-user (or the application) could get away with this. Now they get errors. Can you imagine the end-user frustration?

First, it is in order to discuss the FCRP_ERR (14) error. In c-treeACE single-user mode and under the c-treeACE Server, a file update flag is maintained within the header of each file. When a file is written to, in any manner, this flag is set to indicate the file has been updated. When the file is closed, this flag is re-set, indicating that the application has properly closed the file. Any attempt to open a file which has been marked update and which has not been properly closed, will result in a FCRP_ERR (14) error. The c-treeACE Server has no way of knowing the state of this file, and therefore must return this state back to the application as an integrity error/warning. In c-tree’s multi-user FPUTFGET mode, the write operation is immediate secured to disk and therefore this flag is not maintained nor considered. An error 14 simply did not exist under

FPUTFGET. An application could exit without properly closing a file, or a computer or file server

immediate catastrophic results for the customer. Perhaps the last “enter-key” entry at the time of power loss could be out of sync, yet the entire file would not be in question.

So now, take the scenario where one has a user, who has been running for years under

FPUTFGET, who upgrades to the c-treeACE Server. As a reasonable half-step, the developer

chooses to start with the application running in the same matter as it did with FPUTFGET, and intends to add the necessary code changes for transaction processing at a later date. The developer’s efforts are easy, simply re-link the application with the c-treeACE Client library instead of the FPUTFGET library, and it is ready to go. Now, the updated application and new c-treeACE Server are deployed at the customer’s site. The customer proceeds to operate in the same manner before, now complimented by the Client/Server architecture, experiencing less network traffic, and better performance due to the Server’s data caches. Now, as before, the customer “flips the switch” at the end of the day, just like they have done for years (without you knowing it). CATASTROPHIC situation. Now all data/index files open at the time are in question. Because of the c-treeACE Server’s caches, not just the last “enter-key”, but the entire file is now undefined. A FCRP_ERR (14) is properly returned the next time the file is opened. The user, who is used to coming in the next day, switching on the machine and going back to work, was now calling the developer’s tech support line reporting numerous error 14 messages and corrupt data. The following solutions are available to solve this dilemma:

1. Of course, the ultimate solution is to secure the data using transaction control. This way all entries are 100% secure, up to the point of the last transaction commit. When migrating from

FPUTFGET, this solution requires application code changes to implement the transaction

control, as transaction processing does not exist in FPUTFGET.

2. When the c-treeACE Server was introduced, a file mode was added to c-treeACE called

ctWRITETHRU. If a developer defined a file as ctWRITETHRU, all its write operations would

be flushed to disk in the same manner of the FPUTFGET model. What is different about server ctWRITETHRU versus the FPUTFGET is that the server continues to maintain the update flag in the file’s header as described above. Therefore, if the machine is switched off, the data is in the same state as the FPUTFGET model. The exception is that the open request returns the 14 error, where under FPUTFGET it does not. The server keyword

COMPATIBILITY WTHRU_UPDFLG exists for the c-treeACE Server to instructs the server not to maintain this update flag for ctWRITETHRU files. Therefore to completely “clone” the

FPUTFGET results, a developer needs to add the ctWRITETHRU file mode to all file

definitions within the program, and activate the COMPATIBILITY WTHRU_UPDFLG keyword in the server’s configuration file (ctsrvr.cfg). (Actually, this is better than a clone, for all read operations may safely remain cached under the c-treeACE Server.)

3. There is an additional additional feature which prevents the need to change the client application. Once the server configuration keyword COMPATIBILITY FORCE_WRITETHRU

has been activated, all files opened in non-transaction processing mode (nonTRNLOG), are automatically set to ctWRITETHRU. In other words, this has the same effect as the developer changing all this file modes to include ctWRITETHRU, but because this is automatically done on the server side, the client side application does not need to be touched. This solution is the best and easiest for developers who want to take easy step from FPUTFGET to Client/Server without changing the application.

By activating the following keywords in your server’s configuration file (ctsrvr.cfg), the bases are covered:

COMPATIBILITY FORCE_WRITETHRU COMPATIBILITY WTHRU_UPDFLG

In addition, a warning message helps the developer recognize this vulnerability. If a server does NOT have COMPATIBILITY WTHRU_UPDFLG in its configuration file, and if

be issued in CTSTATUS.FCS concerning the vulnerability to FCRP_ERR (14) if a server is not shutdown properly. The warning is only entered into CTSTATUS.FCS one time, after each server startup when a vulnerable file is detected. The keyword STATUS_MASK WARNING_FCRP_ERR may be added to the configuration file to eliminate this warning message.

4.15.3 Adding Transaction Processing

Adding transaction processing to an application permits complex, atomic updates and automatic recovery in the case of software or hardware failures. Transaction processing can be added with the transaction processing sub-API or with SetOperationState().

To add efficient transaction processing, use the transaction processing sub-API described in Data

Integrity in the c-treeACE Programmer's Reference Guide

(http://docs.faircom.com/doc/ctreeplus/). If your application is already prepared for multi-user use, replacing LockISAM(ctENABLE) calls with Begin(ctTRNLOG | ctENABLE) and replacing

LockISAM(ctFREE) calls with Commit(ctFREE) or Abort(ctFREE) calls, depending on the status of the transaction at that point, is a simple method of implementing transaction processing. See

ctixmg.c for an example and Data Integrity for more details.

To add transaction processing quickly, though not in the most efficient manner, use

SetOperationState() with the OPS_AUTOISAM_TRN mode. This performs a transaction around each ISAM update. See “SetOperationState” for more details. This method does not effectively lock updates. You will still need to use some form of locking control. Consider the

OPS_LOCKON_GET mode for SetOperationState() to minimize network traffic.

Once the application supports transaction processing, add either of the transaction processing file modes, ctTRNLOG or ctPREIMG, to the data files requiring transaction processing using the UpdateFileMode() function. Index files must be rebuilt to add or remove transaction processing. For additional information on Transaction Processing, please see Data Integrity.

4.15.4 Single-threaded to Multi-Threaded

Switching to a multi-threaded, ctThrd, library is similar to adding transaction processing: superficially very easy, but with many implications.

As a minimum when using the ctThrd library, you must implement the ctThrd API. You must call ctThrdInit() before initializing c-treeACE, just as you must initialize c-tree before calling any other c-treeACE API functions.

Any new threads that call c-treeACE API functions must be created with ctThrdCreate() or attached with ctThrdAttach().

In the Multi-threaded Standalone model, do not mix the c-treeACE Instance API

(RegisterCtree(), etc.) with the ctThrd API. Each thread is it’s own instance of c-treeACE, and handles instance switching via the ctThrd functions. This is not an issue with the Multi-threaded Client Model.

See ctThrd Function Overview in the c-treeACE Programmers Reference Guide (http://docs.faircom.com/doc/ctreeplus/) for more detail.