Skip to content

Commit 4f2bc90

Browse files
committed
[lmdb facebookincubator#1] Factor out a generic DB layer
1 parent 03c9387 commit 4f2bc90

20 files changed

Lines changed: 2040 additions & 1857 deletions

glean.cabal.in

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,18 @@ library rts
387387
extra-libraries: atomic
388388
pkgconfig-depends: libunwind, libglog, icu-uc, gflags, libxxhash
389389

390+
library storage
391+
import: fb-haskell, fb-cpp, deps, folly
392+
visibility: private
393+
CXX_LIB_glean_cpp_storage
394+
include-dirs: .
395+
install-includes:
396+
glean/storage/ffi.h
397+
glean/storage/db.h
398+
glean/storage/stats.h
399+
build-depends:
400+
glean:rts,
401+
390402
library rocksdb
391403
import: fb-haskell, fb-cpp, deps, folly
392404
visibility: private
@@ -400,18 +412,7 @@ library rocksdb
400412
glean/rocksdb/util.h
401413
pkgconfig-depends: rocksdb, fmt
402414
build-depends:
403-
glean:rocksdb-stats,
404-
glean:rts,
405-
406-
-- This needs to be separate from rocksdb because it can't be compiled with -fno-rtti
407-
library rocksdb-stats
408-
import: fb-haskell, fb-cpp, deps, folly
409-
visibility: private
410-
CXX_LIB_glean_cpp_rocksdb_stats
411-
include-dirs: .
412-
install-includes:
413-
glean/rocksdb/stats.h
414-
build-depends:
415+
glean:storage,
415416
glean:rts,
416417

417418
library util
@@ -596,6 +597,7 @@ library db
596597
Glean.Database.Schema.Types
597598
Glean.Database.Storage
598599
Glean.Database.Storage.Memory
600+
Glean.Database.Storage.DB
599601
Glean.Database.Storage.RocksDB
600602
Glean.Database.Trace
601603
Glean.Database.Types

glean/db/Glean/Database/Storage.hs

Lines changed: 78 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ module Glean.Database.Storage
1010
( Mode(..)
1111
, CreateSchema(..)
1212
, Storage(..)
13+
, Database
14+
, DatabaseOps(..)
1315
, DBVersion(..)
1416
, AxiomOwnership
1517
, WriteLock(..)
@@ -26,11 +28,12 @@ import Glean.Database.Backup.Backend (Data)
2628
import Glean.Internal.Types (StoredSchema)
2729
import Glean.RTS.Foreign.FactSet (FactSet)
2830
import Glean.RTS.Foreign.Inventory (Inventory)
29-
import Glean.RTS.Foreign.Lookup (CanLookup, Lookup)
30-
import Glean.RTS.Foreign.Ownership
31+
import Glean.RTS.Foreign.Lookup (CanLookup(..), Lookup)
32+
import Glean.RTS.Foreign.Ownership hiding (computeDerivedOwnership)
3133
import Glean.RTS.Types (Fid, Pid)
3234
import Glean.ServerConfig.Types (DBVersion(..))
3335
import Glean.Types (PredicateStats, Repo, SchemaId)
36+
import Glean.Util.Some
3437

3538
-- | List of binary representation versions we can read
3639
readableVersions :: [DBVersion]
@@ -76,20 +79,16 @@ type AxiomOwnership = HashMap ByteString (VS.Vector Fid)
7679
-- | Token representing the write lock
7780
data WriteLock w = WriteLock w
7881

79-
-- | An abstract storage for fact database
80-
class CanLookup (Database s) => Storage s where
81-
-- | A fact database
82-
data Database s
82+
data family Database s
8383

84+
-- | An abstract storage for fact database
85+
class DatabaseOps (Database s) => Storage s where
8486
-- | A short, user-readable description of the storage
8587
describe :: s -> String
8688

8789
-- | Open a database
8890
open :: s -> Repo -> Mode -> DBVersion -> IO (Database s)
8991

90-
-- | Close a database
91-
close :: Database s -> IO ()
92-
9392
-- | Delete a database if it exists
9493
delete :: s -> Repo -> IO ()
9594

@@ -98,57 +97,89 @@ class CanLookup (Database s) => Storage s where
9897
-- directory where the database would be stored.
9998
safeRemoveForcibly :: s -> Repo -> IO ()
10099

100+
-- | Determine the total capacity of the storage medium (e.g., disk size).
101+
getTotalCapacity :: s -> IO (Maybe Int)
102+
103+
-- | Determine the used capacity of the storage medium (e.g., how much of the
104+
-- disk is in use).
105+
getUsedCapacity :: s -> IO (Maybe Int)
106+
107+
-- | Determine the free capacity of the storage medium (e.g., how much of the
108+
-- disk is free).
109+
getFreeCapacity :: s -> IO Int
110+
111+
-- | Execute the action, passing to it a path to a scratch directory which can
112+
-- be used, e.g., for downloading databases. This directory is not guaranteed
113+
-- to persist beyond the call and is not guaranteed to be empty.
114+
withScratchRoot :: s -> (FilePath -> IO a) -> IO a
115+
116+
-- | Restore a database. The scratch directory which can be used for
117+
-- storing intermediate files is guaranteed to be empty and will be
118+
-- deleted after the operation completes. The implementation may
119+
-- delete the serialized database file after it has been consumed,
120+
-- to reduce the number of copies of the DB on disk during a restore.
121+
restore
122+
:: s -- ^ storage
123+
-> Repo -- ^ repo
124+
-> FilePath -- ^ scratch directory
125+
-> FilePath -- ^ file containing the serialiased database (produced by 'backup')
126+
-> IO ()
127+
128+
class CanLookup db => DatabaseOps db where
129+
-- | Close a database
130+
close :: db -> IO ()
131+
101132
-- | Obtain the 'PredicateStats' for each predicate
102-
predicateStats :: Database s -> IO [(Pid, PredicateStats)]
133+
predicateStats :: db -> IO [(Pid, PredicateStats)]
103134

104135
-- | Store an arbitrary binary key/value pair in the database. This data is
105136
-- completely separate from the facts.
106137
--
107138
-- NOTE: It is expected that 'store' and 'retrieve' are used sparingly and
108139
-- there are no performance guarantees. A typical use case for this is
109140
-- storing the serialised schema in the database.
110-
store :: Database s -> ByteString -> ByteString -> IO ()
141+
store :: db -> ByteString -> ByteString -> IO ()
111142

112143
-- | Retrieve the value of a key previously stored with 'store'.
113-
retrieve :: Database s -> ByteString -> IO (Maybe ByteString)
144+
retrieve :: db -> ByteString -> IO (Maybe ByteString)
114145

115146
-- | Commit a set of facts to the database. The facts must have the right ids,
116147
-- they are NOT renamed.
117-
commit :: Database s -> FactSet -> IO ()
148+
commit :: db -> FactSet -> IO ()
118149

119150
-- | Add ownership data about a set of (committed) facts.
120-
addOwnership :: Database s -> WriteLock w -> AxiomOwnership -> IO ()
151+
addOwnership :: db -> WriteLock w -> AxiomOwnership -> IO ()
121152

122153
-- | Optimise a database for reading. This is typically done before backup.
123-
optimize :: Database s -> Bool {- compact -} -> IO ()
154+
optimize :: db -> Bool {- compact -} -> IO ()
124155

125156
computeOwnership
126-
:: Database s
157+
:: db
127158
-> Maybe Lookup
128159
-- ^ Base DB lookup if this is a stacked DB, because ownership may
129160
-- need to propagate ownership through facts in the base DB.
130161
-> Inventory
131162
-> IO ComputedOwnership
132163

133-
storeOwnership :: Database s -> WriteLock w -> ComputedOwnership -> IO ()
164+
storeOwnership :: db -> WriteLock w -> ComputedOwnership -> IO ()
134165

135166
-- | Fetch the 'Ownership' interface for this DB. This is used to
136167
-- make a 'Slice' (a view of a subset of the facts in the DB).
137168
--
138169
-- Can return 'Nothing' if this database backend doesn't support
139170
-- ownership. (TODO: support ownership in the memory backend and
140171
-- remove this 'Maybe').
141-
getOwnership :: Database s -> IO (Maybe Ownership)
172+
getOwnership :: db -> IO (Maybe Ownership)
142173

143-
getUnitId :: Database s -> ByteString -> IO (Maybe UnitId)
144-
getUnit :: Database s -> UnitId -> IO (Maybe ByteString)
174+
getUnitId :: db -> ByteString -> IO (Maybe UnitId)
175+
getUnit :: db -> UnitId -> IO (Maybe ByteString)
145176

146177
-- | Called once per batch.
147-
addDefineOwnership :: Database s -> WriteLock w -> DefineOwnership -> IO ()
178+
addDefineOwnership :: db -> WriteLock w -> DefineOwnership -> IO ()
148179

149180
-- | Called once per derived predicate at the end of its derivation.
150181
computeDerivedOwnership
151-
:: Database s
182+
:: db
152183
-> WriteLock w
153184
-> Ownership
154185
-> Maybe Lookup
@@ -162,44 +193,39 @@ class CanLookup (Database s) => Storage s where
162193
-- faster getOwner() operations. Takes time to cache the data and
163194
-- memory to retain the cache. Only useful if this DB will be used
164195
-- in an incremental stack.
165-
cacheOwnership :: Database s -> IO ()
166-
167-
prepareFactOwnerCache :: Database s -> IO ()
168-
169-
-- | Determine the total capacity of the storage medium (e.g., disk size).
170-
getTotalCapacity :: s -> IO (Maybe Int)
171-
172-
-- | Determine the used capacity of the storage medium (e.g., how much of the
173-
-- disk is in use).
174-
getUsedCapacity :: s -> IO (Maybe Int)
175-
176-
-- | Determine the free capacity of the storage medium (e.g., how much of the
177-
-- disk is free).
178-
getFreeCapacity :: s -> IO Int
196+
cacheOwnership :: db -> IO ()
179197

180-
-- | Execute the action, passing to it a path to a scratch directory which can
181-
-- be used, e.g., for downloading databases. This directory is not guaranteed
182-
-- to persist beyond the call and is not guaranteed to be empty.
183-
withScratchRoot :: s -> (FilePath -> IO a) -> IO a
198+
prepareFactOwnerCache :: db -> IO ()
184199

185200
-- | Backup a database. The scratch directory which can be used for storing
186201
-- intermediate files is guaranteed to be empty and will be deleted after
187202
-- the operation completes.
188203
backup
189-
:: Database s -- ^ database
204+
:: db -- ^ database
190205
-> FilePath -- ^ scratch directory
191206
-> (FilePath -> Data -> IO a)
192207
-- ^ function which expects the serialised database
193208
-> IO a
194209

195-
-- | Restore a database. The scratch directory which can be used for
196-
-- storing intermediate files is guaranteed to be empty and will be
197-
-- deleted after the operation completes. The implementation may
198-
-- delete the serialized database file after it has been consumed,
199-
-- to reduce the number of copies of the DB on disk during a restore.
200-
restore
201-
:: s -- ^ storage
202-
-> Repo -- ^ repo
203-
-> FilePath -- ^ scratch directory
204-
-> FilePath -- ^ file containing the serialiased database (produced by 'backup')
205-
-> IO ()
210+
instance CanLookup (Some DatabaseOps) where
211+
withLookup (Some db) = withLookup db
212+
lookupName (Some db) = lookupName db
213+
214+
instance DatabaseOps (Some DatabaseOps) where
215+
close (Some db) = close db
216+
predicateStats (Some db) = predicateStats db
217+
store (Some db) = store db
218+
retrieve (Some db) = retrieve db
219+
commit (Some db) = commit db
220+
addOwnership (Some db) = addOwnership db
221+
optimize (Some db) = optimize db
222+
computeOwnership (Some db) = computeOwnership db
223+
storeOwnership (Some db) = storeOwnership db
224+
getOwnership (Some db) = getOwnership db
225+
getUnitId (Some db) = getUnitId db
226+
getUnit (Some db) = getUnit db
227+
addDefineOwnership (Some db) = addDefineOwnership db
228+
computeDerivedOwnership (Some db) = computeDerivedOwnership db
229+
cacheOwnership (Some db) = cacheOwnership db
230+
prepareFactOwnerCache (Some db) = prepareFactOwnerCache db
231+
backup (Some db) = backup db

0 commit comments

Comments
 (0)