glean/hs/Glean/RTS/Foreign/FactSet.hs (142 lines of code) (raw):
{-
Copyright (c) Meta Platforms, Inc. and affiliates.
All rights reserved.
This source code is licensed under the BSD-style license found in the
LICENSE file in the root directory of this source tree.
-}
module Glean.RTS.Foreign.FactSet
( FactSet
, new
, factMemory
, firstFreeId
, serialize
, serializeReorder
, append
, rebase
, renameFacts
) where
import Control.Exception
import Data.Int
import Data.Vector.Storable as Vector
import Foreign.C.String
import Foreign.C.Types
import Foreign.ForeignPtr
import Foreign.Ptr
import Util.FFI
import Glean.FFI
import Glean.RTS.Foreign.Define
import Glean.RTS.Foreign.Inventory (Inventory)
import Glean.RTS.Foreign.Lookup (Lookup(..), CanLookup(..))
import Glean.RTS.Foreign.LookupCache (LookupCache)
import Glean.RTS.Foreign.Stacked (stacked)
import Glean.RTS.Foreign.Subst (Subst)
import Glean.RTS.Types (Fid(..))
import qualified Glean.Types as Thrift
-- An environment for defining facts
newtype FactSet = FactSet (ForeignPtr FactSet)
instance Object FactSet where
wrap = FactSet
unwrap (FactSet p) = p
destroy = glean_factset_free
instance CanLookup FactSet where
lookupName _ = "factset"
withLookup x f = with x $ f . glean_factset_lookup
instance CanDefine FactSet where
withDefine x f = with x $ f . glean_factset_define
new :: Fid -> IO FactSet
new next_id = construct $ invoke $ glean_factset_new next_id
factMemory :: FactSet -> IO Int
factMemory facts = fromIntegral <$> with facts glean_factset_fact_memory
firstFreeId :: FactSet -> IO Fid
firstFreeId facts = with facts glean_factset_first_free_id
mkBatch :: IO (Fid, CSize, Ptr (), CSize) -> IO Thrift.Batch
mkBatch fn = mask_ $ do
(Fid first_id, count, facts_data, facts_size) <- fn
Thrift.Batch first_id (fromIntegral count)
<$> unsafeMallocedByteString facts_data facts_size
<*> pure Nothing
<*> pure mempty
serialize :: FactSet -> IO Thrift.Batch
serialize facts =
with facts $ \facts_ptr -> do
mkBatch $ invoke $ glean_factset_serialize facts_ptr
serializeReorder :: FactSet -> Vector Int64 -> IO Thrift.Batch
serializeReorder facts order =
with facts $ \facts_ptr -> do
unsafeWith order $ \order_ptr -> do
mkBatch $ invoke $ glean_factset_serializeReorder
facts_ptr
order_ptr
(fromIntegral (Vector.length order))
rebase :: Inventory -> Thrift.Subst -> LookupCache -> FactSet -> IO FactSet
rebase inventory Thrift.Subst{..} cache facts =
with inventory $ \inventory_ptr ->
unsafeWith subst_ids $ \ids_ptr ->
with cache $ \cache_ptr ->
with facts $ \facts_ptr ->
construct $ invoke $
glean_factset_rebase
facts_ptr
inventory_ptr
(Fid subst_firstId)
(fromIntegral $ Vector.length subst_ids)
ids_ptr
cache_ptr
append :: FactSet -> FactSet -> IO ()
append target source =
with target $ \target_ptr ->
with source $ \source_ptr ->
invoke $ glean_factset_append target_ptr source_ptr
-- Prepare a Thrift batch for writing into the database by renaming and
-- deduplicating facts.
renameFacts
:: CanLookup l
=> Inventory -- ^ where to lookup predicates
-> l -- ^ where to lookup facts
-> Fid -- ^ first free fact id in the database
-> Thrift.Batch -- ^ batch to rename
-> IO (FactSet, Subst)
-- ^ resulting facts and substitution
renameFacts inventory base next batch = do
added <- new next
subst <- defineUntrustedBatch (stacked base added) inventory batch
return (added, subst)
foreign import ccall unsafe glean_factset_new
:: Fid -> Ptr (Ptr FactSet) -> IO CString
foreign import ccall unsafe "&glean_factset_free" glean_factset_free
:: FunPtr (Ptr FactSet -> IO ())
foreign import ccall unsafe glean_factset_fact_memory
:: Ptr FactSet -> IO CSize
foreign import ccall unsafe glean_factset_first_free_id
:: Ptr FactSet -> IO Fid
foreign import ccall unsafe glean_factset_lookup
:: Ptr FactSet -> Ptr Lookup
foreign import ccall unsafe glean_factset_define
:: Ptr FactSet -> Define
foreign import ccall unsafe glean_factset_serialize
:: Ptr FactSet
-> Ptr Fid
-> Ptr CSize
-> Ptr (Ptr ())
-> Ptr CSize
-> IO CString
foreign import ccall unsafe glean_factset_serializeReorder
:: Ptr FactSet
-> Ptr Int64
-> CSize
-> Ptr Fid
-> Ptr CSize
-> Ptr (Ptr ())
-> Ptr CSize
-> IO CString
foreign import ccall unsafe glean_factset_rebase
:: Ptr FactSet
-> Ptr Inventory
-> Fid
-> CSize
-> Ptr Int64
-> Ptr LookupCache
-> Ptr (Ptr FactSet)
-> IO CString
foreign import ccall unsafe glean_factset_append
:: Ptr FactSet -> Ptr FactSet -> IO CString