@@ -25,6 +25,9 @@ import Util.OptParse
2525import Util.Log ( logInfo )
2626import Thrift.Protocol.Compact
2727
28+ import qualified Glean.Database.Config as GleanDB
29+ import Glean.Database.Schema
30+ import Glean.Database.Schema.Types
2831import Glean.LocalOrRemote (loadDbSchema )
2932import qualified Glean.LocalOrRemote as Glean
3033import Glean.Types
@@ -34,11 +37,6 @@ import qualified Glean.RTS.Foreign.FactSet as FactSet
3437import Glean.RTS.Foreign.Define (DefineFlags (.. ), defineBatch )
3538import qualified Glean.RTS.Foreign.Inventory as Inventory
3639import Glean.RTS.Foreign.Ownership
37- import qualified Glean.Database.Config as GleanDB
38- import Glean.Database.Schema.Types
39- import qualified Glean.Util.ThriftSource as ThriftSource
40- import Glean.Database.Config (cfgServerConfig )
41- import Glean.Database.Schema
4240
4341import GleanCLI.Types
4442import GleanCLI.Common (dbOpts , fileFormatOpt , FileFormat (.. ))
@@ -51,7 +49,7 @@ data MergeCommand = MergeCommand
5149 , mergeFileSize :: Int
5250 , mergeOutDir :: FilePath
5351 , fileFormat :: FileFormat
54- , inventorySource :: Either Repo FilePath
52+ , inventorySource :: Maybe ( Either Repo FilePath )
5553 }
5654
5755inventoryOpt :: Parser FilePath
@@ -61,6 +59,11 @@ inventoryOpt = strOption $
6159 help (" Inventory created with --write-serialized-inventory and which "
6260 <> " was used to create binary format files of facts" )
6361
62+ data SchemaData
63+ = HaveSchema DbSchema
64+ | HaveInventory Inventory. Inventory
65+ | HaveNothing
66+
6467instance Plugin MergeCommand where
6568 parseCommand = commandParser " merge" (progDesc " Merge fact files" ) $ do
6669 mergeFiles <- many $ strArgument (
@@ -77,29 +80,40 @@ instance Plugin MergeCommand where
7780 long " output" <>
7881 metavar " DIR" <>
7982 help " Destination directory for the merged fact files"
80- inventorySource <- Left <$> dbOpts <|> Right <$> inventoryOpt
83+ inventorySource <- optional $ Left <$> dbOpts <|> Right <$> inventoryOpt
8184 fileFormat <- fileFormatOpt BinaryFormat
8285 return MergeCommand {.. }
8386
8487 withService evb cfgAPI svc MergeCommand {.. } = do
85- (inventory, dbSchema) <- case inventorySource of
86- Left repo -> do
88+ -- * --file-format=binary requires an inventory, from either --db or
89+ -- --inventory.
90+ -- * --file-format=json requires a dbSchema, from either --db or
91+ -- schema_id in the JSON file. It's pointless to use --inventory with
92+ -- --file-format=json, because the inventory isn't used.
93+ schemaData <- case inventorySource of
94+ Just (Left repo) -> do
8795 dbSchema <- Glean. withBackendWithDefaultOptions
8896 evb cfgAPI svc Nothing $ \ backend -> do
8997 loadDbSchema backend repo
90- logInfo(" db's schema ID is: " <> show (schemaId dbSchema))
91- return (schemaInventory dbSchema, Just dbSchema)
92- Right mergeInventory -> do
93- inventory <- Inventory. deserialize <$> B. readFile mergeInventory
94- -- Get the schema_id from the JSON's schema ID field
95- --- this needs to be done when the file is considered later on
96- -- dbSchema <-
97- return (inventory, Nothing )
98+ logInfo(" db's schema ID is: " <> show (schemaId dbSchema))
99+ return (HaveSchema dbSchema)
100+ Just (Right mergeInventory) -> do
101+ case fileFormat of
102+ JsonFormat -> do
103+ hPutStrLn stderr $
104+ " Warning: --inventory is ignored with --file-format=json"
105+ return HaveNothing
106+ _ -> do
107+ inventory <- Inventory. deserialize <$> B. readFile mergeInventory
108+ return (HaveInventory inventory)
109+ Nothing ->
110+ return HaveNothing
98111 createDirectoryIfMissing True mergeOutDir
99112 hSetBuffering stderr LineBuffering
100113 outputs <- newIORef []
101114 expandedMergeFiles <- mapM expandFile mergeFiles
102- stream 1 (merge fileFormat inventory dbSchema $ concat expandedMergeFiles)
115+ stream 1
116+ (merge fileFormat schemaData (concat expandedMergeFiles))
103117 (writeToFile outputs)
104118 -- stream overlaps writing with reading
105119 files <- readIORef outputs
@@ -146,84 +160,87 @@ instance Plugin MergeCommand where
146160 " (" <> show (B. length batch) <> " bytes)"
147161 B. writeFile out batch
148162
149- merge fileFormat inventory dbSchema files write = loop 0 0 Nothing files
163+ merge fileFormat schemaData files write =
164+ loop 0 0 Nothing schemaData files
150165 where
151- read :: FilePath -> Int -> FactSet -> IO FactOwnership
152- read file size factSet = do
166+ read
167+ :: FilePath
168+ -> Int
169+ -> FactSet
170+ -> SchemaData
171+ -> IO (FactOwnership , SchemaData )
172+ read file size factSet schemaData = do
153173 logInfo $ " Reading " <> file <> " (" <> show size <> " bytes)"
154- -- Merge can take an existing db or an inventory.
155- -- A DB has a dbSchema, so we can use that to build the batches
156- -- to merge
157- -- An inventory doesn't have a dbSchema, so leads to "Nothing"
158- -- This means that we need to get the schema from somewhere
159- --- this will be the first JSON file we see
160- -- read the 'schema_id' field in that file and create a
161- -- new dbSchema intance with that using configerator's
162- -- stored default schema index
163-
164- batch <- case fileFormat of
174+
175+ let
176+ define batch inventory newSchemaData = do
177+ subst <- defineBatch factSet inventory batch
178+ DefineFlags {
179+ trustRefs = True ,
180+ ignoreRedef = True }
181+ own <- substOwnership subst $ FactOwnership (batch_owned batch)
182+ return (own, newSchemaData)
183+
184+ case fileFormat of
165185 JsonFormat -> do
166186 (batches, schema_id_file) <- fileToBatches file
167- case dbSchema of
168- Nothing -> do
187+ dbSchema <- case schemaData of
188+ HaveSchema dbSchema
189+ | Just schema_id <- schema_id_file,
190+ schema_id /= schemaId dbSchema ->
191+ throwIO $ ErrorCall $
192+ " Schema ID mismatch:\n db: "
193+ <> show (schemaId dbSchema) <> " \n vs\n File: "
194+ <> file <> " has " <> show schema_id
195+ | otherwise -> return dbSchema
196+ _otherwise -> do
197+ -- the first time (only), we load the schema we'll
198+ -- be using to parse the JSON files.
169199 schema_id <- case schema_id_file of
170- Nothing -> throwIO $ ErrorCall " missing schema ID"
200+ Nothing -> throwIO $ ErrorCall $
201+ file <> " : missing schema_id"
171202 Just id -> return id
172203 let cfg = case svc of
173204 Glean. Local cfg _ -> cfg
174205 Glean. Remote {} -> def
175- serverConfig <- ThriftSource. load cfgAPI (cfgServerConfig cfg)
176- loc <- GleanDB. schemaLocation cfg serverConfig
177- let (schemaSource, _) = GleanDB. cfgSchemaHook cfg loc
178- index <- ThriftSource. load cfgAPI schemaSource
179- dbSchema <- newDbSchema Nothing index
180- (SpecificSchemaId schema_id) readWriteContent def
181- buildJsonBatch dbSchema
182- (schemaIdToOpts $ Just (schemaId dbSchema)) batches
183- Just schema -> do
184- if Just (schemaId schema) == schema_id_file then
185- logInfo(
186- " Schema matches with db schema. Merging data from "
187- <> file
188- )
189- else
190- throwIO $ ErrorCall $
191- " ERROR - ABORTING MERGE\n Schema ID mismatch:\n db: "
192- <> show (schemaId schema) <> " \n vs\n File: "
193- <> file <> " has " <> show schema_id_file
194- let getSchemaId theschema = Just (schemaId theschema) in
195- buildJsonBatch schema
196- (schemaIdToOpts $ getSchemaId schema) batches
206+ index <- GleanDB. loadSchemaIndex cfg cfgAPI
207+ newDbSchema Nothing index (SpecificSchemaId schema_id)
208+ readWriteContent def
209+ batch <- buildJsonBatch dbSchema
210+ (schemaIdToOpts $ Just (schemaId dbSchema)) batches
211+ define batch (schemaInventory dbSchema) (HaveSchema dbSchema)
197212
198213 BinaryFormat -> do
214+ inventory <- case schemaData of
215+ HaveSchema dbSchema -> return (schemaInventory dbSchema)
216+ HaveInventory inventory -> return inventory
217+ HaveNothing -> throwIO $ ErrorCall $
218+ " --file-format=binary requires either --inventory, " <>
219+ " --db, or --db-name and --db-instance"
199220 bytes <- B. readFile file
200221 case deserializeCompact bytes of
201222 Left err -> throwIO $ ErrorCall $
202223 " failed to deserialize " <> file <> " : " <> err
203- Right batch -> return batch
204- subst <- defineBatch factSet inventory batch
205- DefineFlags {
206- trustRefs = True ,
207- ignoreRedef = True }
208- substOwnership subst $ FactOwnership (batch_owned batch)
209-
210- loop ! _ _ Nothing [] = return ()
211- loop ! n _ (Just set) [] = write (n, Right set)
212- loop ! n currentSize acc (f : files) = do
224+ Right batch ->
225+ define batch inventory (HaveInventory inventory)
226+
227+ loop ! _ _ Nothing _ [] = return ()
228+ loop ! n _ (Just set) _ [] = write (n, Right set)
229+ loop ! n currentSize acc schema (f : files) = do
213230 size <- fromIntegral <$> getFileSize f
214231 if size > mergeFileSize && fileFormat == BinaryFormat
215232 -- just copy huge binary files
216233 then do
217234 write (n, Left f)
218- loop (n+ 1 ) currentSize acc files
235+ loop (n+ 1 ) currentSize acc schema files
219236 else do
220237 (factSet, ownership) <- case acc of
221238 Nothing -> (,[] ) <$> FactSet. new lowestFid
222239 Just facts -> return facts
223- owners <- read f size factSet
240+ ( owners, schema) <- read f size factSet schema
224241 newSize <- factSetSize factSet
225242 let facts = (factSet, owners : ownership)
226243 (n, acc) <- if newSize > mergeFileSize
227244 then do write (n, Right facts); return (n+ 1 , Nothing )
228245 else return (n, Just facts)
229- loop n newSize acc files
246+ loop n newSize acc schema files
0 commit comments