Working with Sessions

The FairCom DB API interface requires a session object to perform any data structure initialization or manipulation. The following steps must be executed within a session before any database or table operations are attempted:

  1. Construct a CTSession object
  2. Logon to a c-tree session by calling the CTSession::Logon() method.

Then, after this initialization, all database and table operations should be performed. After these, in order to finalize the database operations, the following steps should be performed:

  1. Logout from a c-tree session by calling the CTSession::Logout() method.
  2. Destroy the CTSession object

Creating a Session Object

A valid session object is required to perform any session operation. The default parameter of the CTSession constructor is CTSESSION_CTDB.

// create a default CTSession object
CTSession ASession;
try
{
   // logon to session using default
   // server name, user name and password.
   CTSession.Logon();
}
catch (CTException &err)
{
   printf("Session logon failed with error %d\n", err.GetErrorCode);
}

If you create a dynamic CTSession object with the new operator, you are required to destroy the object with the delete operator.

// create a dynamic CTSession object
CTSession* pSession = new CTSession;

if (!pSession)
{
   printf("CTSession allocation failed\n");
}  
... other operations ..

// destroy the CTSession object
delete pSession;

When a session object is created, we can specify the session type. There are three different session types:

CTSESSION_CTREE Allocate a new session for logon only. No session or database dictionary files will be used. No database functions can be used with this session mode. You must allocate table handles using the session handle.
CTSESSION_CTDB Allocate a new session making full usage of FairCom DB API session and database dictionaries. With this session mode, a Session dictionary file must exist to perform a session logon and you need to connect to a database before attempting to perform operation on tables.
CTSESSION_SQL Allocate a new session for FairCom DB SQL processing. This mode allows changes made at the FairCom DB API level to be reflected at the FairCom DB SQL level without requiring an additional table import step; your tables are immediately available with the FairCom DB SQL interface. While this session type is available, limitations still exist. Support for alter table operations are not supported; FairCom DB API AlterTable() activities are NOT reflected in the FairCom DB SQL system tables.
// Create a session object
CTSession ASession(CTSESSION_CTDB);

Creating a New Session Dictionary

When operating with sessions of type CTSESSION_CTDB or CTSESSION_SQL, a session dictionary file named ctdbdict.fsd is required before a session logon is performed. The session dictionary file ctdbdict.fsd is located by default either in the server directory (client/server application) or in the application directory (stand-alone application).

There could be situations where the FairCom DB SQL session dictionary file does not exist because it was deleted or this is the very first time the system is being executed. In this case it is necessary to create a session dictionary file before attempting to logon to a session. It is important to note that only one session dictionary file is necessary for the normal operation of FairCom DB SQL. Once created, the session dictionary file can be used for all database and table operations.

The following code fragment shows an example on how to create a new session dictionary file:

CTSession ASession;  
try
{
   ASession.Create("FAIRCOMS", "ADMIN", "ADMIN");
}
catch (CTException &err)
{
   printf("Create session failed with error %d\n", Err.GetErrorCode());
}

In the server name, the full network address may be used (FAIRCOMS@10.0.0.1 or FAIRCOMS@my_machine.com for instance). For non-server applications, the parameter is ignored and may be set to NULL.

A valid user name is required to access the c-tree Server. When the server is first installed, only the default user is permitted server access. This user name, ADMIN, is intended for the database administrator. ADMIN is also the default user name for FairCom DB API sessions. For non-server applications, the user name may be NULL. For server applications, see the c-tree Server Administrator’s Guide on how to create users and groups.

A valid user password is also required to access the c-tree Server. When the server is first installed, the default user ADMIN is associated with the default password, also ADMIN. For non-server applications, the user password may be NULL.

Session Logon and Logout

In order to perform any database operations, it is necessary to logon to a c-tree session. A session is terminated with a session logout.

To log on to a session, a CTSession object must be instantiated and then CTSession::Logon() method should be called to perform the session logon.

Example:

// Logon to a session
CTSession ASession;
try
{
	ASession.Logon("FAIRCOMS", "ADMIN", "ADMIN");
}
catch (CTException &err)
{
	printf("Session logon failed with error %d\n", err.GetErrorCode());
}

Note: A useful sequence in code is to try to log on to the session, and if it fails with error FNOP_ERR (12), create the session dictionary and then log on again.

Example:


CTSession ASession;
CTBOOL createit = NO;
// try to logon to a session
try
{
   ASession.Logon("FAIRCOMS", "ADMIN", "ADMIN");
}
catch (CTException &err)
{
   if (err.GetErrorCode() == FNOP_ERR)
   {
      createit = YES;
   }
   else
      throw;
}
if (createit)
{
   ASession.Create("FAIRCOMS", "ADMIN", "ADMIN");
   try
   {
      ASession.Logon("FAIRCOMS", "ADMIN", "ADMIN");
   }
   catch (CTException &err)
   {
      printf("Logon failed with error %d\n", err.GetErrorCode());
   }
}

