Skip to content

Commit

Permalink
Cleaned it up and started to bring it up to date
Browse files Browse the repository at this point in the history
- removed various data cache directories
- converted files with mixed tabs/spaces
- removed trailing and empy line whitespace
- added a .gitignore file
- added a simple stack.yaml
- added a simple script to build the demos
- added a script to cleanup .tcachedata folders
- Demos compile with Stack lts-13.x / GHC 8.6.4
  - remmoved deprecated language extensions (no code changes)
  - blindly "fixed" one demo which had no main.
  - made DBRef.hs compile
  - made DynamicSample.hs compile
  • Loading branch information
oderwat committed Apr 4, 2019
1 parent fe49c7a commit b37317c
Show file tree
Hide file tree
Showing 236 changed files with 200 additions and 340 deletions.
6 changes: 6 additions & 0 deletions .gitignore
@@ -0,0 +1,6 @@
.tcachedata
.stack-work
*.hi
*.o
demos/bin/*
demos/.build
5 changes: 2 additions & 3 deletions Data/Persistent/IDynamic.hs
@@ -1,5 +1,4 @@
{-# OPTIONS -XExistentialQuantification
-XOverlappingInstances
-XUndecidableInstances
-XScopedTypeVariables
-XDeriveDataTypeable
Expand Down Expand Up @@ -121,14 +120,14 @@ serializedEqual (IDyn r) str= unsafePerformIO $ do
case t of
DRight x -> return $ runW (showp x) == str -- !> ("R "++ (show $ unpack $ runW (showp x)))
DLeft (str', _) -> return $ str== str' -- !> ("L "++ (show $ unpack str' ))

fromIDyn :: (Typeable a , Serialize a)=> IDynamic -> a
fromIDyn x= case safeFromIDyn x of
Left s -> error s
Right v -> v


safeFromIDyn :: (Typeable a, Serialize a) => IDynamic -> Either String a
safeFromIDyn :: (Typeable a, Serialize a) => IDynamic -> Either String a
safeFromIDyn (d@(IDyn r))= final where
final= unsafePerformIO $ do
t <- readIORef r
Expand Down
76 changes: 38 additions & 38 deletions Data/TCache.hs
Expand Up @@ -713,7 +713,7 @@ getResource r= do{mr<- getResources [r];return $! head mr}
getResources:: (IResource a, Typeable a)=>[a]-> IO [Maybe a]
getResources rs= atomically $ withSTMResources rs f1 where
f1 mrs= Resources [] [] mrs


-- | Delete the resource from cache and from persistent storage.
--
Expand Down Expand Up @@ -781,33 +781,33 @@ releaseTPVars rs cache = mapM_ (releaseTPVar cache) rs

releaseTPVar :: (IResource a,Typeable a)=> Ht -> a -> STM ()
releaseTPVar cache r =do
c <- unsafeIOToSTM $ H.lookup cache keyr
case c of
Just (CacheElem _ w) -> do
mr <- unsafeIOToSTM $ deRefWeak w
case mr of
Nothing -> unsafeIOToSTM (finalize w) >> releaseTPVar cache r
Just dbref@(DBRef key tv) -> do
applyTriggers [dbref] [Just (castErr r)]
c <- unsafeIOToSTM $ H.lookup cache keyr
case c of
Just (CacheElem _ w) -> do
mr <- unsafeIOToSTM $ deRefWeak w
case mr of
Nothing -> unsafeIOToSTM (finalize w) >> releaseTPVar cache r
Just dbref@(DBRef key tv) -> do
applyTriggers [dbref] [Just (castErr r)]
t <- unsafeIOToSTM timeInteger
writeTVar tv . Exist $ Elem (castErr r) t t

writeTVar tv . Exist $ Elem (castErr r) t t


Nothing -> do
ti <- unsafeIOToSTM timeInteger
tvr <- newTVar NotRead
dbref <- unsafeIOToSTM . evaluate $ DBRef keyr tvr
applyTriggers [dbref] [Just r]
writeTVar tvr . Exist $ Elem r ti ti
w <- unsafeIOToSTM . mkWeakPtr dbref $ Just $ fixToCache dbref
unsafeIOToSTM $ H.insert cache keyr (CacheElem (Just dbref) w)-- accesed and modified XXX
return ()


where keyr= keyResource r

Nothing -> do
ti <- unsafeIOToSTM timeInteger
tvr <- newTVar NotRead
dbref <- unsafeIOToSTM . evaluate $ DBRef keyr tvr
applyTriggers [dbref] [Just r]
writeTVar tvr . Exist $ Elem r ti ti
w <- unsafeIOToSTM . mkWeakPtr dbref $ Just $ fixToCache dbref
unsafeIOToSTM $ H.insert cache keyr (CacheElem (Just dbref) w)-- accesed and modified XXX
return ()


where keyr= keyResource r




delListFromHash :: IResource a => Ht -> [a] -> STM ()
delListFromHash cache xs= mapM_ del xs
Expand All @@ -829,7 +829,7 @@ delListFromHash cache xs= mapM_ del xs


updateListToHash hash kv= mapM (update1 hash) kv where
update1 h (k,v)= H.insert h k v
update1 h (k,v)= H.insert h k v



Expand All @@ -847,8 +847,8 @@ clearSyncCacheProc time check sizeObjects= forkIO clear
clear = do
threadDelay $ time * 1000000
handle ( \ (e :: SomeException)-> hPutStr stderr (show e) >> clear ) $ do
clearSyncCache check sizeObjects -- !> "CLEAR"
clear
clearSyncCache check sizeObjects -- !> "CLEAR"
clear

criticalSection mv f= bracket
(takeMVar mv)
Expand Down Expand Up @@ -932,7 +932,7 @@ clearSyncCache check sizeObjects= criticalSection saving $ do

-- delete elems from the cache according with the checking criteria
filtercache t cache lastSync elems= mapM_ filter elems
where
where
filter (CacheElem Nothing w)= return() --alive because the dbref is being referenced elsewere
filter (CacheElem (Just (DBRef key _)) w) = do
mr <- deRefWeak w
Expand All @@ -941,13 +941,13 @@ clearSyncCache check sizeObjects= criticalSection saving $ do
Just (DBRef _ tv) -> atomically $ do
r <- readTVar tv
case r of
Exist (Elem x lastAccess _ ) ->
if check t lastAccess lastSync
then do
Exist (Elem x lastAccess _ ) ->
if check t lastAccess lastSync
then do
unsafeIOToSTM . H.insert cache key $ CacheElem Nothing w
writeTVar tv NotRead
else return ()
_ -> return()
else return ()
_ -> return()



Expand All @@ -962,8 +962,8 @@ defaultCheck
-> Integer -- ^ last cache syncronization (with the persisten storage)
-> Bool -- ^ return true for all the elems not accesed since half the time between now and the last sync
defaultCheck now lastAccess lastSync
| lastAccess > halftime = False
| otherwise = True
| lastAccess > halftime = False
| otherwise = True

where
halftime= now- (now-lastSync) `div` 2
Expand Down Expand Up @@ -1002,9 +1002,9 @@ extract elems lastSave= filter1 [] [] (0:: Int) elems
r <- readTVar tvr
case r of
Exist (Elem r _ modTime) ->
if (modTime >= lastSave)
then filter1 (Filtered r:sav) tofilter (n+1) rest
else filter1 sav tofilter (n+1) rest -- !> ("rejected->" ++ keyResource r)
if (modTime >= lastSave)
then filter1 (Filtered r:sav) tofilter (n+1) rest
else filter1 sav tofilter (n+1) rest -- !> ("rejected->" ++ keyResource r)

_ -> filter1 sav tofilter (n+1) rest

Expand Down
68 changes: 34 additions & 34 deletions Data/TCache/IResource.hs
Expand Up @@ -16,23 +16,23 @@ import Data.List(isInfixOf)

{- | Must be defined for every object to be cached.
-}
class IResource a where
{- The `keyResource string must be a unique since this is used to index it in the hash table.
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

Expand All @@ -55,29 +55,29 @@ class IResource a where
readResource :: a -> IO (Maybe a)
readResource x = readResourceByKey $ keyResource x

-- | To write into persistent storage. It must be strict.
-- | To write into 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.
-- . However, because it is executed by 'safeIOToSTM' it is guaranteed that the execution is not interrupted.
-- 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`)
-- Since there is no provision for rollback from failure in writing to
-- persistent storage, 'writeResource' must retry until success.
writeResource:: a-> IO()
writeResource r= writeResources [r]
-- | multiple write (hopefully) in a single request. That is up to you and your backend
-- . Defined by default as 'mapM_ writeResource'
writeResources :: [a] -> IO()
writeResources= mapM_ writeResource

-- | Delete the resource. It is called syncronously. So it must commit
delResource:: a-> IO()
delResource x= delResources [x]
writeResource:: a-> IO()
writeResource r= writeResources [r]

-- | multiple write (hopefully) in a single request. That is up to you and your backend
-- . Defined by default as 'mapM_ writeResource'
writeResources :: [a] -> IO()
writeResources= mapM_ writeResource

-- | Delete the resource. It is called syncronously. So it must commit
delResource:: a-> IO()
delResource x= delResources [x]

delResources :: [a] -> IO()
delResources= mapM_ delResource
-- | Resources data definition used by 'withSTMResources'
-- | Resources data definition used by 'withSTMResources'
data Resources a b
= Retry -- ^ forces a retry
| Resources
Expand Down Expand Up @@ -145,26 +145,26 @@ defaultReadResource x= defaultReadResourceByKey $ key x
defaultReadResourceByKey :: (Serializable a, Indexable a) => String-> IO (Maybe a)
defaultReadResourceByKey k= iox
where
iox = handle handler $ do
s <- readFileStrict filename :: IO String
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
| 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
Expand All @@ -174,16 +174,16 @@ defaultWriteResource x= safeWrite filename (serialize x) -- `debug` ("write "
filename= defPath x ++ key x
safeWrite filename str= handle handler $ writeFile filename str
where
where
handler (e :: IOError)
| isDoesNotExistError e=do
| isDoesNotExistError e=do
createDirectoryIfMissing True $ take (1+(last $ elemIndices '/' filename)) filename --maybe the path does not exist
safeWrite filename str
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
Expand All @@ -194,7 +194,7 @@ defaultDelResource x= handle (handler filename) $ removeFile filename --`debug
| isAlreadyInUseError e= do
--hPutStrLn stderr $ "defaultDelResource: busy" ++ " in file: " ++ filename ++ " retrying"
threadDelay 1000000
defaultDelResource x
defaultDelResource x
| otherwise = do
--hPutStrLn stderr $ "defaultDelResource: " ++ show e ++ " in file: " ++ filename ++ " retrying"
threadDelay 1000000
Expand All @@ -209,9 +209,9 @@ readFileStrict f = openFile f ReadMode >>= \ h -> readIt h `finally` hClose h
readIt h= do
s <- hFileSize h
let n= fromIntegral s
str <- replicateM n (hGetChar h)
str <- replicateM n (hGetChar h)
return str
newtype Transient a= Transient a
Expand Down
2 changes: 1 addition & 1 deletion Data/TCache/IndexQuery.hs
Expand Up @@ -71,7 +71,7 @@ fields in a registers are to be indexed, they must have different types.

{-# LANGUAGE DeriveDataTypeable, MultiParamTypeClasses
, FunctionalDependencies, FlexibleInstances, UndecidableInstances
, TypeSynonymInstances, IncoherentInstances, OverlappingInstances #-}
, TypeSynonymInstances, IncoherentInstances #-}
module Data.TCache.IndexQuery(
index
, (.==.)
Expand Down
2 changes: 1 addition & 1 deletion TCache.cabal
Expand Up @@ -78,7 +78,7 @@ library

exposed: True
buildable: True
extensions: OverlappingInstances UndecidableInstances
extensions: UndecidableInstances
ScopedTypeVariables DeriveDataTypeable
hs-source-dirs: .
other-modules:
Expand Down
1 change: 0 additions & 1 deletion TCacheData - copia/Queue#boss1

This file was deleted.

1 change: 0 additions & 1 deletion TCacheData - copia/Queue#boss2

This file was deleted.

1 change: 0 additions & 1 deletion TCacheData/I54321

This file was deleted.

1 change: 0 additions & 1 deletion TCacheData/Queue#boss1

This file was deleted.

1 change: 0 additions & 1 deletion TCacheData/Queue#boss2

This file was deleted.

1 change: 0 additions & 1 deletion TCacheData/U12345

This file was deleted.

16 changes: 16 additions & 0 deletions buildDemos.sh
@@ -0,0 +1,16 @@
#!/bin/bash

# This is a crude way to build all the demo files placing them into the
# demos/bin folder and removing the build artifacts afterwards

rm -rf ./demos/.build
rm -rf ./demos/bin/*

for fullfile in ./demos/*.hs; do
filename=$(basename -- "$fullfile")
binname="${filename%.*}"
echo "$filename -> $binname"
stack exec ghc -- -outputdir demos/.build $fullfile -o demos/bin/$binname
done

rm -rf ./demos/.build
1 change: 0 additions & 1 deletion cacheData/1

This file was deleted.

1 change: 0 additions & 1 deletion cacheData/10

This file was deleted.

1 change: 0 additions & 1 deletion cacheData/100

This file was deleted.

1 change: 0 additions & 1 deletion cacheData/101

This file was deleted.

1 change: 0 additions & 1 deletion cacheData/102

This file was deleted.

1 change: 0 additions & 1 deletion cacheData/103

This file was deleted.

1 change: 0 additions & 1 deletion cacheData/104

This file was deleted.

1 change: 0 additions & 1 deletion cacheData/105

This file was deleted.

1 change: 0 additions & 1 deletion cacheData/106

This file was deleted.

0 comments on commit b37317c

Please sign in to comment.