   )
  )
 
-(defrecord ImmutableState [^Model metamodel ^IFn close-hook])
 (defrecord MutableState [^Long lastPing ^Map views])
+(defrecord ImmutableState [^Model metamodel ^IFn close-hook ^Atom mutable])
 
 (defn -init [^Model metamodel ^IFn close-hook]
   (debug "init")
   [ ;; super ctor args
    []
    ;; instance state
-   (let [mutable (MutableState. (System/currentTimeMillis) {})
-	 immutable (ImmutableState. metamodel close-hook)]
-     [immutable (atom mutable)])])
+   (ImmutableState. metamodel close-hook (atom (MutableState. (System/currentTimeMillis) {})))])
 
 (defn ^ImmutableState immutable [^org.dada.core.SessionImpl this]
-  (first (.state this)))
+   (.state this))
 
-(defn mutable [^org.dada.core.SessionImpl this]
-  (second (.state this)))
+(defn ^Atom mutable [^org.dada.core.SessionImpl this]
+  (.mutable (immutable this)))
 
 (defn -ping [^org.dada.core.SessionImpl this]
   (trace "ping")

 (:require
  [org.dada.core RemoteSession])
 (:import
  [clojure.lang IFn]
  [java.util Map]
  [org.dada.core Data Model RemoteSession View]
  )

  (with-record ^MutableState @(mutable this) [lastPing] lastPing))

(defn -close [^org.dada.core.SessionImpl this]
  (with-record
   (immutable this)
   [close-hook mutable]
   (close-hook this)
   (debug "close")
   (doseq [[^View view models] (:views @mutable)]
       (doseq [^Model model models] (.deregisterView model view)))))

(defn ^Data -registerView [^org.dada.core.SessionImpl this ^Model model ^View view]
  (debug "registerView")
  (with-record
   (immutable this)
   [^Model metamodel mutable]
   (let [model-name (.getName model)
	 ^Model model (.find metamodel model-name)]
     (if (nil? model)
       (throw (IllegalArgumentException. (str "no Model for name: " model-name)))
       (let [data (.registerView model view)]
	 (swap! mutable (fn [state] (assoc (assoc2m state :views view model) :lastPing (System/currentTimeMillis))))
	 data)))))

(defn ^Data -deregisterView [^org.dada.core.SessionImpl this ^Model model ^View view]
  (debug "deregisterView")
  (with-record
   (immutable this)
   [^Model metamodel mutable]
   (let [model-name (.getName model)
	 ^Model model (.find metamodel model-name)]
     (if (nil? model)
       (throw (IllegalArgumentException. (str "no Model for name: " model-name)))
       (let [data (.deregisterView model view)]
	 (swap! mutable (fn [state] (assoc (dissoc2m state :views view model) :lastPing (System/currentTimeMillis))))
	 data)))))

(defn ^Data -find [^org.dada.core.SessionImpl this ^Model model key]
  (with-record
   (immutable this)
   [^Model metamodel mutable]
   (swap! mutable assoc :lastPing (System/currentTimeMillis))
   (.find ^Model (.find metamodel (.getName model)) key)))