When operations with the session are no longer needed, it is necessary to logout from the session by invoking method CTSession::Logout().

Example:

CTSession ASession;
// logon to a session
try
{
  	ASession.Logon("FAIRCOMS", "ADMIN", "ADMIN");
  	// ... perform some other operations ..
  	ASession.Logout();
}
catch (CTException &err)
{
	printf("Logon or Logout failed with error %d\n", err.GetErrorCode());
}


Session Properties

The default session properties are suitable for most FairCom DB API applications. Advanced developers may need to tune FairCom DB API to meet application requirements. Use CTSession::SetSessionParams() to set the following properties:

Table 3-1: Default Session Parameters

Property Explanation Default
BUFS Index file buffers 10
FILS File structure blocks 32
SECT Node sectors 32
DBUFS Data file buffers 10
USERPROF User profile mask 513

The default USERPROF value of 513 tells single-user, transaction-control applications, to remove the auxiliary log files S*.FCS and L*.FCS upon successful termination of the application, and also removes the automatic key transformation.

The table below present all possible values for the USERPROF parameter. See InitISAMXtd for detailed descriptions.

User Profile Values

Keyword Value Explanation
USERPRF_NTKEY 1 Do not perform auto tfrmkey
USERPRF_SAVENV 2 Savenv mode for transactions
USERPRF_NDATA 32 Do not perform auto data - UNIFRMAT conversion
USERPRF_LOCLIB 64 Use a local library: not server
USERPRF_PTHTMP 128 Add tmpname to input path, otherwise use system tmpname
USERPRF_CLRCHK 512 Clear transaction logs

Example:


// set a different user profile before logging on to a session
CTSession ASession;
try
{
   // set the new profile
   ASession.SetSessionParam(USERPROF, (USERPRF_NTKEY | USERPROF_CLRCHK));
   
   // logon to a session
   ASession.Logon("FAIRCOMS", "ADMIN", "ADMIN");
}
catch (CTException &err)
{
	printf("Session logon failed with error %d\n", err.GetErrorCode());
}

Server and User Name Properties

Once a session is active, the user may retrieve the server name for the session with CTSession::GetServerName(). Retrieve the user name by calling the CTSession::GetUserLogonName() method. Please refer to the example in "Active property".

Active Property

A session is active if the user has logged on to a valid session dictionary using CTSession::Logon(). To render a session inactive, log off using CTSession::Logout(). To verify the status of the session, use CTSession::IsActive().

Example:

//if session is active, retrieve the server name and user logon name
if (ASession.IsActive())
{
   printf("Server name: %s\n", ASession.GetServerName());
   printf("User name  : %s\n", ASession.GetUserLogonName());
}

Path Property

The default path for client/server applications is the server directory, while the default path for non-server applications is the application directory. If, for any reason, there is the need to modify the location of the session dictionary, the CTSession::SetPath() may be used, before creating and/or logging on to the session. CTSession::GetPath() may be used to retrieve the path for an active session.

Using this property, it is even possible to have multiple session dictionaries, in separate directories. This is not required, since the concepts of restricting access to different users to diverse tables or databases may be implemented inside a unique session dictionary.

The example below shows how to use the CTSession::SetPath() function to create a session dictionary file in a user specified directory, instead of the default directory:

Example:

CTSession ASession;
try
{
	ASession.SetPath("\new\session");
	ASession.Create("FAIRCOMS", "ADMIN", "ADMIN");
}
catch (CTException &err)
{
   printf("Create session failed with error %d\n", err.GetErrorCode());
}


Managing Databases

Once the user performs a successful Session logon, the session object can be used to operate on databases.

Every time a new database is created, or an existing database is added to a session, the database properties such as database name and path are placed in an entry of the database dictionary file.

Every time a user activates a database by connecting to it using CTDatabase::Connect() method, the database is placed in a list of active (connected) databases within the session. When a database is deactivated or disconnected by CTDatabase::Disconnect() method, the database is removed from the list of active databases. A user may query the active database list by locating the first active database, the next active database or finding a specific active database.

Creating a new Database

Use CTSesson::CreateDatabase() method to create a new database. CTSession::CreateDatabase() takes a database name and the path where the database dictionary file is to be created. If the database path is NULL or empty ("") the database is created in the server directory, for client/server applications, or in the current directory for standalone applications.

// create a new database MyDatabase
try
{
   ASession.CreateDatabase("MyDatabase", "");
}
catch (CTException &err)
{
   printf("Create database failed with error %d\n", err.GetErrorCode());
}

CTSession::CreateDatabase() creates a new database dictionary file with the database name and extension .FDD (FairCom Database Dictionary). Using the example above, the database dictionary file created is MyDatabase.fdd.

