blob: 0b4af78e4349da989365d8b21036be03f2412dc1 [file] [log] [blame]
// Copyright (C) 2018 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef IORAP_SRC_INODE2FILENAME_SEARCH_DIRECTORIES_H_
#define IORAP_SRC_INODE2FILENAME_SEARCH_DIRECTORIES_H_
#include "inode2filename/inode.h"
#include "inode2filename/system_call.h"
#include "inode2filename/inode_resolver.h"
#include <fruit/fruit.h>
#include <rxcpp/rx.hpp>
namespace iorap::inode2filename {
// TODO: rename.
using SearchMode = ProcessMode;
struct SearchDirectories {
// Type-erased subset of rxcpp::connectable_observable<?>
struct RxAnyConnectable {
// Connects to the underlying observable.
//
// This kicks off the graph, streams begin emitting items.
// This method will block until all items have been fully emitted
// and processed by any subscribers.
virtual void connect() = 0;
virtual ~RxAnyConnectable(){}
};
// Create a cold observable of inode results (a lazy stream) corresponding
// to the inode search list.
//
// A depth-first search is done on each of the root directories (in order),
// until all inodes have been found (or until all directories have been exhausted).
//
// Some internal errors may occur during emission that aren't part of an InodeResult;
// these will be sent to the error logcat and dropped.
//
// Calling this function does not begin the search.
// The returned observable will begin the search after subscribing to it.
//
// The emitted InodeResult stream has these guarantees:
// - All inodes in inode_list will eventually be emitted exactly once in an InodeResult
// - When all inodes are found, directory traversal is halted.
// - The order of emission can be considered arbitrary.
//
// Lifetime rules:
// - The observable must be fully consumed before deleting any of the SearchDirectory's
// borrowed constructor parameters (e.g. the SystemCall).
// - SearchDirectory itself can be deleted at any time after creating an observable.
rxcpp::observable<InodeResult>
FindFilenamesFromInodes(std::vector<std::string> root_directories,
std::vector<Inode> inode_list,
SearchMode mode) const;
// Create a cold observable of inode results (a lazy stream) corresponding
// to the inode search list.
//
// A depth-first search is done on each of the root directories (in order),
// until all inodes have been found (or until all directories have been exhausted).
//
// Some internal errors may occur during emission that aren't part of an InodeResult;
// these will be sent to the error logcat and dropped.
//
// Calling this function does not begin the search.
// The returned observable will begin the search after subscribing to it.
//
// The emitted InodeResult stream has these guarantees:
// - All inodes in inode_list will eventually be emitted exactly once in an InodeResult
// - When all inodes are found, directory traversal is halted.
// - The order of emission can be considered arbitrary.
//
// Lifetime rules:
// - The observable must be fully consumed before deleting any of the SearchDirectory's
// borrowed constructor parameters (e.g. the SystemCall).
// - SearchDirectory itself can be deleted at any time after creating an observable.
std::pair<rxcpp::observable<InodeResult>, std::unique_ptr<RxAnyConnectable>>
FindFilenamesFromInodesPair(std::vector<std::string> root_directories,
std::vector<Inode> inode_list,
SearchMode mode) const;
// No items on the output stream will be emitted until 'inodes' completes.
//
// The current algorithm is a naive DFS, so if it began too early it would either
// miss the search items or require traversal restarts.
//
// See above for more details.
rxcpp::observable<InodeResult>
FindFilenamesFromInodes(std::vector<std::string> root_directories,
rxcpp::observable<Inode> inodes,
SearchMode mode) const;
rxcpp::observable<InodeResult>
ListAllFilenames(std::vector<std::string> root_directories) const;
rxcpp::observable<InodeResult> FilterFilenamesForSpecificInodes(
// haystack that will be subscribed to until all in inode_list are found.
rxcpp::observable<InodeResult> all_inodes,
// key list: traverse all_inodes until we emit all results from inode_list.
std::vector<Inode> inode_list,
// all_inodes have a missing device number: use stat(2) to fill it in.
bool missing_device_number,
bool needs_verification) const;
rxcpp::observable<InodeResult> EmitAllFilenames(
// haystack that will be subscribed to until all in inode_list are found.
rxcpp::observable<InodeResult> all_inodes,
// all_inodes have a missing device number: use stat(2) to fill it in.
bool missing_device_number,
bool needs_verification) const;
// Any borrowed parameters here can also be borrowed by the observables returned by the above
// member functions.
//
// The observables must be fully consumed within the lifetime of the borrowed parameters.
INJECT(SearchDirectories(borrowed<SystemCall*> system_call))
: system_call_(system_call) {}
// TODO: is there a way to get rid of this second RxAnyConnectable parameter?
private:
// This gets passed around to lazy lambdas, so we must finish consuming any observables
// before the injected system call is deleted.
borrowed<SystemCall*> system_call_;
};
} // namespace iorap::inode2filename
#endif // IORAP_SRC_INODE2FILENAME_SEARCH_DIRECTORIES_H_