diff --git a/Data/TCache/Defs.hs b/Data/TCache/Defs.hs
new file mode 100644
--- /dev/null
+++ b/Data/TCache/Defs.hs
@@ -0,0 +1,19 @@
+{-# LANGUAGE   DeriveDataTypeable #-}
+
+module Data.TCache.Defs where
+import Data.Typeable
+import Control.Concurrent.STM(TVar)
+	
+
+	
+type AccessTime = Integer
+type ModifTime  = Integer
+
+
+data Status a= NotRead | DoNotExist | Exist a deriving Typeable
+
+data Elem a= Elem a AccessTime ModifTime   deriving Typeable
+
+type TPVar a=   TVar (Status(Elem a))
+
+data DBRef a= DBRef String  (TPVar a)  deriving Typeable
diff --git a/Data/TCache/IResource.hs b/Data/TCache/IResource.hs
new file mode 100644
--- /dev/null
+++ b/Data/TCache/IResource.hs
@@ -0,0 +1,228 @@
+{-# LANGUAGE   ScopedTypeVariables
+    , UndecidableInstances, FlexibleInstances #-}
+module Data.TCache.IResource where
+
+import Data.Typeable
+import System.IO.Unsafe
+import Control.Concurrent.STM
+import Control.Concurrent
+import System.Directory
+import Control.Exception as Exception
+import System.IO
+import System.IO.Error
+import Data.List(elemIndices)
+import Control.Monad(when,replicateM)
+import Data.List(isInfixOf)
+
+--instance  (Typeable a, Typeable b) => Typeable (HashTable a b) where
+--       typeOf _=mkTyConApp (mkTyCon "Data.HashTable.HashTable") [Data.Typeable.typeOf (undefined ::a), Data.Typeable.typeOf (undefined ::b)]
+
+--import Debug.Trace
+
+--debug a b= trace b a
+
+{- | An IResource instance that must be defined for every object being cached.
+there are a set of implicit IResource instance trough utiliy classes (See below)
+-}
+class IResource a where 
+        {- The `keyResource string must be a unique  since this is used to index it in the hash table. 
+        when accessing a resource, the user must provide a partial object for wich the key can be obtained.
+        for example:
+        
+        @data Person= Person{name, surname:: String, account :: Int ....)
+        
+        keyResource Person n s ...= n++s@
+        
+        the data being accesed must define the fields used by keyResource. For example
+
+         @  readResource Person {name="John", surname= "Adams"}@
+        
+        leaving the rest of the fields undefined
+
+        when using default file persistence, the key is used as file name. so it must contain valid filename characters
+        
+        -}
+        keyResource :: a -> String             -- ^ must be defined
+
+        {- | 'readResourceByKey' implements the database access and marshalling or of the object.
+        while the database access must be strict, the marshaling must be lazy if, as is often the case,
+        some parts of the object are not really accesed.
+        Moreover, if the object contains DBRefs, this avoids unnecesary cache lookups
+        this method is called inside 'atomically' blocks and thus may be interrupted without calling
+        Since STM transactions retry, readResourceByKey may be called twice in strange situations. So it must be idempotent, not only in the result but also in the effect in the database
+        -}
+        readResourceByKey :: String -> IO(Maybe a)
+        -- | the write operation in persistent storage. It must be strict.  
+        -- Since STM transactions may retry, writeResource must be idempotent, not only in the result but also in the effect in the database
+        -- all the new obbects are writeen to the database on synchromization
+        -- so writeResource must not autocommit.
+        -- Commit code must be located in the postcondition. (see 'setConditions')
+    	writeResource:: a-> IO()
+
+        -- | is called syncronously. It must autocommit   
+    	delResource:: a-> IO()
+
+{- | idempotentProperty k= do
+       r <-  readResourceByKey k
+       r' <- readResourceByKey k
+       return (r == r')
+
+
+
+idempotentProperty :: (IResource a) => a -> IO Bool
+idempotentProperty x= do
+   r <-  readResourceByKey $ keyResource x
+   r' <- readResourceByKey $ keyResource x
+   return (r == r')
+
+readResource :: IResource a => a-> IO (Maybe a)
+readResource x= readResourceByKey $ keyResource x
+-}
+
+
+
+
+-- | Resources data definition used by 'withSTMResources'    
+data Resources a b
+       = Retry             -- ^ forces a retry
+       | Resources
+          { toAdd :: [a]    -- ^ resources to be inserted back in the cache
+          , toDelete :: [a] -- ^ resources to be deleted from the cache and from permanent storage
+          , toReturn :: b   -- ^ result to be returned
+          }
+
+
+-- | Empty resources: @resources= Resources  [] [] ()@
+resources :: Resources a ()
+resources =  Resources  [] [] ()
+
+
+
+
+{- | Indexable is an utility class used to derive instances of IResource
+
+Example:
+
+@data Person= Person{ pname :: String, cars :: [DBRef Car]} deriving (Show, Read, Typeable)
+data Car= Car{owner :: DBRef Person , cname:: String} deriving (Show, Read, Eq, Typeable)
+@
+
+Since Person and Car are instances of 'Read' ans 'Show', by defining the 'Indexable' instance
+will implicitly define the IResource instance for file persistence:
+
+@
+instance Indexable Person where  key Person{pname=n} = \"Person \" ++ n
+instance Indexable Car where key Car{cname= n} = \"Car \" ++ n
+@
+-}
+class Indexable a where
+    key:: a -> String
+    defPath :: a -> String       -- ^ additional extension for default file paths.
+                                -- The default value is "data/".
+
+                                -- IMPORTANT:  defPath must depend on the datatype, not the value (must be constant). Default is "TCacheData/"
+    defPath =  const "TCacheData/"
+
+--instance IResource a => Indexable a where
+--   key x= keyResource x
+
+{- | Serialize is an abstract serialization ionterface in order to define implicit instances of IResource.
+The deserialization must be as lazy as possible if deserialized objects contain DBRefs,
+lazy deserialization avoid unnecesary DBRef instantiations when they are not accessed,
+since DBRefs instantiations involve extra cache lookups
+For this reason serialization/deserialization is to/from ordinary Strings
+serialization/deserialization are not performance critical in TCache
+-}
+class Serializable a where
+  serialize   :: a -> String
+  deserialize :: String -> a
+
+{- | Read, Show,  instances are implicit instances of Serializable
+instance (Show a, Read a) => Serializable a where
+    serialize= show
+    deserialize= read
+-}
+
+
+defaultReadResource :: (Serializable a, Indexable a, Typeable a) =>  a -> IO (Maybe a)
+defaultReadResource x= defaultReadResourceByKey $ key x
+
+   
+castErr a= r where
+  r= case cast a of
+      Nothing -> error $ "Type error: " ++ (show $ typeOf a) ++ " does not match "++ (show $ typeOf r)
+                          ++ "\nThis means that objects of these two types have the same key \nor the retrieved object type is not the stored one for the same key\n"
+      Just x  -> x
+
+
+defaultReadResourceByKey :: (Serializable a, Indexable a) =>  String-> IO (Maybe a)
+defaultReadResourceByKey k= iox
+     where
+     iox = handle handler $ do   
+             s <-  readFileStrict  filename :: IO String 
+             return $ Just (deserialize s )                                                         -- `debug` ("read "++ filename)
+     
+     filename=  defPathIO iox  ++ k
+
+     defPathIO ::(Serializable a, Indexable a)=> IO (Maybe a) -> String
+     defPathIO iox= defPath x
+       where
+       Just x= unsafePerformIO $ (return $ Just undefined)  `asTypeOf`  iox
+
+ 
+     handler :: (Serializable a, Indexable a) =>   IOError ->  IO (Maybe a)
+     handler  e
+      | isAlreadyInUseError e = defaultReadResourceByKey  k                         
+      | isDoesNotExistError e = return Nothing
+      | otherwise= if ("invalid" `isInfixOf` ioeGetErrorString e)
+         then
+            error $ ( "readResource: " ++ show e) ++ " defPath and/or keyResource are not suitable for a file path"
+              
+         else defaultReadResourceByKey  k
+
+
+defaultWriteResource :: (Serializable a, Indexable a) => a-> IO()
+defaultWriteResource x= safeWrite filename (serialize x)   --  `debug` ("write "++filename)
+  where
+  filename= defPath x ++ key x
+
+safeWrite filename str= handle  handler  $ writeFile filename str
+     where          
+     handler  (e :: IOError)
+       | isDoesNotExistError e=do 
+                  createDirectoryIfMissing True $ take (1+(last $ elemIndices '/' filename)) filename   --maybe the path does not exist
+                  safeWrite filename str               
+
+       | otherwise =do
+                --phPutStrLn stderr $ "defaultWriteResource:  " ++ show e ++  " in file: " ++ filename ++ " retrying"
+                safeWrite filename str
+              
+defaultDelResource :: (Indexable a) => a -> IO()
+defaultDelResource x=  handle (handler filename) $ removeFile filename  --`debug` ("delete "++filename)
+     where
+     filename= defPath x ++ key x
+     handler :: String -> IOError -> IO ()
+     handler file e
+       | isDoesNotExistError e= return ()
+       | isAlreadyInUseError e= do
+            --hPutStrLn stderr $ "defaultDelResource: busy"  ++  " in file: " ++ filename ++ " retrying"
+            threadDelay 1000000
+            defaultDelResource x   
+       | otherwise = do
+           --hPutStrLn stderr $ "defaultDelResource:  " ++ show e ++  " in file: " ++ filename ++ " retrying"
+           threadDelay 1000000
+           defaultDelResource x
+
+
+
+
+-- Strict read from file, needed for default file persistence
+readFileStrict f = openFile f ReadMode >>= \ h -> readIt h `finally` hClose h
+  where
+  readIt h= do
+      s   <- hFileSize h
+      let n= fromIntegral s
+      str <- replicateM n (hGetChar h) 
+      return str
+    
+
diff --git a/Data/TCache/Triggers.hs b/Data/TCache/Triggers.hs
new file mode 100644
--- /dev/null
+++ b/Data/TCache/Triggers.hs
@@ -0,0 +1,70 @@
+
+
+{-# LANGUAGE ExistentialQuantification, DeriveDataTypeable, BangPatterns #-}
+module Data.TCache.Triggers(DBRef(..),Elem(..),Status(..),addTrigger,applyTriggers) where
+import Data.TCache.IResource
+import Data.TCache.Defs
+import Data.Typeable
+import Data.IORef
+import System.IO.Unsafe
+import Unsafe.Coerce
+import GHC.Conc (STM, unsafeIOToSTM)
+import Data.Maybe(maybeToList,catMaybes)
+import Data.List(nubBy)
+import Control.Concurrent.STM
+
+import Debug.Trace
+import Data.Maybe(fromJust)
+
+newtype  TriggerType a= TriggerType (DBRef a -> Maybe a -> STM()) deriving Typeable
+
+data CMTrigger= forall a.(IResource a, Typeable a) => CMTrigger  !((DBRef a) -> Maybe a -> STM())
+
+
+
+cmtriggers :: IORef [(TypeRep ,[CMTrigger])]
+cmtriggers= unsafePerformIO $ newIORef []
+
+
+
+{- | Add an user defined trigger to the list of triggers
+Trriggers are called just before an object of the given type is created, modified or deleted.
+The DBRef to the object and the new value is passed to the trigger.
+The called trigger function has two parameters: the DBRef being accesed
+(which still contains the old value), and the new value.
+If the content of the DBRef is being deleted, the second parameter is 'Nothing'.
+if the DBRef contains Nothing, then the object is being created
+-}
+addTrigger :: (IResource a, Typeable a) =>     ((DBRef a) -> Maybe a -> STM()) -> IO()
+addTrigger   t= do
+   map <-  readIORef cmtriggers
+   writeIORef cmtriggers $
+      let ts = mbToList $ lookup atype map
+          in  nubByType $ (atype ,CMTrigger t : ts) : map
+  where
+  nubByType= nubBy (\(t,_)(t',_) -> t==t')
+  (_,(atype:_))= splitTyConApp  . typeOf $ TriggerType t
+
+
+
+mbToList mxs= case mxs of Nothing -> []; Just xs -> xs
+
+applyTriggers:: (IResource a, Typeable a) => [DBRef a] -> [Maybe a] -> STM()
+applyTriggers  [] _ = return()
+applyTriggers  dbrfs mas = do
+   map <- unsafeIOToSTM $ readIORef cmtriggers
+   let ts = mbToList $ lookup   (typeOf $ fromJust (head mas)) map
+   mapM_ f  ts
+
+   where
+   f t= mapM2_ (f1 t)  dbrfs  mas
+
+   f1 ::(IResource a, Typeable a) =>  CMTrigger -> DBRef a -> Maybe a ->  STM()
+   f1 (CMTrigger t) dbref ma =    (unsafeCoerce t)  dbref ma
+
+
+
+mapM2_ _ [] _= return()
+mapM2_ f (x:xs) (y:ys)=  f x y >> mapM2_ f xs ys
+
+
diff --git a/TCache.cabal b/TCache.cabal
--- a/TCache.cabal
+++ b/TCache.cabal
@@ -1,5 +1,5 @@
 name:                TCache
-version:             0.8.0
+version:             0.8.0.1
 synopsis:            Data caching and Persistent STM transactions
 description:
 
@@ -47,5 +47,7 @@
 build-Depends:       base >=4 && <5,directory >= 1.0, old-time >=1.0,stm>=2, containers >= 0.1.0.1,  transformers >=0.2 && <0.3
 
 
-exposed-modules:   Data.TCache, Data.TCache.FilePersistence, Data.TCache.IndexQuery
+exposed-modules:   Data.TCache, Data.TCache.FilePersistence
+                   , Data.TCache.IndexQuery, Data.TCache.Triggers
+                   , Data.TCache.IResource, Data.TCache.Defs
 ghc-options:       -O2