Adding an existing Database

An existing database may be added or imported to a session by calling the CTSession::AddDatabase() method. Use CTSession::AddDatabase() to add an existing database to the current session. CTSession::AddDatabase() takes a database name and the path where the database is located.

// add MyDatabase to the current session
try
{
   ASession.AddDatabase("MyDatabase", "");
}
catch (CTException &err)
{
   printf("Add database failed with error %d\n", err.GetErrorCode());
}

Dropping a Database

When you drop a database from a session, the database information is removed from the session dictionary, but the database dictionary file is left untouched. The drop database operation can be reversed with an add database operation. Drop a database from a session by calling CTSession::DropDatabase() method.

// drop MyDatabase from current session
try
{
   ASession.DropDatabase("MyDatabase");
}
catch (CTException &err)
{
   printf("Drop database failed with error %d\n", err.GetErrorCode());
}

Deleting a Database

When you delete a database from a session, the database information is removed from the session dictionary and the database dictionary file is deleted. The delete database operation cannot be reversed and the database dictionary data will be lost. Delete a database from a session by calling CTSession::DeleteDatabase() method.

// delete MyDatabase from current session
try
{
   ASession.DeleteDatabase("MyDatabase");
}
catch (CTException &err)
{
   printf("Delete database failed with error %d\n", err.GetErrorCode());
}

First Database

CTSession::FirstDatabase() will retrieve the name and path of the first database in a session. If the session has no databases, CTSession::FirstDatabase() returns NO (false).

Next Database

CTSession::NextDatabase() will retrieve the name and path of the next database in a session. CTSession::NextDatabase() returns NO (false) when no more databases exist for the current session.

