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