-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Transparently swapping data from in-memory structures to disk -- -- This package provides a wrapper for functors, which allows their data -- to be automatically swapped to disk and loaded back when necessary. -- Although interaction with filesystem is required, whole interface -- (with exception of initialization) is pure and safe as long as no -- external manipulation with used database files happens while the -- program is running. Because only actual data, not indices (in -- Data.Map.Map, for example), are swapped and some accounting -- information are remembered for each item, this system is suitable -- mainly for situations where values are considerably larger then -- indices. Furthermore, creating complete snapshots to a file of this -- structure is supported; such snapshot can be then loaded, with -- individual values being read as they are requested. This package uses -- the Tokyo Cabinet http://fallabs.com/tokyocabinet/ database, -- which needs to be installed on the system. A prototype of another data -- structure, SwapMap, is available in the git repository. It is similar -- to the Data.Map.Map and like Swapper allows transparent swapping of -- data to disk, but without requiring any accessory function and with -- the ability to swap both elements and indices. This one is, however, -- not complete and thus not provided here. @package swapper @version 0.1 -- | Snapshot is a type class generalizing Serialize, as it, -- apart from writing values in the Put monad (or reading in -- Get), allows to perform arbitrary IO actions, like -- saving data to (or loading from) some external database files. Any -- instance of Serialize is also trivially an instance of -- Snapshot. module Data.Disk.Swapper.Snapshot class (Typeable a, Version a) => Snapshot a getFromSnapshot :: Snapshot a => Get (IO a) putToSnapshot :: Snapshot a => a -> IO Put instance [overlap ok] Serialize a => Snapshot a -- | Here is provided a Cache type class designed to generalize -- notion of cache currently used in Swapper. module Data.Disk.Swapper.Cache -- | First parameter of this class is actual cache type, the second is type -- of cached values. The cache should just hold an reference to those -- values that are meant to be kept in memory. class Cache a v | a -> v addValue :: Cache a v => a -> v -> IO (IO ()) -- | Version of addValue, which works with a cache in IORef. addValueRef :: Cache a v => IORef a -> v -> IO (IO ()) data SomeCache v SomeCache :: !c -> SomeCache v -- | Provides standard clock cache with second chance mechanism. data ClockCache a ClockCache :: Int -> MVar [(IORef a, IORef Bool)] -> ClockCache a ccSize :: ClockCache a -> Int ccData :: ClockCache a -> MVar [(IORef a, IORef Bool)] mkClockCache :: Int -> IO (ClockCache a) -- | NullCache does not cache any values data NullCache a NullCache :: NullCache a nullCache :: SomeCache a instance Typeable1 ClockCache instance Cache (NullCache a) a instance Cache (ClockCache a) a instance Cache (SomeCache v) v -- | This module provides the actual wrapper around functors, which allows -- them to swap their values to disk. Before any use, original structure -- have to by turned into appropriate Swapper using function -- mkSwapper; this has to be done in IO monad. The created object -- can then be used in normal pure way, when internal side effects -- concern only database files determined by the first parameter passed -- to mkSwapper; those should not be altered externally during the -- program run. -- -- Because the Swapper is different type than the original functor, -- lifting functions are provided to allow manipulation with it. Those -- are adding for functions, which add new elements like -- : or Data.Map.insert, getting for function -- retrieving elements like head or Data.Map.lookup, -- changing for functions changing the structure itself like -- tail. Concrete examples are provided it the description of the -- aforementioned functions. -- -- When creating snapshot using putToSnapshot, all items present -- it structure are saved into the current database file (its name is -- then recorded to the snapshot itself in order to be able to load in -- future) and new one is created for items added thereafter. When the -- snapshot is loaded using getFromSnapshot, only indices and -- auxiliary data are loaded into the memory at that time; values are -- read on demand from their database file. module Data.Disk.Swapper data Swapper f a -- | Creates Swapper from given functor object. The first parameter -- is prefix from which the name of database files are derived (by -- appending their index number and database extension), those files -- should not be altered by external files when the program is running or -- between saving and loading snapshots. -- -- The Swapper initially uses the NullCache, which does not -- keep any data in memory, apart from those referenced from other -- places. mkSwapper :: (Serialize a, NFData a, Functor f) => FilePath -> f a -> IO (Swapper f a) -- | Sets cache for given Swapper object; it determines, which items -- are to be swapped onto disk, when available slots are used up (and -- also how many of such slots actually exists in the first place); can -- be shared among several Swappable objects. setCache :: Cache c a => Swapper f a -> c -> IO () -- | Analogous to the setCache, but works with Swapper -- encosed in an IORef. setCacheRef :: Cache c a => IORef (Swapper f a) -> c -> IO () -- | Lifting function used for adding new elements to the Swapper -- object. Needs to be applied to functions like : or -- Data.Map.insert for them to act on Swapper instead of the -- original structure. Requires the function in its first argument to -- work for functor containing arbitrary type. -- --
-- a :: Swapper [] Int -- let a' = adding (:) 6 a -- -- b :: Swapper (Map String) Int -- let b' = adding (insert "new") 42 b --adding :: (Serialize a, NFData a) => (forall b. b -> f b -> f b) -> (a -> Swapper f a -> Swapper f a) -- | Function used to lift functions getting elements from inner structure, -- like head or Data.Map.lookup, to functions getting -- elements from Swapper object. Functions in the first argument -- needs to work on f containing elements of arbitrary type. -- --
-- a :: Swapper [] Int -- let x = getting head a -- -- b :: Swapper (Map String) Int -- let y = getting (lookup "some") b --getting :: Serialize a => (forall b. f b -> b) -> (Swapper f a -> a) -- | This function is needed to make functions changing the structure -- somehow (like tail or Data.Map.delete), to change the -- Swapper instead. Like the previous lifting functions, its first -- argument needs to work for any values of any type. -- --
-- a :: Swapper [] Int -- let a' = changing tail a -- -- b :: Swapper (Map String) Int -- let b' = changing (delete "some") b --changing :: Serialize a => (forall b. f b -> f b) -> (Swapper f a -> Swapper f a) swapperDBPrefix :: Swapper f a -> FilePath instance (Typeable a, Version a, Serialize a, Typeable1 f, Traversable f, Snapshot (f ByteString)) => Snapshot (Swapper f a) instance Version a => Version (Swapper f a) instance (Typeable1 f, Typeable a) => Typeable (Swapper f a) instance Typeable a => Typeable (Swappable a) module Data.Disk.Swapper.HappstackCompat createSwapperCheckpoint :: MVar TxControl -> IO () instance Snapshot (Swapper f a) => Serialize (Swapper f a)