Lecture 10
Lecture 10
• Call from one function to another function within the same process
– Uses stack to pass arguments and return values
– Accesses objects via pointers (e.g., C) or by reference (e.g., Java)
• LPC has exactly-once semantics
– If process is alive, called function executed exactly once
Remote Procedure Call
• Call from one function to another function, where caller and callee
function reside in different processes
– Function call crosses a process boundary
– Accesses procedures via global references
• Can’t use pointers across processes since a reference address in process P1 may point to a different object in
another process P2
• E.g., Procedure address = IP + port + procedure number
P1 main() LPC
int f1()
int f2()
LPC
RPCs
P1 main() LPC
int f1()
int f2()
LPC
RPC
P2
int f2()
RPCs
RPC
P2
int f2()
RPCs
• Possible semantics
– At most once semantics (e.g., Java RMI)
– At least once semantics (e.g., Sun RPC)
– Maybe, i.e., best-effort (e.g., CORBA) (Common Object Request Brokerage Architecture)
Implementing RPCs
int caller()
Client stub
P1 Communication module
(“client”)
Communication module
Dispatcher
Server stub
P2
int callee()
(“server”)
RPC Components
int caller()
Client
•Client stub: has same function signature as callee()
Client stub
– Allows same caller() code to be used for LPC and RPC
P1 Communication module
•Communication Module: Forwards requests and
replies to appropriate hosts
(“client”)
Server
Communication module
•Dispatcher: Selects which server stub to forward
request to
Dispatcher
•Server stub: calls callee(), allows it to return a value
Server stub
P2
int callee()
(“server”)
Generating Code
• Programmer only writes code for caller function and callee function
• Code for remaining components all generated automatically from function
signatures (or object interfaces in Object-based languages)
– E.g., Sun RPC system: Sun XDR interface representation fed into rpcgen compiler
• These components together part of a Middleware system
– E.g., CORBA (Common Object Request Brokerage Architecture)
– E.g., Sun RPC
– E.g., Java RMI
Marshalling
• Caller (and callee) process uses its own platform-dependent way of storing data
• Middleware has a common data representation (CDR)
– Platform-independent
Marshalling (2)
• Now that we know RPCs, we can use them as a building block to understand transactions
Transaction
Client code:
int transaction_id = openTransaction();
x = server.getFlightAvailability(ABC, 123, date);
if (x > 0)
y = server.bookTicket(ABC, 123, date);
RPCs
server.putSeat(y, “aisle”);
// commit entire transaction or abort
closeTransaction(transaction_id);
Example: Transaction
Client code:
int transaction_id = openTransaction();
x = server.getFlightAvailability(ABC, 123, // read(ABC, 123, date)
date);
if (x > 0) // write(ABC, 123, date)
RPCs y = server.bookTicket(ABC, 123, date); // write(ABC, 123, date)
server.putSeat(y, “aisle”);
// commit entire transaction or abort
closeTransaction(transaction_id);
Atomicity and Isolation
• Atomicity: All or nothing principle: a transaction should either i) complete successfully, so its effects
are recorded in the server objects; or ii) the transaction has no effect at all.
• Isolation: Need a transaction to be indivisible (atomic) from the point of view of other transactions
– No access to intermediate results/states of other transactions
– Free from interference by operations of other transactions
• But…
• Clients and/or servers might crash
• Transactions could run concurrently, i.e., with multiple clients
• Transactions may be distributed, i.e., across multiple servers
ACID Properties for Transactions
• Two transactions are serially equivalent if and only if all pairs of conflicting
operations (pair containing one operation from each transaction) are
executed in the same order (transaction order) for all objects (data) they both
access.
– Take all pairs of conflict operations, one from T1 and one from T2
– If the T1 operation was reflected first on the server, mark the pair as “(T1, T2)”, otherwise
mark it as “(T2, T1)”
– All pairs should be marked as either “(T1, T2)” or all pairs should be marked as “(T2, T1)”.
1. Lost Update Problem – Caught!
At Server: seats = 10
Transaction T1 Transaction T2
x = getSeats(ABC123);
x = getSeats(ABC123); T1’s or T2’s update was lost!
// x = 10
if(x > 1) if(x > 1)
(T2, T1) // x = 10
x = x – 1;
write(x, ABC123);
(T1, T2) seats = 9
x = x – 1;
write(x, ABC123);
commit (T1, T2)
commit seats = 9
2. Inconsistent Retrieval Problem – Caught!
At Server:
Transaction T1 Transaction T2 ABC123 = 10
x = getSeats(ABC123); ABC789 = 15
• At commit point of a transaction T, check for serial equivalence with all other
transactions
– Can limit to transactions that overlapped in time with T
• If not serially equivalent
– Abort T
– Roll back (undo) any writes that T did to server objects
Can We do better?
• More concurrency => more transactions per second => more revenue ($$$)
• Real-life workloads have a lot of read-only or read-mostly transactions
– Exclusive locking reduces concurrency
– Hint: Ok to allow two transactions to concurrently read an object, since read-read
is not a conflicting pair
Another Approach: Read-Write Locks
• Each object has a lock that can be held in one of two modes
– Read mode: multiple transactions allowed in
– Write mode: exclusive lock
• Before first reading O, transaction T calls read_lock(O)
– T allowed in only if all transactions inside lock for O all entered via read mode
– Not allowed if any transaction inside lock for O entered via write mode
Read-Write Locks (2)
• Two-phase locking
– A transaction cannot acquire (or promote) any locks after it has started
releasing locks
– Transaction has two phases
1. Growing phase: only acquires or promotes locks
2. Shrinking phase: only releases locks
– Strict two phase locking: releases locks only at commit point
Why Two-phase Locking => Serial Equivalence?
• Proof by contradiction
• Assume two phase locking system where serial equivalence is violated for some two
transactions T1, T2
• Two facts must then be true:
– (A) For some object O1, there were conflicting operations in T1 and T2 such that the time ordering pair is (T1,
T2)
– (B) For some object O2, the conflicting operation pair is (T2, T1)
• (A) => T1 released O1’s lock and T2 acquired it after that
=> T1’s shrinking phase is before or overlaps with T2’s growing phase
• Similarly, (B) => T2’s shrinking phase is before or overlaps with T1’s growing phase
• But both these cannot be true!
Downside of Locking
• Deadlocks!
Downside of Locking – Deadlocks!
Transaction T1 Transaction T2 T1
Lock(ABC123);
Wait for
Lock(ABC789); Wait for
x = write(10, ABC123);
Lock(ABC789); T2
// Blocks waiting for T2 y = write(15, ABC789);
Lock(ABC123);
… … // Blocks waiting for T1
When do Deadlocks Occur?
3. Deadlock Prevention
•Set up the system so one of the necessary conditions is violated
1. Some objects are accessed in exclusive lock modes
• Fix: Allow read-only access to objects
2. Transactions holding locks cannot be preempted
• Fix: Allow preemption of some transactions
3. There is a circular wait (cycle) in the Wait-for graph
• Fix: Lock all objects in the beginning; if fail any, abort transaction => No cycles in Wait-for graph
Next