// display all databases in a session
CTDBRET DisplayDatabases(CTSession& ASession)
{
   CTDBRET Retval = CTDBRET_OK;
try
{
      CTString dbName;
      CTString dbPath;
  
      if (ASession.FirstDatabase(dbName, dbPath))
      do
      {
printf("Database: %s Path: %s\n", dbName.c_str(), dbPath.c_str());
      }
      while (ASession.NextDatabase(dbName, dbPath);
}
catch (CTException &err)
{
   Retval = err.GetErrorCode();
}
   return Retval;
}

Find Database

CTSession::FindDatabase() locates a specific database given the database name and, if the database exists, retrieves the database path. If a database cannot be found, CTSession::FindDatabase() returns NO (false).

// return YES if database exist or NO if database does not exit
CTBOOL DatabaseExist(CTSession& ASession, CTString& dbName)
{
   CTBOOL Retval;
   CTString dbPath;
  
   try
{
      Retval = ASession.FindDatabase(dbName, dbPath);
   }
   catch (CTException &err)
   {
      Retval = NO;
   }
   return Retval;
}

First Active Database

CTSession::GetFirstActive() retrieves a database object pointer of the first active database. If the session contains no active databases, CTSession::GetFirstActive() returns NULL.

Next Active Database

CTSession::GetNextActive() retrieves a database object pointer of the next active database. When no more active database exist, CTSession::GetNextActive() returns NULL.

// Display all active databases
void DisplayActiveDatabases(CTSession &ASession)
{
   VRLEN hScan;
   CTDatabase* pDatabase;
 
   if ((pDatabase = ASession.GetFirstActive(&hScan)) != NULL)
   {
      do
      {
          printf("Database: %s Path: %s\n", pDatabase->GetName().c_str(),
   	   pDatabase->GetPath().c_str());
	   hDatabase = ASession.GetNextActive(&hScan);
      }
      while (pDatabase != NULL);
   }
}

Find Active Database

CTSession::FindActive() locates a specific active database and returns the database object pointer. If the database is not active, CTSession::FindActive() returns NULL.

// Check if database is active
CTBOOL IsDatabaseActive(CTSession &ASession, const CTString& dbName)
{
   return (ASession.FindActive(dbName) != NULL) ? YES : NO;
}

The function above is shown for example purposes only as the FairCom DB API API method CTDatabase::IsActive() provides a more efficient way to check if a database is active or not.

Database UID (Unique IDentifier)

When a database is created or added to a session, an automatic and unique identifier (UID) is associated with the database. A database UID is unique within the session.

A database UID is an unsigned long value that can be used as an alternative method to operate on databases, once the database is created or added to the session.

You can obtain a database UID with CTSession::GetDatabaseUID

Find Database by UID

The overloaded method CTSession::FindDatabase() locates a database given the database UID and retrieves the database name and path. The following example shows how to implement a database connect procedure using the database UID instead of the database name.

// Database Connect using UID
CTDatabase* ConnectByUID(CTSession &ASession, ULONG uid)
{
   CTString dbName;
   CTString dbPath;
   CTDatabase *Retval = NULL;

   if (ASession.FindDatabase(uid, dbName, dbPath)
   {
      Retval = new CTDatabase(ASession);
      if (Retval)
      {
         Retval->Connect(dbName);
      }
      else
      {
         throw CTException(CTDBRET_NOMEMORY);
      }
   }
   else
   {
      throw CTException(FNOP_ERR);
   }
   return Retval;
} 

Find active Database by UID

The overloaded CTSession::FindActive() locates an active database given its UID number and returns the database object pointer. The following example shows how to check if a database is active using its UID number.

// check if database is active, by UID
CTBOOL IsActiveDatabase(CTSession &ASession, ULONG uid)
{
   return (ASession.FindActive(uid) != NULL) ? YES : NO;
}

 

Working with Sessions without Dictionary Support

There may be situations where it is necessary to operate with a table that does not belong to a database, or where a session or database dictionary file is not required. For these situations the user may want to create a session object of type CTSESSION_CTREE.

// create a session object without dictionary support
CTSession ASession(CTSESSION_CTREE);
// Logon to a session
try
{
   ASession.Logon("FAIRCOMS", "ADMIN", "ADMIN");
}
catch (CTException &err)
{
   printf("Session logon failed with code %d\n", err.GetErrorCode());
}

The CTSession::Logon() call above will perform a c-tree logon but it will not attempt to open a session dictionary file. The same result is obtained if a normal CTSESSION_CTDB or CTSESSION_SQL session is allocated but the method CTSession::SetLogonOnly() is called before CTSession::Logon().

// create a session object without dictionary support
CTSession ASession;
// Logon to a session
try
{
   ASession.SetLogonOnly();
   ASession.Logon("FAIRCOMS", "ADMIN", "ADMIN");
}
catch (CTException &err)
{
   printf("Session logon failed with code %d\n", err.GetErrorCode());
}

 

Attach and Detach Existing Sessions

There are situations where an existing connection to c-tree already exists, via a call to a low level or ISAM c-tree initialization function, but FairCom DB API functionality is required without terminating the existing connection and starting a new FairCom DB API session. The following methods are available to permit a session handle to be attached and detached from an existing c-tree connection.

CTSession::Attach() attaches an inactive session handle to an existing c-tree Plus or FairCom DB API session. Attached sessions have no information on server, user name or user password, and these values are set to NULL. If a Logout() is performed on an attached session handle, no session logout is performed and a DetachSession() call is executed instead.

There are three valid mode values:

mode Parameter Description
CTATTACH_SESSION Attach to a FairCom DB API session whose session handle is pointed by parameter source.
CTATTACH_CTREEID Attach to a c-tree Plus session whose instance id string is pointed by parameter source.
CTATTACH_CURRENT Attach to the current c-tree instance. Contents of parameter source is ignored, as the c-tree instance id is obtained by calling WCHCTREE() function.

CTSession::Detach() detaches a FairCom DB API session handle. The c-tree ISAM or low-level un-initialization is not called, but the session handle control structures are released and re-initialized. Handle is a session handle allocated by AllocSesison(). DetachSession() returns CTDBRET_OK on success.

Session Dictionary

The session dictionary is a collection of databases, and each record of the session dictionary file contains the information of a particular database. In general, just one session dictionary file exists, ctdbdict.fsd, located by default in the execution directory (client/server development) or in the execution directory (stand-alone application). The table below represents the general layout of a session dictionary file:

Session Dictionary Layout

Field Type Length Description
TYPE CT_INT4 4 Record type: 1-database 2-table 3-index
STATUS CT_INT4 4 Record status: 0-status ok 1-reserved
NAME CT_FSTRING 128 Name of database or table or index
LINK CT_FSTRING 128 Name of table if record type is 3-index
LINKNBR CT_INT4 4 Table UID if record type is 3-index
PATH CT_FSTRING 256 Path of database dictionary, data or index
SUPEXT CT_FSTRING 16 Super file extension (if super file is used)
DATEXT CT_FSTRING 16 Data file extension (usually .DAT)
IDXEXT CT_FSTRING 16 Index file extension (usually .IDX)
VERSION CT_INT4 4 Record version: 0x00010000 (version 1.0)
COUNTER CT_INT4 4 Deprecated.
UID CT_INT4 4 UID for database or table or index
OWNER CT_FSTRING 128 Name of owner - used by the c-treeSQL server
MIRROR_NAME CT_FSTRING 128 Name of mirrored file.
MIRROR_PATH CT_FSTRING 128 Path of mirrored file.
RESERVED CT_ARRAY 3128 Reserved for future use

This information is included for general information on the session dictionary structure. FairCom DB API has appropriate functions to retrieve any needed information from the session dictionary, such as the database UID or path.

A session dictionary file has several different record types:

  • Database records (the field Type set to 1) holds information about databases.
  • A special type four record which maintained the COUNTER field has been been deprecated as of FairCom DB V9.0.