Question

I. Problem Statement:

Your project's run time environment consists of a main thread that handles the input,

initializes the necessary data structures and a pool of mutex and condition variables to

ensure that operations belonging to the same transaction are executed in proper order

(zgt_test.C). The main thread creates a transaction manager object (there is only one Tx

mgr object) and the associated hash table that acts as a lock table. As the input is read

from a file, a separate thread is created and started for carrying out each operation (in

a real DBMS one thread or process will handle all the operations of a Tx) requested by

that transaction (zgt_tm.C). The reason for using threads is to allow concurrent execution

of multiple threads, where possible, by the Tx mgr logic. The thread is terminated at the

end of the operation using a pthread_exit call. The main thread reads transactions

(instructions from the input- see below) and invokes a method on the created

transaction manager object. This method will create a new thread to perform each

operation.

The thread created for each operation will execute a function (not a method, as we are

using C) for that operation in zgt_tx.C. For example, the function begintx does the

operation of starting a transaction. All the functions for a transaction execution (begintx,

readtx, writetx, committx, and aborttx) need to be implemented or completed as part of/nCSE 4331/5331 - Fall 2023 (All Sections)

this project. The thread has to make sure that a previous operation by the same

transaction has been completed before starting the current operation (otherwise, as

you know, it is not a legal schedule). In order to do that, it uses a condition wait on a

mutex. Each transaction has a mutex associated with it for this purpose. This is

accomplished by using the SEQNUM array and condset array defined in class zgt_tm. They

are initialized to zero. Each operation is assigned its position using the count variable

before a thread is created. SEQNUM is used to keep track of the order of operations for

each Tx. The count variable in each thread holds the current operation number. They are

compared with the condset[tid] value to decide whether to wait (using cond_wait on the

thread) for an operation or proceed. This allows the operations to be executed

sequentially within a Tx. Use the cond_wait and cond_broadcast functions. The working

of these functions is described in the supplementary material. If the operation is

successfully completed (i.e., transaction gets a shared or exclusive lock for that

operation), the appropriate parameters should be inserted in the log file. Do a flush on

the logfile write operation to force write it. If there are no threads available, an error

should be written in the log. You make sure all threads complete before exiting the test

program.

Since each operation of each transaction is done in a separate thread, all errors and the

log output need to be printed (or transmitted) at the point of occurrence. These threads

cannot return any error status.

A transaction abort operation should release locks held on all objects by that transaction

(not necessarily in any particular order). In addition, the abort operation should release

all transactions waiting on objects held by the aborted transaction so that one of them

can proceed.

A transaction commit will also release locks held on all objects by that transaction and the

transactions waiting on those objects (not necessarily in any particular order). This is done

by doing as many p operations associated with the semaphore for that tx. In a real DBMS,

the data durability (or persistence) will be handled by the buffer manager and the log is

written for recovery which we are not addressing in this project. However, in this

simplified project, values of the data items reflect the work accomplished by a

transaction.

Question image 1Question image 2