1% BEGIN LICENSE BLOCK 2% Version: CMPL 1.1 3% 4% The contents of this file are subject to the Cisco-style Mozilla Public 5% License Version 1.1 (the "License"); you may not use this file except 6% in compliance with the License. You may obtain a copy of the License 7% at www.eclipse-clp.org/license. 8% 9% Software distributed under the License is distributed on an "AS IS" 10% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 11% the License for the specific language governing rights and limitations 12% under the License. 13% 14% The Original Code is The ECLiPSe Constraint Logic Programming System. 15% The Initial Developer of the Original Code is Cisco Systems, Inc. 16% Portions created by the Initial Developer are 17% Copyright (C) 2006 Cisco Systems, Inc. All Rights Reserved. 18% 19% Contributor(s): 20% 21% END LICENSE BLOCK 22 23% File : multiuser-sec.tex 24% Date : March 1992 25% Author : Michael Dahmen 26% Modified by : Luis Hermosilla, August 1992 27% Joachim Schimpf, July 1994 28% Project : MegaLog-Sepia User Manual 29% Content : The multi user system, recovery, transactions 30 31\newpage 32 33\chapter{Multi User \eclipse} 34\label{multi} 35\index{multi user} 36\index{transaction} 37The \eclipse multi user system allows to share databases or 38knowledge bases among several users. Every user is running an \eclipse 39process and is able to retrieve and update information. 40To the user, multi user database access is similar to single user 41access described in the previous chapters except that any 42access of shared relations must be performed within a {\em transaction} context. 43This guarantees that the database is kept in a consistent 44state at all times. 45 46Multi User \eclipse is designed for client-server networks. 47A database server process manages the database, and the \eclipse client 48processes communicate with the server, possibly across a network. 49The standard \eclipse configuration allows up to 32 concurrent user 50processes per database. This restriction may be lifted in future releases. 51 52\section{The Database server} 53 54Any database can be used in either single or multi user mode: 55\begin{itemize} 56\item In single user mode, a single \eclipse process opens the database 57exclusively, preventing other users from using it at the same time. 58\item In multi user mode, a database server process manages the 59database and several \eclipse client processes can use the database 60concurrently via this server. 61\end{itemize} 62The multi user mode is enabled for a database by simply starting 63a database server for it. A server is started with the command 64\begin{quote}\begin{verbatim} 65% bang_server /data/base/path & 66\end{verbatim}\end{quote} 67where the argument specifies the database that the server should control. 68The server should be started as background process, which is achieved 69by the \verb+&+ suffix. 70The server must be started before the first user process tries to 71open the database (otherwise the first user process would open it 72in single user mode). 73When there is already a server running, or when the database is 74already open in single user mode, an attempt to start a server 75results in an error. 76 77The database server may be terminated by the following command 78\begin{quote}\begin{verbatim} 79% kill -INT pid 80\end{verbatim}\end{quote} 81where {\tt pid} is the process identification 82number of the database server process. 83 84\section{Accessing a Multi User Database} 85 86After invoking the \eclipse process the user opens a database or 87knowledge base as usual, by just specifying the database path name. 88The system will check whether the database is controlled 89by a database server. If so, it will connect to the server and 90switch to multi user mode, otherwise the database is opened in single 91user mode. 92 93After opening the shared database a user has access to all permanent 94relations, as they are all shared. The temporary relations are private 95per user and invisible to other users. Access to both types of relation 96is provided by the interface described in chapter \ref{database-sec} and 97\ref{knowbase-sec}. However, any access to shared relations is only 98possible within a transaction context. 99If a database access is made outside a transaction context 100an error is raised. 101\index{transaction} 102\index{shared relation} 103 104A transaction context is established as follows: 105\begin{quote}\begin{verbatim} 106?- transaction(Goal). 107\end{verbatim}\end{quote} 108which executes {\bf Goal} as a transaction. Any changes the execution of 109the goal makes to the database are only {\em committed} (i.e. 110made permanent) if the goal succeeds. This 111gives a transaction an all-or-nothing property, 112with either all the updates of the goal being committed to the database for 113a valid goal, or the database being left in 114the old state (i.e. as before the transaction started) 115for an invalid goal. An example: 116 117\begin{quote}\begin{verbatim} 118?- openkb(test). 119 120yes 121?- transaction(( flight <==> S1, passenger <==> S2 )). 122S1 = [+flight_no, +from, +to, time, day]. 123S2 = [+name, +flight_no]. 124yes 125?- transaction( 126 insert_clause(flight(ba100,london,munich,1200,tuesday)) 127 ). 128 129yes 130?- read(Name), read(Flight), % should not be done inside transactions 131 transaction( (insert_clause( passenger(Name,Flight) ), 132 flight(Flight, From, To, Time, Day), 133 % assuming flight is transparent 134 write('From: '), writeln(From), 135 write('To: '), writeln(To), 136 write('Time: '), writeln(Day), 137 write('Day: '), writeln(Time), 138 write('Confirm (y/n): '), 139 read(Conf), 140 Conf == y) ). 141 142smith. 143ba100. 144From: london 145To: munich 146Time: tuesday 147Day: 1200 148Confirm (y/n): 149\end{verbatim}\end{quote} 150This example takes a passenger's name (smith) and flight request 151(ba100) and prints the flight details. If the request is confirmed 152the passenger name and flight is added to the passenger relation. 153The addition to the database required by the sub-goal 154\begin{quote}\begin{verbatim} 155insert_clause( passenger(Name,Flight) ) 156\end{verbatim}\end{quote} 157 will only be committed if 'y.' is entered to confirm the flight booking. 158Otherwise the final sub-goal fails and no database changes are made. 159 160Note that it is not possible to modify the shared part of the database 161schema while using a database in the multi user mode. This restriction 162might be lifted in future releases. 163 164\section{Concurrency Control} 165\index{concurrency} 166\eclipse uses the {\em Two Phase Locking} algorithm to control 167concurrent usage of the database. 168\index{two phase locking} 169Two phase locking uses read and write locks on 170all permanent relations. Before a read or write 171operation is performed within a transaction the 172corresponding lock is obtained. This is done during 173the first phase of the transaction. The second phase consists 174of only two operations, namely committing or undoing the 175changes and releasing all obtained locks. Several transactions 176can have a read lock on a single item, but if a transaction 177has a write lock no other can have any lock on it at the 178same time. When a transaction is unable to 179obtain a lock it is suspended until the lock comes free, 180and then it is continued. 181This strategy guarantees serialisability i.e.\ 182the result of the interleaved execution is equivalent 183to a sequential execution of non-interleaved transactions. 184Concurrency control is performed automatically behind 185the scenes and there is neither a need nor a possibility for the user 186to influence it. Only the lock granularity can be changed by the 187user between relation level and page level locking (see Knowledge Base BIP 188Book, {\bf database_parameter/2}). 189 190\section{Deadlock Detection and Handling} 191\index{deadlock} 192Since a transaction is suspended when a lock cannot 193be obtained there is the chance of a {\em deadlock}. 194A deadlock is a situation where a set of transactions is 195suspended, each waiting for an item locked by another member 196of the set. A deadlock can only be resolved by aborting at 197least one of the transactions. 198 199The transaction that is aborted when deadlock occurs is called 200the victim. The strategy for victim selection must prevent 201lifelock. A lifelock happens when the victim is restarted and 202leads to the same deadlock as before. A lifelock is prevented in 203\eclipse by always aborting the youngest transaction, and by 204fairness of lock distribution (i.e. on a first-come first-served 205basis). 206 207When a transaction is aborted due to deadlock an error is raised 208and the error handler executes the goal 209 210\begin{quote}\begin{verbatim} 211?- exit_block(transaction_abort). 212\end{verbatim}\end{quote} 213This {\em exit\_block/1} operation aborts the transaction and restarts it. 214A transaction is restarted up to 10 times. If it is chosen as victim 21510 times another is raised and no further attempt to restart is made. 216 217Before the transaction is restarted all changes done to shared relations 218are undone. However, changes to private relations or the Prolog 219main memory (e.g. dynamic database, global variable and arrays) are not 220undone. Programs that are executed as transactions must therefore be 221written in such a way that they can cope with restarts. 222One way to achieve this is to trap the {\em exit\_block/1} operation with 223{\em block/3} construct. Another possibility is to remove all temporary 224relations at the start of any transaction. 225 226A simple example how to use the {\em block/3} construct is given below. 227Let us assume \verb+s1+ and \verb+s2+ are shared relations and \verb+p+ 228a private, all with a single attribute of type atom. 229 230\begin{quote}\begin{verbatim} 231unsafe(X) :- ins_tup(s1,X), ins_tup(p,X), ins_tup(s2,X). 232 233?- transaction(unsafe(new_item)). 234\end{verbatim}\end{quote} 235Such a program is unsafe with respect to transaction abort in the case 236of deadlocks. Let us assume that a deadlock occurs when an attempt is 237made to insert into \verb+s2+ and that this transaction is selected as 238victim. The change done to \verb+s1+ will be undone, but the change 239of \verb+p+ will not, because it is part of the private database. 240A safe version using {\em block/3} looks as follows. 241 242\begin{quote}\begin{verbatim} 243safe(X) :- ins_tup(s1,X), 244 block(ins_tup(p,X), 245 Tag, 246 ( del_tup(p,X), exit_block(Tag) )), 247 ins_tup(s2,X). 248 249?- transaction(safe(new_item)). 250\end{verbatim}\end{quote} 251If the same deadlock occurs in this transaction the tuple inserted will 252be deleted before the transaction restarts. It is important that 253the {\em block/3} does invoke the {\em exit\_block/1} afterwards, 254otherwise the transaction will not be restarted. 255 256Please note that the example above simplifies the problem, e.g. it 257does not handle the case that the insertion was not effective because 258the tuple is already stored. In general it is simpler to 259initialise the private relations at the start of the transaction, 260the method sketched aboved should only used where that approach 261is not possible for other reasons. 262 263 264\section{Recovery} 265 266The capability to undo transactions requires a recovery mechanism. 267The \eclipse recovery algorithm does also handle recovery after 268a system failure 269\footnote{A `system failure' is when there is a hardware or software 270failure that requires a process(es) to be restarted, but does not affect secondary storage.}. 271If system failure occurs while \eclipse is executing transactions a 272{\em consistent recovery} is guaranteed. This means that after such 273a failure the database will be left in a consistent state, 274with any changes made by aborted or incomplete transactions being undone. 275A {\em shadow page} technique is used by \eclipse to implement the 276recovery procedure. 277\index{recovery} 278 279Recovery only applies to permanent relations and not temporary ones. 280This is because temporary relations are conceptually intended to last 281for just the life of the transaction in which they are produced, and 282therefore recovery is unnecessary. In actual fact temporary relations 283continue to exist until the end of the owner's \eclipse session. 284This provides a useful way of passing sets of tuples or clauses 285outside a transaction. 286 287Recovery after a system failure is also provided in single user \eclipse. 288The {\em transaction/1} predicate does exist in all variants and 289defines the unit of recovery. 290Note that recovery from system failure is only guaranteed to work if 291the operating system supports acknowledge disk writes and the 292controlling \eclipse parameter is turned on (see Knowledge Base BIP Book, 293{\bf database_parameter/2}). 294 295\section{Old \& New States} 296 297During a transaction a permanent relation has two states. 298The old state is the state of the relation before the transaction starts 299and the new state is the state of the relation 300after all the changes of previous subgoals have been made. 301Within a transaction the new 302state is always used (unless the old state is explicitly selected), and when 303the transaction completes successfully the changes are 304committed and the old state becomes equal to the new state. 305 306To obtain the old state within a transaction the operator {\bf old} is 307used in the following way: 308\index{old/1} 309\begin{quote}\begin{verbatim} 310old(RelationName) 311\end{verbatim}\end{quote} 312where {\bf RelationName} is the name of a relation. 313Therefore a predicate can be directed to work with the 314old state of a relation by adding the old operator 315to the relation's name. An example is 316 317\begin{quote}\begin{verbatim} 3181 ?- transaction( digits <++ [ 1,2,3,4,5 ] ). 319 320yes 3212 ?- transaction( ( ins_tup( digits(6) ), 322 findall(X,retr_tup( old(digits), X), L))). 323L = [[1], [2], [3], [4], [5]] 324X = _g16 325 326yes 3273 ?- transaction( findall(X,retr_tup(digits,X),L) ). 328L = [[1], [2], [3], [4], [5], [6]] 329X = _g4 330 331yes 332\end{verbatim}\end{quote} 333The second transaction inserts a tuple into the digits relation, 334and then generates a list of all the tuples in that relation. 335Since the {\bf retr\_tup} predicate is directed to work with the old 336state the newly added tuple does not appear in the list. 337 338 339Even though the new state of a predicate is used by default a 340new operator is included for completeness i.e. 341\index{new/1} 342\begin{quote}\begin{verbatim} 343new(RelationName) 344\end{verbatim}\end{quote} 345The old state exists both in the DB and the KB version, however, in 346the KB version access is a bit tricky. An expression like 347\begin{quote}\begin{verbatim} 348retrieve_clause(( (old(name))(Arg1, Arg2) :- Body )) 349\end{verbatim}\end{quote} 350is {\em not} legal Prolog. One must therefore first introduce a synonym 351\begin{quote}\begin{verbatim} 352old(name) <--> old_name 353retrieve_clause(( old_name(Arg1, Arg2) :- Body )) 354\end{verbatim}\end{quote} 355 356\section{Deterministic Transactions} 357 358Since a transaction must release all its locks on completion 359it cannot backtrack. Therefore {\bf transaction/1} will 360succeed at most once (i.e. it is deterministic). 361This does not limit the use of the transaction primitive 362as the {\bf findall} predicate can be used to collect 363sets of solutions (see previous example). 364Also temporary relations can be used. As mentioned 365above these conceptually die when their transaction dies, 366but since it is a useful way of passing sets of clauses 367from a transaction (which can then be used for backtracking 368{\em outside} a transaction) they are allowed to live until 369the end of the session. 370 371