----------------------------------------------------------------------------- -- | -- Module : Database.ETS -- Copyright : (c) 2020-2021 EMQ Technologies Co., Ltd. -- License : BSD-style (see the LICENSE file) -- -- Maintainer : Feng Lee, feng@emqx.io -- Yang M, yangm@emqx.io -- Stability : experimental -- Portability : portable -- -- The Erlang ETS Database. -- ----------------------------------------------------------------------------- module Database.ETS where import Control.Monad (IO) import Data.Pid (Pid) import Data.Maybe (Maybe(..)) import Data.Ref (Reference) import Data.Term (Term) import Data.Unit (Unit) import System.IO (FilePath) import Foreign (ffiIO0, ffiIO1, ffiIO2, ffiIO3, ffiIO4) -- | Table name is an Atom. type TableName = Atom -- TableId Reference | TableName Atom foreign import data TableId :: Type data TableAccess = Public | Protected | Private data TableType = Set | OrderedSet | Bag | DuplicateBag type TableOptions = { tableType :: TableType , access :: TableAccess , namedTable :: Boolean , keyPos :: Integer , heir :: Maybe (Pid, Term) , compressed :: Boolean , readConcurrency :: Boolean , writeConcurrency :: Boolean --, decentralizedCounters :: Boolean } type TableInfo = { id :: Reference , name :: Atom , size :: Integer , node :: Atom , memory :: Integer , owner :: Pid , heir :: Maybe Pid , tableType :: TableType , namedTable :: Boolean , keypos :: Integer , protection :: TableAccess , compressed :: Boolean , readConcurrency :: Boolean , writeConcurrency :: Boolean --, decentralizedCounters :: Boolean } options :: TableOptions options = { tableType = Set , access = Protected , namedTable = true , keyPos = 1 , heir = Nothing , compressed = false , readConcurrency = false , writeConcurrency = false } all :: IO [TableId] all = ffiIO0 :ets :all -- | Displays information about all ETS tables on a terminal. browse :: IO String browse = ffiIO0 :ets :i -- | Browses table Tab on a terminal. -- browseTable :: TableId -> IO String browseTable :: TableId -> IO String browseTable = ffiIO1 :ets :i -- | Delete the entire table. deleteTable :: TableId -> IO () deleteTable = ffiIO1 :ets :delete -- | Delete a record. delete :: forall k. TableId -> k -> IO () delete = ffiIO2 :ets :delete -- | Delete all records of a table. deleteAllObjects :: TableId -> IO () deleteAllObjects = ffiIO1 :ets :delete_all_objects deleteObject :: forall o. TableId -> o -> IO () deleteObject = ffiIO2 :ets :delete_object foreign import file2tab :: FilePath -> IO TableId foreign import file2tabWithVerify :: FilePath -> IO TableId foreign import first :: TableId -> forall k. IO (Maybe k) foreign import foldl :: forall v acc. (v -> acc -> acc) -> acc -> TableId -> IO acc foreign import foldr :: forall v acc. (v -> acc -> acc) -> acc -> TableId -> IO acc fromDETS :: TableId -> TableName -> IO () fromDETS = ffiIO2 :ets :from_dets -- foreign import data MatchSpec :: Type -- fun2ms :: forall a. a -> MatchSpec -- fun2ms = ffi1 :ets :fun2ms giveAway :: forall a. TableId -> Pid -> a -> IO () giveAway = ffiIO3 :ets :give_away foreign import info :: TableId -> IO (Maybe TableInfo) getInfo :: forall v. TableId -> Atom -> IO v getInfo = ffiIO2 :ets :info -- TODO: init_table/2 insert :: forall v. TableId -> v -> IO Boolean insert = ffiIO2 :ets :insert insertObjects :: forall v. TableId -> [v] -> IO Boolean insertObjects = ffiIO2 :ets :insert insertNew :: forall v. TableId -> v -> IO Boolean insertNew = ffiIO2 :ets :insert_new insertNewObjects :: forall v. TableId -> [v] -> IO Boolean insertNewObjects = ffiIO2 :ets :insert_new foreign import last :: forall k. TableId -> IO (Maybe k) lookup :: forall k v. TableId -> k -> IO [v] lookup = ffiIO2 :ets :lookup lookupElement :: forall k v. TableId -> k -> Integer -> IO v lookupElement = ffiIO3 :ets :lookup_element member :: forall k. TableId -> k -> IO Boolean member = ffiIO2 :ets :member -- | Creates a new table. foreign import new :: Atom -> TableOptions -> IO TableId foreign import next :: forall k. TableId -> k -> IO (Maybe k) foreign import prev :: forall k. TableId -> k -> IO (Maybe k) rename :: TableId -> Atom -> IO Atom rename = ffiIO2 :ets :rename foreign import tab2file :: TableId -> FilePath -> IO () tab2list :: forall v. TableId -> IO [v] tab2list = ffiIO1 :ets :tab2list take :: forall k v. TableId -> k -> IO [v] take = ffiIO2 :ets :take toDETS :: TableId -> Atom -> IO Atom toDETS = ffiIO2 :ets :to_dets whereis :: Atom -> IO TableId whereis = ffiIO1 :ets :whereis match :: forall a v. TableId -> a -> IO [v] match = ffiIO2 :ets :match foreign import data Continuation :: Type foreign import matchContinuation :: forall v. Continuation -> IO (Maybe ([v], Continuation)) foreign import matchWithLimit :: forall a v. TableId -> a -> Integer -> IO (Maybe ([v], Continuation)) matchDelete :: forall a. TableId -> a -> IO Boolean matchDelete = ffiIO2 :ets :match_delete matchObject :: forall a v. TableId -> a -> IO [v] matchObject = ffiIO2 :ets :match_object foreign import matchObjectContinuation :: forall v. Continuation -> IO (Maybe ([v], Continuation)) foreign import matchObjectWithLimit :: forall a v. TableId -> a -> Integer -> IO (Maybe ([v], Continuation)) safeFixtable :: TableId -> Boolean -> IO Boolean safeFixtable = ffiIO2 :ets :safe_fixtable foreign import slot :: forall v. TableId -> Integer -> IO (Maybe [v]) foreign import tabfileInfo :: FilePath -> IO TableInfo foreign import updateElement :: forall k v. TableId -> k -> Integer -> v -> IO Boolean updateElementList :: forall k v. TableId -> k -> [(Integer, v)] -> IO Boolean updateElementList = ffiIO3 :ets :update_element updateCounter :: forall k. TableId -> k -> (Integer, Integer) -> IO Integer updateCounter = ffiIO3 :ets :update_counter updateCounterWithThreshold :: forall k. TableId -> k -> (Integer, Integer, Integer, Integer) -> IO Integer updateCounterWithThreshold = ffiIO3 :ets :update_counter updateCounterWithDefault :: forall k a. TableId -> k -> (Integer, Integer) -> a -> IO Integer updateCounterWithDefault = ffiIO4 :ets :update_counter updateCounterIncr :: forall k. TableId -> k -> Integer -> IO Integer updateCounterIncr = ffiIO3 :ets :update_counter updateCounterIncrWithDefault :: forall k a. TableId -> k -> Integer -> a -> IO Integer updateCounterIncrWithDefault = ffiIO4 :ets :update_counter {- TODO: is_compiled_ms/1 match_spec_compile/1 match_spec_run/2 repair_continuation/2 select/1 select/2 select/3 select_count/2 select_delete/2 select_replace/2 select_reverse/1 select_reverse/2 select_reverse/3 setopts/2 tab2file/3 table/1 table/2 test_ms/2 -}