Skip to content

Commit 679bcb5

Browse files
committed
Add more config-agnostic methods to Root ledger
1 parent 5da42cc commit 679bcb5

File tree

2 files changed

+84
-2
lines changed

2 files changed

+84
-2
lines changed

src/lib/mina_ledger/root.ml

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,63 @@ struct
215215
; backing_2 = Config.backing_of_config config
216216
} )
217217

218+
let create_checkpoint_with_directory t ~directory_name =
219+
let backing_type =
220+
match t with
221+
| Stable_db _db ->
222+
Config.Stable_db
223+
| Converting_db _db ->
224+
Config.Converting_db
225+
in
226+
let config = Config.with_directory ~backing_type ~directory_name in
227+
create_checkpoint t ~config ()
228+
229+
(** Migrate the accounts in the ledger database [stable_db] and store them in
230+
[empty_hardfork_db]. The accounts are set in the target database in chunks
231+
so the daemon is still responsive during this operation; the daemon would
232+
otherwise stop everything as it hashed every account in the list. *)
233+
let chunked_migration ?(chunk_size = 1 lsl 6) stable_locations_and_accounts empty_migrated_db =
234+
let open Async.Deferred.Let_syntax in
235+
let ledger_depth = Migrated_db.depth empty_migrated_db in
236+
let addrs_and_accounts =
237+
List.mapi stable_locations_and_accounts ~f:(fun i acct ->
238+
( Migrated_db.Addr.of_int_exn ~ledger_depth i
239+
, Account.Hardfork.of_stable acct ) )
240+
in
241+
let rec set_chunks accounts =
242+
let%bind () = Async_unix.Scheduler.yield () in
243+
let chunk, accounts' = List.split_n accounts chunk_size in
244+
if List.is_empty chunk then return empty_migrated_db
245+
else (
246+
Migrated_db.set_batch_accounts empty_migrated_db chunk ;
247+
set_chunks accounts' )
248+
in
249+
set_chunks addrs_and_accounts
250+
251+
let make_converting t =
252+
let open Async.Deferred.Let_syntax in
253+
match t with
254+
| Converting_db _db ->
255+
return t
256+
| Stable_db db ->
257+
let directory_name =
258+
Stable_db.get_directory db
259+
|> Option.value_exn
260+
~message:"Invariant: database must be in a directory"
261+
in
262+
let converting_config =
263+
Converting_ledger.Config.with_primary ~directory_name
264+
in
265+
let migrated_db =
266+
Migrated_db.create
267+
~directory_name:converting_config.converting_directory
268+
~depth:(Stable_db.depth db) ()
269+
in
270+
let%map migrated_db =
271+
chunked_migration (Stable_db.to_list_sequential db) migrated_db
272+
in
273+
Converting_db (Converting_ledger.of_ledgers db migrated_db)
274+
218275
let as_unmasked t =
219276
match t with
220277
| Stable_db db ->
@@ -270,4 +327,12 @@ struct
270327
Stable_db.get_all_accounts_rooted_at_exn db
271328
| Converting_db db ->
272329
Converting_ledger.get_all_accounts_rooted_at_exn db
330+
331+
let unsafely_decompose_root t =
332+
match t with
333+
| Stable_db db ->
334+
(db, None)
335+
| Converting_db db ->
336+
( Converting_ledger.primary_ledger db
337+
, Some (Converting_ledger.converting_ledger db) )
273338
end

src/lib/mina_ledger/root.mli

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,12 +124,23 @@ module Make
124124
-> t
125125

126126
(** Make a checkpoint of the root ledger and return a new root ledger backed
127-
by that checkpoint *)
127+
by that checkpoint. Throws an exception if the config does not match the
128+
backing type of the root. *)
128129
val create_checkpoint : t -> config:Config.t -> unit -> t
129130

130-
(** Make a checkpoint of the root ledger *)
131+
(** Make a checkpoint of the root ledger. Throws an exception if the config
132+
does not match the backing type of the root. *)
131133
val make_checkpoint : t -> config:Config.t -> unit
132134

135+
(** Make a checkpoint of the root ledger [t] of the same backing type using
136+
[directory_name] as a template for its location. Return a new root ledger
137+
backed by that checkpoint. *)
138+
val create_checkpoint_with_directory :
139+
t -> directory_name:string -> t
140+
141+
(** Convert a root backed by a [Config.Stable_db] to *)
142+
val make_converting : t -> t Async.Deferred.t
143+
133144
(** View the root ledger as an unmasked [Any_ledger] so it can be used by code
134145
that does not need to know how the root is implemented *)
135146
val as_unmasked : t -> Any_ledger.witness
@@ -160,4 +171,10 @@ module Make
160171
(** Get all of the accounts that are in a subtree of the underlying Merkle
161172
tree rooted at `address`. The accounts are ordered by their addresses. *)
162173
val get_all_accounts_rooted_at_exn : t -> addr -> (addr * account) list
174+
175+
(** Decompose a root into its components parts. Users of this method must be
176+
careful to ensure that either the underlying databases remain in sync, or
177+
that they are not later used to back a root ledger. Use this on temporary
178+
copies of root ledgers if possible. *)
179+
val unsafely_decompose_root : t -> Stable_db.t * Migrated_db.t option
163180
end

0 commit comments

Comments
 (0)