/*
 * Copyright (C) 2017 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 SRC_TRACED_PROBES_FTRACE_FTRACE_PROCFS_H_
#define SRC_TRACED_PROBES_FTRACE_FTRACE_PROCFS_H_

#include <memory>
#include <set>
#include <string>
#include <vector>

#include "perfetto/ext/base/scoped_file.h"

namespace perfetto {

class FtraceProcfs {
 public:
  static const char* const kTracingPaths[];

  // Tries creating an |FtraceProcfs| at the standard tracefs mount points.
  // Takes an optional |instance_path| such as "instances/wifi/", in which case
  // the returned object will be for that ftrace instance path.
  static std::unique_ptr<FtraceProcfs> CreateGuessingMountPoint(
      const std::string& instance_path = "");

  static std::unique_ptr<FtraceProcfs> Create(const std::string& root);

  static int g_kmesg_fd;

  explicit FtraceProcfs(const std::string& root);
  virtual ~FtraceProcfs();

  // Set the filter for syscall events. If empty, clear the filter.
  bool SetSyscallFilter(const std::set<size_t>& filter);

  // Enable the event under with the given |group| and |name|.
  bool EnableEvent(const std::string& group, const std::string& name);

  // Disable the event under with the given |group| and |name|.
  bool DisableEvent(const std::string& group, const std::string& name);

  // Returns true if the event under the given |group| and |name| exists and its
  // enable file is writeable.
  bool IsEventAccessible(const std::string& group, const std::string& name);

  // Disable all events by writing to the global enable file.
  bool DisableAllEvents();

  // Read the format for event with the given |group| and |name|.
  // virtual for testing.
  virtual std::string ReadEventFormat(const std::string& group,
                                      const std::string& name) const;

  virtual std::string ReadPageHeaderFormat() const;

  std::string GetCurrentTracer();
  // Sets the "current_tracer". Might fail with EBUSY if tracing pipes have
  // already been opened for reading.
  bool SetCurrentTracer(const std::string& tracer);
  // Resets the "current_tracer" to "nop".
  bool ResetCurrentTracer();
  bool AppendFunctionFilters(const std::vector<std::string>& filters);
  bool ClearFunctionFilters();
  bool AppendFunctionGraphFilters(const std::vector<std::string>& filters);
  bool ClearFunctionGraphFilters();

  // Get all triggers for event with the given |group| and |name|.
  std::vector<std::string> ReadEventTriggers(const std::string& group,
                                             const std::string& name) const;

  // Create an event trigger for the given |group| and |name|.
  bool CreateEventTrigger(const std::string& group,
                          const std::string& name,
                          const std::string& trigger);

  // Remove an event trigger for the given |group| and |name|.
  bool RemoveEventTrigger(const std::string& group,
                          const std::string& name,
                          const std::string& trigger);

  // Remove all event trigger for the given |group| and |name|.
  bool RemoveAllEventTriggers(const std::string& group,
                              const std::string& name);

  // Sets up any associated event trigger before enabling the event
  bool MaybeSetUpEventTriggers(const std::string& group,
                               const std::string& name);

  // Tears down any associated event trigger after disabling the event
  bool MaybeTearDownEventTriggers(const std::string& group,
                                  const std::string& name);

  // Returns true if rss_stat_throttled synthetic event is supported
  bool SupportsRssStatThrottled();

  // Read the printk formats file.
  std::string ReadPrintkFormats() const;

  // Opens the "/per_cpu/cpuXX/stats" file for the given |cpu|.
  base::ScopedFile OpenCpuStats(size_t cpu) const;

  // Read the "/per_cpu/cpuXX/stats" file for the given |cpu|.
  std::string ReadCpuStats(size_t cpu) const;

  // Set ftrace buffer size in pages.
  // This size is *per cpu* so for the total size you have to multiply
  // by the number of CPUs.
  bool SetCpuBufferSizeInPages(size_t pages);

  // Returns the number of CPUs.
  // This will match the number of tracing/per_cpu/cpuXX directories.
  size_t virtual NumberOfCpus() const;

  // Clears the trace buffers for all CPUs. Blocks until this is done.
  void ClearTrace();

  // Clears the trace buffer for cpu. Blocks until this is done.
  void ClearPerCpuTrace(size_t cpu);

  // Writes the string |str| as an event into the trace buffer.
  bool WriteTraceMarker(const std::string& str);

  // Read tracing_on and return true if tracing_on is 1, otherwise return false.
  bool GetTracingOn();

  // Write 1 to tracing_on if |on| is true, otherwise write 0.
  bool SetTracingOn(bool on);

  // Returns true if ftrace tracing is available.
  // Ftrace tracing is available iff "/current_tracer" is "nop", indicates
  // function tracing is not in use. Necessarily
  // racy: another program could enable/disable tracing at any point.
  bool IsTracingAvailable();

  // Set the clock. |clock_name| should be one of the names returned by
  // AvailableClocks. Setting the clock clears the buffer.
  bool SetClock(const std::string& clock_name);

  // Get the currently set clock.
  std::string GetClock();

  // Get all the available clocks.
  std::set<std::string> AvailableClocks();

  uint32_t ReadBufferPercent();
  bool SetBufferPercent(uint32_t percent);

  // Get all the enabled events.
  virtual std::vector<std::string> ReadEnabledEvents();

  // Open the raw pipe for |cpu|.
  virtual base::ScopedFile OpenPipeForCpu(size_t cpu);

  virtual const std::set<std::string> GetEventNamesForGroup(
      const std::string& path) const;

  // Returns the |id| for event with the given |group| and |name|. Returns 0 if
  // the event doesn't exist, or its /id file could not be read. Not typically
  // needed if already parsing the format file.
  uint32_t ReadEventId(const std::string& group, const std::string& name) const;

  std::string GetRootPath() const { return root_; }

 protected:
  // virtual and protected for testing.
  virtual bool WriteToFile(const std::string& path, const std::string& str);
  virtual bool AppendToFile(const std::string& path, const std::string& str);
  virtual bool ClearFile(const std::string& path);
  virtual bool IsFileWriteable(const std::string& path);
  virtual char ReadOneCharFromFile(const std::string& path);
  virtual std::string ReadFileIntoString(const std::string& path) const;

 private:
  // Checks the trace file is present at the given root path.
  static bool CheckRootPath(const std::string& root);

  bool WriteNumberToFile(const std::string& path, size_t value);

  const std::string root_;
};

}  // namespace perfetto

#endif  // SRC_TRACED_PROBES_FTRACE_FTRACE_PROCFS_H_
