summaryrefslogtreecommitdiffstats
path: root/src/inode2filename/inode_resolver.h
blob: 218640f22b2d3222527e4f509ec2dc5c859e7d33 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Copyright (C) 2019 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_INODE_RESOLVER_H_
#define IORAP_SRC_INODE2FILENAME_INODE_RESOLVER_H_

#include "common/expected.h"
#include "inode2filename/data_source.h"
#include "inode2filename/inode.h"
#include "inode2filename/system_call.h"

#include <rxcpp/rx.hpp>

#include <memory>
#include <optional>
#include <string>
#include <vector>
namespace iorap::inode2filename {

enum class ProcessMode {
  // Test modes:
  kInProcessDirect,  // Execute the code directly.
  kInProcessIpc,     // Execute code via IPC layer using multiple threads.
  // Shipping mode:
  kOutOfProcessIpc,  // Execute code via fork+exec with IPC.

  // Note: in-process system-wide stat(2)/readdir/etc is blocked by selinux.
  // Attempting to call the test modes will fail with -EPERM.
  //
  // Use fork+exec mode in shipping configurations, which spawns inode2filename
  // as a separate command.
};

enum class VerifyKind {
  kNone,
  kStat,
};

std::vector<std::string> ToArgs(VerifyKind verify_kind);

struct InodeResolverDependencies : public DataSourceDependencies {
  ProcessMode process_mode = ProcessMode::kInProcessDirect;
  VerifyKind verify{VerifyKind::kStat};  // Filter out results that aren't up-to-date with stat(2) ?
};

std::vector<std::string> ToArgs(const InodeResolverDependencies& deps);

// Create an rx-observable chain that allows searching for inode->filename mappings given
// a set of inode keys.
class InodeResolver : public std::enable_shared_from_this<InodeResolver> {
 public:
  static std::shared_ptr<InodeResolver> Create(InodeResolverDependencies dependencies,
                                               std::shared_ptr<DataSource> data_source);  // nonnull

  // Convenience function for above: Uses DataSource::Create for the data-source.
  static std::shared_ptr<InodeResolver> Create(InodeResolverDependencies dependencies);

  // Search the associated data source to map each inode in 'inodes' to a file path.
  //
  // Observes DataSource::EmitInodes(), which is unsubscribed from early once all inodes are found.
  //
  // Notes:
  // * Searching does not begin until all 'inodes' are observed to avoid rescanning.
  // * If the observable is unsubscribed to prior to completion, searching will halt.
  //
  // Post-condition: All emitted results are in inodes, and all inodes are in emitted results.
  rxcpp::observable<InodeResult>
      FindFilenamesFromInodes(rxcpp::observable<Inode> inodes) const;
      // TODO: feels like we could turn this into a general helper?
  // Convenience function for above.
  virtual rxcpp::observable<InodeResult>
      FindFilenamesFromInodes(std::vector<Inode> inodes) const;

  // Enumerate *all* inodes available from the data source, associating it with a filepath.
  //
  // Depending on the data source (e.g. diskscan), it can take a very long time for this observable
  // to complete. The intended use-case is for development/debugging, not for production.
  //
  // Observes DataSource::EmitInodes() until it reaches #on_completed.
  //
  // Notes:
  // * If the observable is unsubscribed to prior to completion, searching will halt.
  virtual rxcpp::observable<InodeResult>
      EmitAll() const;

  // Notifies the DataSource to begin recording.
  // Some DataSources may be continuously refreshing, but only if recording is enabled.
  // To get the most up-to-date data, toggle recording before reading the inodes out.
  void StartRecording();  // XX: feels like this should be BPF-specific.

  // Notifies the DataSource to stop recording.
  // Some DataSources may be continuously refreshing, but only if recording is enabled.
  // The snapshot of data returned by e.g. #EmitAll would then not change outside of recording.
  void StopRecording();

  virtual ~InodeResolver();
 private:
  struct Impl;
  Impl* impl_;

 protected:
  InodeResolver(InodeResolverDependencies dependencies);
  InodeResolver(InodeResolverDependencies dependencies, std::shared_ptr<DataSource> data_source);
  InodeResolverDependencies& GetDependencies();
  const InodeResolverDependencies& GetDependencies() const;
};

}

#endif  // IORAP_SRC_INODE2FILENAME_INODE_RESOLVER_H_