1 // Copyright 2018 The Fuchsia Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #pragma once
6 
7 #include <stdbool.h>
8 #include <stdint.h>
9 
10 #include <blobfs/allocator.h>
11 #include <blobfs/extent-reserver.h>
12 #include <blobfs/format.h>
13 #include <blobfs/node-reserver.h>
14 #include <fbl/function.h>
15 #include <fbl/vector.h>
16 #include <zircon/types.h>
17 
18 namespace blobfs {
19 
20 // A helper class which utilizes the visitor pattern to chain together a group
21 // of extents and nodes.
22 //
23 // Precondition:
24 //      nodes.size() >= NodeCountForExtents(extents.size())
25 class NodePopulator {
26 public:
27     NodePopulator(Allocator* allocator,
28                   fbl::Vector<ReservedExtent> extents,
29                   fbl::Vector<ReservedNode> nodes);
30 
31     DISALLOW_COPY_ASSIGN_AND_MOVE(NodePopulator);
32 
33     // Returns the maximum number of nodes necessary to hold |extent_count| extents.
34     static uint32_t NodeCountForExtents(ExtentCountType extent_count);
35 
36     enum class IterationCommand {
37         Continue,
38         Stop,
39     };
40 
41     using OnNodeCallback = fbl::Function<void(const ReservedNode& node)>;
42     using OnExtentCallback = fbl::Function<IterationCommand(ReservedExtent& extent)>;
43 
44     // Utilizes the |allocator| to locate all nodes provided by |nodes|, and allocate each
45     // node the appropriate |extent|.
46     //
47     // Along the way, this methods sets the following fields on the blob inode: |next_node|,
48     // |extents|, |extent_count|. This method sets all fields on the container nodes.
49     //
50     // Before each extent is accessed, |on_extent| is invoked. This allows a caller to modify how
51     // much of the extent is actually used. If IterationCommand::Stop is returned from |on_extent|,
52     // then extent-filling exits early, and no additional extents are used. This ability to "stop
53     // short" when using extents is useful when less storage is needed to persist a blob than
54     // originally allocated. This is common when using compression.
55     //
56     // After all extents are accessed, |on_node| is invoked on all nodes which are actually used to
57     // represent the blob. This may be smaller than the number of nodes passed in the ReservedNode
58     // vector.
59     zx_status_t Walk(OnNodeCallback on_node, OnExtentCallback on_extent);
60 
61 private:
62     Allocator* allocator_;
63     fbl::Vector<ReservedExtent> extents_;
64     fbl::Vector<ReservedNode> nodes_;
65 };
66 
67 } // namespace blobfs
68