blob: 99960ed3030a12b14bfb416ba0580348951ee6a1 [file] [log] [blame]
Narayan Kamathaef84a12020-01-02 15:20:13 +00001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specic language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef MEDIA_PROVIDER_JNI_NODE_INL_H_
18#define MEDIA_PROVIDER_JNI_NODE_INL_H_
19
20#include <android-base/logging.h>
21
Zimbb7c3762020-09-23 13:50:08 +010022#include <atomic>
Nikita Ioffe890e6f22020-06-18 17:35:08 +010023#include <cstdint>
24#include <limits>
Narayan Kamathaef84a12020-01-02 15:20:13 +000025#include <list>
26#include <memory>
27#include <mutex>
Nikita Ioffe890e6f22020-06-18 17:35:08 +010028#include <set>
Zimuzo Ezeozue67db40c2020-02-21 19:41:33 +000029#include <sstream>
Narayan Kamathaef84a12020-01-02 15:20:13 +000030#include <string>
Narayan Kamath568f17a2020-02-19 13:45:29 +000031#include <unordered_set>
Nikita Ioffe890e6f22020-06-18 17:35:08 +010032#include <utility>
Narayan Kamathaef84a12020-01-02 15:20:13 +000033#include <vector>
34
35#include "libfuse_jni/ReaddirHelper.h"
36#include "libfuse_jni/RedactionInfo.h"
37
38class NodeTest;
39
40namespace mediaprovider {
41namespace fuse {
42
43struct handle {
Zim148cbe22020-11-17 15:58:29 +000044 explicit handle(int fd, const RedactionInfo* ri, bool cached, bool passthrough, uid_t uid)
45 : fd(fd), ri(ri), cached(cached), passthrough(passthrough), uid(uid) {
Narayan Kamathbd22bb02020-01-08 16:02:50 +000046 CHECK(ri != nullptr);
47 }
48
Narayan Kamathbd22bb02020-01-08 16:02:50 +000049 const int fd;
50 const std::unique_ptr<const RedactionInfo> ri;
51 const bool cached;
Zim148cbe22020-11-17 15:58:29 +000052 const bool passthrough;
Zim9aa6f542020-10-19 15:39:33 +010053 const uid_t uid;
Narayan Kamathaef84a12020-01-02 15:20:13 +000054
55 ~handle() { close(fd); }
56};
57
58struct dirhandle {
Narayan Kamathbd22bb02020-01-08 16:02:50 +000059 explicit dirhandle(DIR* dir) : d(dir), next_off(0) { CHECK(dir != nullptr); }
Narayan Kamathaef84a12020-01-02 15:20:13 +000060
61 DIR* const d;
62 off_t next_off;
63 // Fuse readdir() is called multiple times based on the size of the buffer and
64 // number of directory entries in the given directory. 'de' holds the list
65 // of directory entries for the directory handle and this list is available
66 // across subsequent readdir() calls for the same directory handle.
67 std::vector<std::shared_ptr<DirectoryEntry>> de;
68
69 ~dirhandle() { closedir(d); }
70};
71
Narayan Kamath568f17a2020-02-19 13:45:29 +000072// Whether inode tracking is enabled or not. When enabled, we maintain a
73// separate mapping from inode numbers to "live" nodes so we can detect when
74// we receive a request to a node that has been deleted.
75static constexpr bool kEnableInodeTracking = true;
76
77class node;
78
79// Tracks the set of active nodes associated with a FUSE instance so that we
80// can assert that we only ever return an active node in response to a lookup.
81class NodeTracker {
82 public:
Nandana Duttaa76d1e2020-04-29 09:42:42 +010083 explicit NodeTracker(std::recursive_mutex* lock) : lock_(lock) {}
Narayan Kamath568f17a2020-02-19 13:45:29 +000084
85 void CheckTracked(__u64 ino) const {
86 if (kEnableInodeTracking) {
87 const node* node = reinterpret_cast<const class node*>(ino);
88 std::lock_guard<std::recursive_mutex> guard(*lock_);
89 CHECK(active_nodes_.find(node) != active_nodes_.end());
90 }
91 }
92
93 void NodeDeleted(const node* node) {
94 if (kEnableInodeTracking) {
95 std::lock_guard<std::recursive_mutex> guard(*lock_);
96 LOG(DEBUG) << "Node: " << reinterpret_cast<uintptr_t>(node) << " deleted.";
97
98 CHECK(active_nodes_.find(node) != active_nodes_.end());
99 active_nodes_.erase(node);
100 }
101 }
102
103 void NodeCreated(const node* node) {
104 if (kEnableInodeTracking) {
105 std::lock_guard<std::recursive_mutex> guard(*lock_);
106 LOG(DEBUG) << "Node: " << reinterpret_cast<uintptr_t>(node) << " created.";
107
108 CHECK(active_nodes_.find(node) == active_nodes_.end());
109 active_nodes_.insert(node);
110 }
111 }
112
113 private:
114 std::recursive_mutex* lock_;
115 std::unordered_set<const node*> active_nodes_;
116};
117
Narayan Kamathaef84a12020-01-02 15:20:13 +0000118class node {
119 public:
120 // Creates a new node with the specified parent, name and lock.
Zimbb7c3762020-09-23 13:50:08 +0100121 static node* Create(node* parent, const std::string& name, const std::string& io_path,
Zimded1ab92021-01-15 10:36:17 +0000122 bool should_invalidate, bool transforms_complete, const int transforms,
Zim801d9852021-01-26 18:30:53 +0000123 const int transforms_reason, std::recursive_mutex* lock,
124 NodeTracker* tracker) {
Narayan Kamath568f17a2020-02-19 13:45:29 +0000125 // Place the entire constructor under a critical section to make sure
126 // node creation, tracking (if enabled) and the addition to a parent are
127 // atomic.
128 std::lock_guard<std::recursive_mutex> guard(*lock);
Zimded1ab92021-01-15 10:36:17 +0000129 return new node(parent, name, io_path, should_invalidate, transforms_complete, transforms,
Zim801d9852021-01-26 18:30:53 +0000130 transforms_reason, lock, tracker);
Narayan Kamathaef84a12020-01-02 15:20:13 +0000131 }
132
133 // Creates a new root node. Root nodes have no parents by definition
134 // and their "name" must signify an absolute path.
Narayan Kamath568f17a2020-02-19 13:45:29 +0000135 static node* CreateRoot(const std::string& path, std::recursive_mutex* lock,
136 NodeTracker* tracker) {
137 std::lock_guard<std::recursive_mutex> guard(*lock);
Zimded1ab92021-01-15 10:36:17 +0000138 node* root = new node(nullptr, path, path, false /* should_invalidate */,
Zim801d9852021-01-26 18:30:53 +0000139 true /* transforms_complete */, 0 /* transforms */,
140 0 /* transforms_reason */, lock, tracker);
Narayan Kamathaef84a12020-01-02 15:20:13 +0000141
142 // The root always has one extra reference to avoid it being
143 // accidentally collected.
144 root->Acquire();
145 return root;
146 }
147
148 // Maps an inode to its associated node.
Narayan Kamath568f17a2020-02-19 13:45:29 +0000149 static inline node* FromInode(__u64 ino, const NodeTracker* tracker) {
150 tracker->CheckTracked(ino);
Narayan Kamathaef84a12020-01-02 15:20:13 +0000151 return reinterpret_cast<node*>(static_cast<uintptr_t>(ino));
152 }
153
154 // Maps a node to its associated inode.
155 static __u64 ToInode(node* node) {
156 return static_cast<__u64>(reinterpret_cast<uintptr_t>(node));
157 }
158
Narayan Kamathaef84a12020-01-02 15:20:13 +0000159 // Releases a reference to a node. Returns true iff the refcount dropped to
160 // zero as a result of this call to Release, meaning that it's no longer
161 // safe to perform any operations on references to this node.
162 bool Release(uint32_t count) {
163 std::lock_guard<std::recursive_mutex> guard(*lock_);
164 if (refcount_ >= count) {
165 refcount_ -= count;
166 if (refcount_ == 0) {
167 delete this;
168 return true;
169 }
170 } else {
171 LOG(ERROR) << "Mismatched reference count: refcount_ = " << this->refcount_
172 << " ,count = " << count;
173 }
174
175 return false;
176 }
177
178 // Builds the full path associated with this node, including all path segments
179 // associated with its descendants.
180 std::string BuildPath() const;
181
Zimuzo Ezeozue67db40c2020-02-21 19:41:33 +0000182 // Builds the full PII safe path associated with this node, including all path segments
183 // associated with its descendants.
184 std::string BuildSafePath() const;
185
Zimd2b59b42021-01-12 17:06:10 +0000186 // Looks up a direct descendant of this node by case-insensitive |name|. If |acquire| is true,
Narayan Kamatheca34252020-02-11 13:08:37 +0000187 // also Acquire the node before returning a reference to it.
Zimd2b59b42021-01-12 17:06:10 +0000188 // |transforms| is an opaque flag that is used to distinguish multiple nodes sharing the same
189 // |name| but requiring different IO transformations as determined by the MediaProvider.
Zimbb7c3762020-09-23 13:50:08 +0100190 node* LookupChildByName(const std::string& name, bool acquire, const int transforms = 0) const {
191 return ForChild(name, [acquire, transforms](node* child) {
192 if (child->transforms_ == transforms) {
193 if (acquire) {
194 child->Acquire();
195 }
196 return true;
Narayan Kamathaef84a12020-01-02 15:20:13 +0000197 }
Zimbb7c3762020-09-23 13:50:08 +0100198 return false;
Zim53c2d702020-09-23 12:18:27 +0100199 });
Narayan Kamathaef84a12020-01-02 15:20:13 +0000200 }
201
Zim53c2d702020-09-23 12:18:27 +0100202 // Marks this node children as deleted. They are still associated with their parent, and
203 // all open handles etc. to the deleted nodes are preserved until their refcount goes
Narayan Kamathaef84a12020-01-02 15:20:13 +0000204 // to zero.
Zim53c2d702020-09-23 12:18:27 +0100205 void SetDeletedForChild(const std::string& name) {
206 ForChild(name, [](node* child) {
207 child->SetDeleted();
208 return false;
209 });
210 }
211
Narayan Kamathaef84a12020-01-02 15:20:13 +0000212 void SetDeleted() {
213 std::lock_guard<std::recursive_mutex> guard(*lock_);
Narayan Kamathaef84a12020-01-02 15:20:13 +0000214 deleted_ = true;
215 }
216
Zim53c2d702020-09-23 12:18:27 +0100217 void RenameChild(const std::string& old_name, const std::string& new_name, node* new_parent) {
218 ForChild(old_name, [=](node* child) {
219 child->Rename(new_name, new_parent);
220 return false;
221 });
222 }
223
Narayan Kamathaef84a12020-01-02 15:20:13 +0000224 void Rename(const std::string& name, node* new_parent) {
Narayan Kamathaef84a12020-01-02 15:20:13 +0000225 std::lock_guard<std::recursive_mutex> guard(*lock_);
226
Zim87c7bf82020-01-07 18:11:27 +0000227 if (new_parent != parent_) {
228 RemoveFromParent();
Nikita Ioffe890e6f22020-06-18 17:35:08 +0100229 name_ = name;
Zim87c7bf82020-01-07 18:11:27 +0000230 AddToParent(new_parent);
Nikita Ioffe890e6f22020-06-18 17:35:08 +0100231 return;
232 }
233
234 // Changing name_ will change the expected position of this node in parent's set of
235 // children. Consider following scenario:
236 // 1. This node: "b"; parent's set: {"a", "b", "c"}
237 // 2. Rename("b", "d")
238 //
239 // After rename, parent's set should become: {"a", "b", "d"}, but if we simply change the
240 // name it will be {"a", "d", "b"}, which violates properties of the set.
241 //
242 // To make sure that parent's set is always valid, changing name is 3 steps procedure:
243 // 1. Remove this node from parent's set.
244 // 2 Change the name.
245 // 3. Add it back to the set.
246 // Rename of node without changing its parent. Still need to remove and re-add it to make
247 // sure lookup index is correct.
248 if (name_ != name) {
249 // If this is a root node, simply rename it.
250 if (parent_ == nullptr) {
251 name_ = name;
252 return;
253 }
254
255 auto it = parent_->children_.find(this);
256 CHECK(it != parent_->children_.end());
257 parent_->children_.erase(it);
258
259 name_ = name;
260
261 parent_->children_.insert(this);
Zim87c7bf82020-01-07 18:11:27 +0000262 }
Narayan Kamathaef84a12020-01-02 15:20:13 +0000263 }
264
265 const std::string& GetName() const {
266 std::lock_guard<std::recursive_mutex> guard(*lock_);
267 return name_;
268 }
269
Zimbb7c3762020-09-23 13:50:08 +0100270 const std::string& GetIoPath() const { return io_path_; }
271
272 int GetTransforms() const { return transforms_; }
273
Zim801d9852021-01-26 18:30:53 +0000274 int GetTransformsReason() const { return transforms_reason_; }
275
Zimbb7c3762020-09-23 13:50:08 +0100276 bool IsTransformsComplete() const {
277 return transforms_complete_.load(std::memory_order_acquire);
278 }
279
280 void SetTransformsComplete() { transforms_complete_.store(true, std::memory_order_release); }
281
Zima76c3492020-02-19 01:23:26 +0000282 node* GetParent() const {
283 std::lock_guard<std::recursive_mutex> guard(*lock_);
284 return parent_;
285 }
286
Narayan Kamathaef84a12020-01-02 15:20:13 +0000287 inline void AddHandle(handle* h) {
288 std::lock_guard<std::recursive_mutex> guard(*lock_);
289 handles_.emplace_back(std::unique_ptr<handle>(h));
290 }
291
292 void DestroyHandle(handle* h) {
293 std::lock_guard<std::recursive_mutex> guard(*lock_);
294
295 auto comp = [h](const std::unique_ptr<handle>& ptr) { return ptr.get() == h; };
296 auto it = std::find_if(handles_.begin(), handles_.end(), comp);
297 CHECK(it != handles_.end());
298 handles_.erase(it);
299 }
300
301 bool HasCachedHandle() const {
302 std::lock_guard<std::recursive_mutex> guard(*lock_);
303
304 for (const auto& handle : handles_) {
305 if (handle->cached) {
306 return true;
307 }
308 }
309 return false;
310 }
311
Zimded1ab92021-01-15 10:36:17 +0000312 bool ShouldInvalidate() const {
Zimf2b47b42020-09-16 14:54:06 +0100313 std::lock_guard<std::recursive_mutex> guard(*lock_);
Zimded1ab92021-01-15 10:36:17 +0000314 return should_invalidate_;
Zimf2b47b42020-09-16 14:54:06 +0100315 }
316
Zimded1ab92021-01-15 10:36:17 +0000317 void SetShouldInvalidate() {
Zimf2b47b42020-09-16 14:54:06 +0100318 std::lock_guard<std::recursive_mutex> guard(*lock_);
Zimded1ab92021-01-15 10:36:17 +0000319 should_invalidate_ = true;
Zimf2b47b42020-09-16 14:54:06 +0100320 }
321
Zim329ba2c2020-09-16 14:23:26 +0100322 bool HasRedactedCache() const {
323 std::lock_guard<std::recursive_mutex> guard(*lock_);
324 return has_redacted_cache_;
325 }
326
327 void SetRedactedCache(bool state) {
328 std::lock_guard<std::recursive_mutex> guard(*lock_);
329 has_redacted_cache_ = state;
330 }
331
Narayan Kamathaef84a12020-01-02 15:20:13 +0000332 inline void AddDirHandle(dirhandle* d) {
333 std::lock_guard<std::recursive_mutex> guard(*lock_);
334
335 dirhandles_.emplace_back(std::unique_ptr<dirhandle>(d));
336 }
337
338 void DestroyDirHandle(dirhandle* d) {
339 std::lock_guard<std::recursive_mutex> guard(*lock_);
340
341 auto comp = [d](const std::unique_ptr<dirhandle>& ptr) { return ptr.get() == d; };
342 auto it = std::find_if(dirhandles_.begin(), dirhandles_.end(), comp);
343 CHECK(it != dirhandles_.end());
344 dirhandles_.erase(it);
345 }
346
347 // Deletes the tree of nodes rooted at |tree|.
348 static void DeleteTree(node* tree);
349
350 // Looks up an absolute path rooted at |root|, or nullptr if no such path
351 // through the hierarchy exists.
352 static const node* LookupAbsolutePath(const node* root, const std::string& absolute_path);
353
354 private:
Zimded1ab92021-01-15 10:36:17 +0000355 node(node* parent, const std::string& name, const std::string& io_path,
356 const bool should_invalidate, const bool transforms_complete, const int transforms,
Zim801d9852021-01-26 18:30:53 +0000357 const int transforms_reason, std::recursive_mutex* lock, NodeTracker* tracker)
Narayan Kamath568f17a2020-02-19 13:45:29 +0000358 : name_(name),
Zimbb7c3762020-09-23 13:50:08 +0100359 io_path_(io_path),
360 transforms_complete_(transforms_complete),
361 transforms_(transforms),
Zim801d9852021-01-26 18:30:53 +0000362 transforms_reason_(transforms_reason),
Narayan Kamath568f17a2020-02-19 13:45:29 +0000363 refcount_(0),
364 parent_(nullptr),
Zim329ba2c2020-09-16 14:23:26 +0100365 has_redacted_cache_(false),
Zimded1ab92021-01-15 10:36:17 +0000366 should_invalidate_(should_invalidate),
Narayan Kamath568f17a2020-02-19 13:45:29 +0000367 deleted_(false),
368 lock_(lock),
369 tracker_(tracker) {
370 tracker_->NodeCreated(this);
Narayan Kamathaef84a12020-01-02 15:20:13 +0000371 Acquire();
372 // This is a special case for the root node. All other nodes will have a
373 // non-null parent.
374 if (parent != nullptr) {
375 AddToParent(parent);
376 }
Zimded1ab92021-01-15 10:36:17 +0000377 // If the node requires transforms, we MUST never cache it in the VFS
378 if (transforms) {
379 CHECK(should_invalidate_);
380 }
Narayan Kamathaef84a12020-01-02 15:20:13 +0000381 }
382
Narayan Kamatheca34252020-02-11 13:08:37 +0000383 // Acquires a reference to a node. This maps to the "lookup count" specified
384 // by the FUSE documentation and must only happen under the circumstances
385 // documented in libfuse/include/fuse_lowlevel.h.
386 inline void Acquire() {
387 std::lock_guard<std::recursive_mutex> guard(*lock_);
388 refcount_++;
389 }
390
Narayan Kamathaef84a12020-01-02 15:20:13 +0000391 // Adds this node to a specified parent.
392 void AddToParent(node* parent) {
393 std::lock_guard<std::recursive_mutex> guard(*lock_);
394 // This method assumes this node is currently unparented.
395 CHECK(parent_ == nullptr);
396 // Check that the new parent isn't nullptr either.
397 CHECK(parent != nullptr);
398
399 parent_ = parent;
Nikita Ioffe890e6f22020-06-18 17:35:08 +0100400 parent_->children_.insert(this);
Narayan Kamathaef84a12020-01-02 15:20:13 +0000401
402 // TODO(narayan, zezeozue): It's unclear why we need to call Acquire on the
403 // parent node when we're adding a child to it.
404 parent_->Acquire();
405 }
406
407 // Removes this node from its current parent, and set its parent to nullptr.
408 void RemoveFromParent() {
409 std::lock_guard<std::recursive_mutex> guard(*lock_);
410
411 if (parent_ != nullptr) {
Nikita Ioffe890e6f22020-06-18 17:35:08 +0100412 auto it = parent_->children_.find(this);
413 CHECK(it != parent_->children_.end());
414 parent_->children_.erase(it);
Narayan Kamathaef84a12020-01-02 15:20:13 +0000415
Narayan Kamathaef84a12020-01-02 15:20:13 +0000416 parent_->Release(1);
417 parent_ = nullptr;
418 }
419 }
420
Zim53c2d702020-09-23 12:18:27 +0100421 // Finds *all* non-deleted nodes matching |name| and runs the function |callback| on each
422 // node until |callback| returns true.
423 // When |callback| returns true, the matched node is returned
424 node* ForChild(const std::string& name, const std::function<bool(node*)>& callback) const {
425 std::lock_guard<std::recursive_mutex> guard(*lock_);
426
427 // lower_bound will give us the first child with strcasecmp(child->name, name) >=0.
428 // For more context see comment on the NodeCompare struct.
429 auto start = children_.lower_bound(std::make_pair(name, 0));
430 // upper_bound will give us the first child with strcasecmp(child->name, name) > 0
431 auto end =
432 children_.upper_bound(std::make_pair(name, std::numeric_limits<uintptr_t>::max()));
433
434 // Make a copy of the matches because calling callback might modify the list which will
435 // cause issues while iterating over them.
436 std::vector<node*> children(start, end);
437
438 for (node* child : children) {
439 if (!child->deleted_ && callback(child)) {
440 return child;
441 }
442 }
443
444 return nullptr;
445 }
446
Nikita Ioffe890e6f22020-06-18 17:35:08 +0100447 // A custom heterogeneous comparator used for set of this node's children_ to speed up child
448 // node by name lookups.
449 //
450 // This comparator treats node* as pair (node->name_, node): two nodes* are first
451 // compared by their name using case-insenstive comparison function. If their names are equal,
452 // then pointers are compared as integers.
453 //
454 // See LookupChildByName function to see how this comparator is used.
455 //
456 // Note that it's important to first compare by name_, since it will make all nodes with same
457 // name (compared using strcasecmp) together, which allows LookupChildByName function to find
458 // range of the candidate nodes by issuing two binary searches.
459 struct NodeCompare {
460 using is_transparent = void;
461
462 bool operator()(const node* lhs, const node* rhs) const {
463 int cmp = strcasecmp(lhs->name_.c_str(), rhs->name_.c_str());
464 if (cmp != 0) {
465 return cmp < 0;
466 }
467 return reinterpret_cast<uintptr_t>(lhs) < reinterpret_cast<uintptr_t>(rhs);
468 }
469
470 bool operator()(const node* lhs, const std::pair<std::string, uintptr_t>& rhs) const {
471 int cmp = strcasecmp(lhs->name_.c_str(), rhs.first.c_str());
472 if (cmp != 0) {
473 return cmp < 0;
474 }
475 return reinterpret_cast<uintptr_t>(lhs) < rhs.second;
476 }
477
478 bool operator()(const std::pair<std::string, uintptr_t>& lhs, const node* rhs) const {
479 int cmp = strcasecmp(lhs.first.c_str(), rhs->name_.c_str());
480 if (cmp != 0) {
481 return cmp < 0;
482 }
483 return lhs.second < reinterpret_cast<uintptr_t>(rhs);
484 }
485 };
486
Zimuzo Ezeozue67db40c2020-02-21 19:41:33 +0000487 // A helper function to recursively construct the absolute path of a given node.
488 // If |safe| is true, builds a PII safe path instead
489 void BuildPathForNodeRecursive(bool safe, const node* node, std::stringstream* path) const;
Narayan Kamathaef84a12020-01-02 15:20:13 +0000490
491 // The name of this node. Non-const because it can change during renames.
492 std::string name_;
Zimbb7c3762020-09-23 13:50:08 +0100493 // Filesystem path that will be used for IO (if it is non-empty) instead of node->BuildPath
494 const std::string io_path_;
495 // Whether any transforms required on |io_path_| are complete.
496 // If false, might need to call a node transform function with |transforms| below
497 std::atomic_bool transforms_complete_;
Zim801d9852021-01-26 18:30:53 +0000498 // Opaque flags that determines the 'required' transforms to perform on node
499 // before IO. These flags should not be interpreted in native but should be passed to the
500 // MediaProvider as part of a transform function and if successful, |transforms_complete_|
501 // should be set to true
Zimbb7c3762020-09-23 13:50:08 +0100502 const int transforms_;
Zim801d9852021-01-26 18:30:53 +0000503 // Opaque value indicating the reason why transforms are required.
504 // This value should not be interpreted in native but should be passed to the MediaProvider
505 // as part of a transform function
506 const int transforms_reason_;
Narayan Kamathaef84a12020-01-02 15:20:13 +0000507 // The reference count for this node. Guarded by |lock_|.
508 uint32_t refcount_;
Nikita Ioffe890e6f22020-06-18 17:35:08 +0100509 // Set of children of this node. All of them contain a back reference
Narayan Kamathaef84a12020-01-02 15:20:13 +0000510 // to their parent. Guarded by |lock_|.
Nikita Ioffe890e6f22020-06-18 17:35:08 +0100511 std::set<node*, NodeCompare> children_;
Narayan Kamathaef84a12020-01-02 15:20:13 +0000512 // Containing directory for this node. Guarded by |lock_|.
513 node* parent_;
514 // List of file handles associated with this node. Guarded by |lock_|.
515 std::vector<std::unique_ptr<handle>> handles_;
516 // List of directory handles associated with this node. Guarded by |lock_|.
517 std::vector<std::unique_ptr<dirhandle>> dirhandles_;
Zim329ba2c2020-09-16 14:23:26 +0100518 bool has_redacted_cache_;
Zimded1ab92021-01-15 10:36:17 +0000519 bool should_invalidate_;
Zim329ba2c2020-09-16 14:23:26 +0100520 bool deleted_;
Narayan Kamathaef84a12020-01-02 15:20:13 +0000521 std::recursive_mutex* lock_;
522
Narayan Kamath568f17a2020-02-19 13:45:29 +0000523 NodeTracker* const tracker_;
524
Narayan Kamathaef84a12020-01-02 15:20:13 +0000525 ~node() {
526 RemoveFromParent();
527
528 handles_.clear();
529 dirhandles_.clear();
Narayan Kamath568f17a2020-02-19 13:45:29 +0000530
531 tracker_->NodeDeleted(this);
Narayan Kamathaef84a12020-01-02 15:20:13 +0000532 }
533
534 friend class ::NodeTest;
535};
536
537} // namespace fuse
538} // namespace mediaprovider
539
540#endif // MEDIA_PROVIDER_JNI_MODE_INL_H_