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 #ifndef __Fuchsia__
8 #error Fuchsia-only Header
9 #endif
10 
11 #include <digest/digest.h>
12 #include <fbl/intrusive_wavl_tree.h>
13 #include <fbl/function.h>
14 #include <fbl/mutex.h>
15 #include <fbl/ref_ptr.h>
16 #include <fs/vnode.h>
17 
18 namespace blobfs {
19 
20 using digest::Digest;
21 
22 // Forward declared because CacheNode needs a mechanism for accessing the class
23 // when it runs out of strong references.
24 class BlobCache;
25 
26 // An abstract blob-backed Vnode, which is managed by the BlobCache.
27 class CacheNode : public fs::Vnode, fbl::Recyclable<CacheNode> {
28 public:
29     // Intrusive methods and structures.
30     using WAVLTreeNodeState = fbl::WAVLTreeNodeState<CacheNode*>;
31     struct TypeWavlTraits {
node_stateTypeWavlTraits32         static WAVLTreeNodeState& node_state(CacheNode& b) { return b.type_wavl_state_; }
33     };
34 
InContainer()35     bool InContainer() const {
36         return type_wavl_state_.InContainer();
37     }
38 
39     // TODO(ZX-3137): This constructor is only used for the "Directory" Vnode.
40     // Once distinct Vnodes are utilized for "blobs" and "the blob directory",
41     // this constructor should be deleted.
42     CacheNode();
43     explicit CacheNode(const Digest& digest);
44     virtual ~CacheNode();
45 
46     // Invoked by fbl::RefPtr when all strong references to RefPtr<CacheNode> go out of scope.
47     //
48     // If a derived class wishes to participate in the Cache's lifetime management,
49     // they must implement the following:
50     //
51     // void fbl_recycle() final {
52     //     CacheNode::fbl_recycle();
53     // }
54     void fbl_recycle() override;
55 
56     // Returns a reference to the BlobCache.
57     //
58     // The BlobCache must outlive all CacheNodes; this method is invoked from the recycler
59     // of a CacheNode.
60     //
61     // The implementation of this method must not invoke any other CacheNode methods.
62     // The implementation of this method must not attempt to acquire a reference to |this|.
63     virtual BlobCache& Cache() = 0;
64 
65     // Identifies if the node should be recycled when it is terminated,
66     // keeping it cached (although possibly in a reduced state).
67     //
68     // This should be true as long as the blob exists on persistent storage, and
69     // would be visible again on reboot.
70     //
71     // The implementation of this method must not invoke any other CacheNode methods.
72     // The implementation of this method must not attempt to acquire a reference to |this|.
73     virtual bool ShouldCache() const = 0;
74 
75     // Places the Vnode into a low-memory state. This function may be invoked when
76     // migrating the node from a "live cache" to a "closed cache".
77     //
78     // The implementation of this method must not invoke any other CacheNode methods.
79     // The implementation of this method must not attempt to acquire a reference to |this|.
80     virtual void ActivateLowMemory() = 0;
81 
82     // Returns the node's digest.
GetKey()83     const uint8_t* GetKey() const {
84         return &digest_[0];
85     }
86 
87 private:
88     friend struct TypeWavlTraits;
89     WAVLTreeNodeState type_wavl_state_ = {};
90     uint8_t digest_[Digest::kLength] = {};
91 };
92 
93 } // namespace blobfs
94