         :pnr    pnr)))
   (log "finished reservation" (:id @reservation)))
 
+(defn process-reservation-par
+  [reservation
+   {:keys [cars flights rooms]}
+   {:keys [n-queries]}
+   workers]
+  "Process a reservation: find a car, flight, and room for the reservation and
+  update the data structures."
+  (dosync
+    (log "start tx for reservation" (:id @reservation))
+    (send (rand-nth workers) :car    cars    reservation n-queries)
+    (send (rand-nth workers) :flight flights reservation n-queries)
+    (send (rand-nth workers) :room   rooms   reservation n-queries)
+    (let [pnr (generate-pnr reservation)]
+      (alter reservation assoc
+        :status :in-process
+        :pnr    pnr)))
+  (log "finished reservation" (:id @reservation)))
+
 ; BEHAVIORS
 
+(def reserve-relation-behavior
+  (behavior
+    [secondary-worker-id master]
+    [relation-name relation reservation n-queries]
+    (log "reserve" relation-name "for reservation" (:id @reservation)
+      "by secondary worker" secondary-worker-id)
+    (dosync
+      (let [n-people (:n-people @reservation)
+            found-relation
+              (look-for-seats (random-subset n-queries relation) n-people)]
+        (when found-relation
+          (log "reserving" relation-name (:id @found-relation))
+          (reserve-relation reservation found-relation n-people))))
+    (send master :done relation-name (:id @reservation))))
+
 ; In vacation, this corresponds to a client.
-(def worker-behavior
-  (behavior
-    [worker-id master data options]
+(def reservation-behavior
+  (behavior
+    [worker-id master secondary-workers data options]
     [reservation]
     ; Note: as opposed to the vacation benchmark, we only support making
     ; reservations, not deleting customers or updating tables.
     (log "start reservation" (:id @reservation) "by worker" worker-id)
-    (process-reservation reservation data options)
-    (send master :done (:id @reservation))))
+    (process-reservation-par reservation data options secondary-workers)
+    (send master :done :reservation (:id @reservation))))
 
 (def done? (promise))
 
 (def master-waiting-behavior
   (behavior
     [n]
-    [_done _reservation-id]
+    [_done _key _id]
+    ; _key is one of :reservation, :car, :flight, :room
     (if (= n 1)
       (do
         (log "done")

    (when (:debug options)
      (def log log-debug))
    (if proceed?
      (let [options {:n-workers      (:workers options)
                     :n-reservations (:reservations options)
                     :n-relations    (:relations options)
                     :n-queries      (:queries options)}]
        (log "options: " options)
        (when (not= (rem (:n-reservations options) (:n-workers options)) 0)
          (println "WARNING: number of reservations is not divisible by number"

(def cli-options
  [["-w" "--workers N" "Number of workers"
    ; Workers are called clients in vacation, the option is -c there.
    :default 20
    :parse-fn #(Integer/parseInt %)]
   ["-s" "--secondary-workers N" "Number of secondary workers"
    ; New, not in vacation.
    :default 20
    :parse-fn #(Integer/parseInt %)]
   ["-n" "--queries N" "Number of queries per relation per reservation"
