1 // Copyright (C) 2018 The Android Open Source Project 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef IORAP_SRC_INODE2FILENAME_SEARCH_DIRECTORIES_H_ 16 #define IORAP_SRC_INODE2FILENAME_SEARCH_DIRECTORIES_H_ 17 18 #include "inode2filename/inode.h" 19 #include "inode2filename/system_call.h" 20 #include "inode2filename/inode_resolver.h" 21 22 #include <fruit/fruit.h> 23 24 #include <rxcpp/rx.hpp> 25 namespace iorap::inode2filename { 26 27 // TODO: rename. 28 using SearchMode = ProcessMode; 29 30 struct SearchDirectories { 31 // Type-erased subset of rxcpp::connectable_observable<?> 32 struct RxAnyConnectable { 33 // Connects to the underlying observable. 34 // 35 // This kicks off the graph, streams begin emitting items. 36 // This method will block until all items have been fully emitted 37 // and processed by any subscribers. 38 virtual void connect() = 0; 39 ~RxAnyConnectableSearchDirectories::RxAnyConnectable40 virtual ~RxAnyConnectable(){} 41 }; 42 43 44 // Create a cold observable of inode results (a lazy stream) corresponding 45 // to the inode search list. 46 // 47 // A depth-first search is done on each of the root directories (in order), 48 // until all inodes have been found (or until all directories have been exhausted). 49 // 50 // Some internal errors may occur during emission that aren't part of an InodeResult; 51 // these will be sent to the error logcat and dropped. 52 // 53 // Calling this function does not begin the search. 54 // The returned observable will begin the search after subscribing to it. 55 // 56 // The emitted InodeResult stream has these guarantees: 57 // - All inodes in inode_list will eventually be emitted exactly once in an InodeResult 58 // - When all inodes are found, directory traversal is halted. 59 // - The order of emission can be considered arbitrary. 60 // 61 // Lifetime rules: 62 // - The observable must be fully consumed before deleting any of the SearchDirectory's 63 // borrowed constructor parameters (e.g. the SystemCall). 64 // - SearchDirectory itself can be deleted at any time after creating an observable. 65 rxcpp::observable<InodeResult> 66 FindFilenamesFromInodes(std::vector<std::string> root_directories, 67 std::vector<Inode> inode_list, 68 SearchMode mode) const; 69 70 // Create a cold observable of inode results (a lazy stream) corresponding 71 // to the inode search list. 72 // 73 // A depth-first search is done on each of the root directories (in order), 74 // until all inodes have been found (or until all directories have been exhausted). 75 // 76 // Some internal errors may occur during emission that aren't part of an InodeResult; 77 // these will be sent to the error logcat and dropped. 78 // 79 // Calling this function does not begin the search. 80 // The returned observable will begin the search after subscribing to it. 81 // 82 // The emitted InodeResult stream has these guarantees: 83 // - All inodes in inode_list will eventually be emitted exactly once in an InodeResult 84 // - When all inodes are found, directory traversal is halted. 85 // - The order of emission can be considered arbitrary. 86 // 87 // Lifetime rules: 88 // - The observable must be fully consumed before deleting any of the SearchDirectory's 89 // borrowed constructor parameters (e.g. the SystemCall). 90 // - SearchDirectory itself can be deleted at any time after creating an observable. 91 std::pair<rxcpp::observable<InodeResult>, std::unique_ptr<RxAnyConnectable>> 92 FindFilenamesFromInodesPair(std::vector<std::string> root_directories, 93 std::vector<Inode> inode_list, 94 SearchMode mode) const; 95 96 // No items on the output stream will be emitted until 'inodes' completes. 97 // 98 // The current algorithm is a naive DFS, so if it began too early it would either 99 // miss the search items or require traversal restarts. 100 // 101 // See above for more details. 102 rxcpp::observable<InodeResult> 103 FindFilenamesFromInodes(std::vector<std::string> root_directories, 104 rxcpp::observable<Inode> inodes, 105 SearchMode mode) const; 106 107 rxcpp::observable<InodeResult> 108 ListAllFilenames(std::vector<std::string> root_directories) const; 109 110 rxcpp::observable<InodeResult> FilterFilenamesForSpecificInodes( 111 // haystack that will be subscribed to until all in inode_list are found. 112 rxcpp::observable<InodeResult> all_inodes, 113 // key list: traverse all_inodes until we emit all results from inode_list. 114 std::vector<Inode> inode_list, 115 // all_inodes have a missing device number: use stat(2) to fill it in. 116 bool missing_device_number, 117 bool needs_verification) const; 118 119 rxcpp::observable<InodeResult> EmitAllFilenames( 120 // haystack that will be subscribed to until all in inode_list are found. 121 rxcpp::observable<InodeResult> all_inodes, 122 // all_inodes have a missing device number: use stat(2) to fill it in. 123 bool missing_device_number, 124 bool needs_verification) const; 125 126 // Any borrowed parameters here can also be borrowed by the observables returned by the above 127 // member functions. 128 // 129 // The observables must be fully consumed within the lifetime of the borrowed parameters. INJECTSearchDirectories130 INJECT(SearchDirectories(borrowed<SystemCall*> system_call)) 131 : system_call_(system_call) {} 132 133 // TODO: is there a way to get rid of this second RxAnyConnectable parameter? 134 private: 135 // This gets passed around to lazy lambdas, so we must finish consuming any observables 136 // before the injected system call is deleted. 137 borrowed<SystemCall*> system_call_; 138 }; 139 140 } // namespace iorap::inode2filename 141 142 #endif // IORAP_SRC_INODE2FILENAME_SEARCH_DIRECTORIES_H_ 143