<commit_before>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This software may be used and distributed according to the terms of the
 * GNU General Public License version 2.
 */

include "eden/fs/config/eden_config.thrift"
include "fb303/thrift/fb303_core.thrift"

namespace cpp2 facebook.eden
namespace java com.facebook.eden.thrift
namespace py facebook.eden
namespace py3 eden.fs.service

/** Thrift doesn't really do unsigned numbers, but we can sort of fake it.
 * This type is serialized as an integer value that is 64-bits wide and
 * should round-trip with full fidelity for C++ client/server, but for
 * other runtimes will have crazy results if the sign bit is ever set.
 * In practice it is impossible for us to have files that large in eden,
 * and sequence numbers will take an incredibly long time to ever roll
 * over and cause problems.
 * Once t13345978 is done, we can uncomment the cpp.type below.
 */
typedef i64 /* (cpp.type = "std::uint64_t") */
unsigned64

typedef i32 pid_t

/**
 * A backing-store-specific identifier for the root tree. For Mercurial or
 * Git, this is a 20-byte binary hash or a 40-byte hexadecimal hash.
 *
 * For other backing stores, this string may have variable length and its
 * meaning is defined by the backing-store. If possible, prefer human-readable
 * strings so they can be read in log files and error messages.
 *
 * This is named ThriftRootId to not conflict with the RootId class, but
 * perhaps this Thrift module should be placed in its own namespace.
 */
typedef binary ThriftRootId

typedef binary ThriftObjectId

/**
 * A source control hash.
 *
 * This should normally be a 20-byte binary value, however the edenfs server
 * will accept BinaryHash arguments as 40-byte hexadecimal strings as well.
 * Data returned by the edenfs server in a BinaryHash field will always be a
 * 20-byte binary value.
 */
typedef binary BinaryHash

/**
 * So, you thought that a path was a string?
 * Paths in posix are arbitrary byte strings with some pre-defined special
 * characters.  On modern systems they tend to be represented as UTF-8 but
 * there is no guarantee.  We use the `PathString` type as symbolic way
 * to indicate that you may need to perform special processing to safely
 * interpret the path data on your system.
 */
typedef binary PathString

/**
 * A customizable type to be returned with an EdenError, helpful for catching
 * and having custom client logic to handle specfic error cases
 */
enum EdenErrorType {
  /** The errorCode property is a posix errno value */
  POSIX_ERROR = 0,
  /** The errorCode property is a win32 error value */
  WIN32_ERROR = 1,
  /** The errorCode property is a windows NT HResult error value */
  HRESULT_ERROR = 2,
  /**
   * An argument passed to thrift was invalid. errorCode will be set to EINVAL
   */
  ARGUMENT_ERROR = 3,
  /** An error occurred. errorCode will be not set */
  GENERIC_ERROR = 4,
  /** The mount generation changed. errorCode will be set to ERANGE */
  MOUNT_GENERATION_CHANGED = 5,
  /** The journal has been truncated. errorCode will be set to EDOM */
  JOURNAL_TRUNCATED = 6,
  /**
   * The thrift funtion that receives this in an error is being called while
   * a checkout is in progress. errorCode will not be set.
   */
  CHECKOUT_IN_PROGRESS = 7,
  /**
  * The thrift function that receives this is an error is being called with a
  * parent that is not the current parent. errorCode will not be set.
  */
  OUT_OF_DATE_PARENT = 8,
}

exception EdenError {
  1: required string message;
  2: optional i32 errorCode;
  3: EdenErrorType errorType;
} (message = 'message')

exception NoValueForKeyError {
  1: string key;
}

/**
 * Information about the running edenfs daemon.
 */
struct DaemonInfo {
  1: i32 pid;
  /**
   * List of command line arguments, including the executable name,
   * given to the edenfs process.
   */
  2: list<string> commandLine;
  /**
   * The service status.
   *
   * This is almost the same value reported by
   * fb303_core.BaseService.getStatus(). fb303_core.BaseService.getStatus()
   * only returns the Thrift server status and does not understand mounts or
   * graceful restarts.
   */
  3: optional fb303_core.fb303_status status;
  /**
   * The uptime of the edenfs daemon
   * Same data from /proc/pid/stat
   */
  4: optional float uptime;
}

/**
* Information about the privhelper process
*/
struct PrivHelperInfo {
  1: bool connected;
}

/**
 * The current running state of an EdenMount.
 */
enum MountState {
  /**
   * The EdenMount object has been constructed but has not started
   * initializing.
   */
  UNINITIALIZED = 0,
  /**
   * The mount point is currently initializing and loading necessary state
   * (such as the root directory contents) before it can ask the kernel to
   * mount it.
   */
  INITIALIZING = 1,
  /**
   * The mount point has loaded its local state needed to start mounting
   * but has not actually started mounting yet.
   */
  INITIALIZED = 2,
  /**
   * Starting to mount fuse.
   */
  STARTING = 3,
  /**
   * The EdenMount is running normally.
   */
  RUNNING = 4,
  /**
   * Encountered an error while starting fuse mount.
   */
  FUSE_ERROR = 5,
  /**
   * EdenMount::shutdown() has been called, but it is not complete yet.
   */
  SHUTTING_DOWN = 6,
  /**
   * EdenMount::shutdown() has completed, but there are still outstanding
   * references so EdenMount::destroy() has not been called yet.
   *
   * When EdenMount::destroy() is called the object can be destroyed
   * immediately.
   */
  SHUT_DOWN = 7,
  /**
   * EdenMount::destroy() has been called, but the shutdown is not complete
   * yet.  There are no remaining references to the EdenMount at this point,
   * so when the shutdown completes it will be automatically destroyed.
   */
  DESTROYING = 8,
  /**
   * An error occurred during mount initialization.
   *
   * This state is used for errors that occur during the INITIALIZING phase,
   * before we have attempted to start the FUSE mount.
   */
  INIT_ERROR = 9,
} (cpp2.enum_type = 'uint32_t')

struct MountInfo {
  1: PathString mountPoint;
  2: PathString edenClientPath;
  3: MountState state;
  4: optional PathString backingRepoPath;
}

struct MountArgument {
  1: PathString mountPoint;
  2: PathString edenClientPath;
  3: bool readOnly;
}

union SHA1Result {
  1: BinaryHash sha1;
  2: EdenError error;
}

/**
 * Effectively a `struct timespec`
 */
struct TimeSpec {
  1: i64 seconds;
  2: i64 nanoSeconds;
}

/**
 * Information about filesystem entries that can be retrieved solely
 * from the tree structure, without having to fetch the actual child
 * objects from source control.
 */
struct EntryInformation {
  1: Dtype dtype;
}

union EntryInformationOrError {
  1: EntryInformation info;
  2: EdenError error;
}

/**
 * Subset of stat() data returned from getFileInformation())
 */
struct FileInformation {
  1: unsigned64 size; // wish thrift had unsigned numbers
  2: TimeSpec mtime;
  3: i32 mode; // mode_t
}

/** Holds information about a file, or an error in retrieving that info.
 * The most likely error will be ENOENT, implying that the file doesn't exist.
 */
union FileInformationOrError {
  1: FileInformation info;
  2: EdenError error;
}

/**
 * File Attributes that can be requested with getAttributesFromFiles(). All attributes
 * should be a power of 2. OR the requested attributes together to get a bitmask.
 */
enum FileAttributes {
  NONE = 0,
  SHA1_HASH = 1,
  FILE_SIZE = 2,
/* NEXT_ATTR = 2^x */
} (cpp2.enum_type = 'uint64_t')

/**
 * Subset of attributes for a single file returned by getAttributesFromFiles()
 */
struct FileAttributeData {
  1: optional BinaryHash sha1;
  2: optional i64 fileSize;
}

/**
 * Attributes for a file or information about error encountered when accessing file attributes.
 * The most likely error will be ENOENT, implying that the file doesn't exist.
 */
union FileAttributeDataOrError {
  1: FileAttributeData data;
  2: EdenError error;
}

/**
 *
 * Ensure that all inflight working copy modification have completed.
 *
 * On some platforms, EdenFS is processing working copy modifications
 * callbacks from the platform in an asynchronous manner, which means that by
 * the time a write/creat/mkdir/unlink/etc syscall returns from the kernel,
 * EdenFS may not have updated its internal state.
 *
 * Thus, an application making changes to the working copy and quickly
 * requesting EdenFS to perform an operation on it will race with EdenFS
 * updating its internal state and may thus get stale data.
 *
 * To avoid this, EdenFS queries need to internally synchronize the working
 * copy before performing the query itself. This structure defines how EdenFS
 * will do this.
 *
 * Applications that care about synchronizing EdenFS up to a certain point in
 * time are expected to set a non-zero syncTimeout once to synchronize EdenFS
 * and then issue all their thrift requests with a syncTimeout of 0.
 */
struct SyncBehavior {
  // How many seconds to wait for the working copy to be synchronized. A value
  // of 0 will not perform any working copy synchronization.
  // If left unset, EdenFS will use a default synchronization timeout.
  1: optional i64 syncTimeoutSeconds;
}

/**
 * Parameters for the getAttributesFromFiles() function
 */
struct GetAttributesFromFilesParams {
  1: PathString mountPoint;
  2: list<PathString> paths;
  3: unsigned64 requestedAttributes;
  4: SyncBehavior sync;
}

/**
 * Return value for the getAttributesFromFiles() function.
 * The returned list of attributes corresponds to the input list of
 * paths; eg; res[0] holds the information for paths[0].
 */
struct GetAttributesFromFilesResult {
  1: list<FileAttributeDataOrError> res;
}

/** reference a point in time in the journal.
 * This can be used to reason about a point in time in a given mount point.
 * The mountGeneration value is opaque to the client.
 */
struct JournalPosition {
  /** An opaque but unique number within the scope of a given mount point.
   * This is used to determine when sequenceNumber has been invalidated. */
  1: i64 mountGeneration;

  /** Monotonically incrementing number
   * Each journalled change causes this number to increment. */
  2: unsigned64 sequenceNumber;

  /** Records the snapshot hash at the appropriate point in the journal */
  3: ThriftRootId snapshotHash;
}

/**
 * Holds information about a set of paths that changed between two points.
 * fromPosition, toPosition define the time window.
 * paths holds the list of paths that changed in that window.
 *
 * This type is quasi-deprecated. It has multiple API problems and should be
 * rethought when we have a chance to make a breaking change.
 */
struct FileDelta {
  /**
   * The fromPosition passed to getFilesChangedSince
   */
  1: JournalPosition fromPosition;
  /**
   * The current position at the time that getFilesChangedSince was called
  */
  2: JournalPosition toPosition;
  /**
   * The union of changedPaths and createdPaths contains the total set of paths
   * changed in the overlay between fromPosition and toPosition.
   * Disjoint with createdPaths.
   */
  3: list<PathString> changedPaths;
  /**
   * The set of paths created between fromPosition and toPosition.
   * Used by Watchman to search for cookies and to populate its 'new' field.
   * Disjoint with changedPaths.
   */
  4: list<PathString> createdPaths;
  /**
   * Deprecated - always empty.
   */
  5: list<PathString> removedPaths;
  /**
   * When fromPosition.snapshotHash != toPosition.snapshotHash this holds
   * the union of the set of files whose ScmFileStatus differed from the
   * committed fromPosition hash before the hash changed, and the set of
   * files whose ScmFileStatus differed from the committed toPosition hash
   * after the hash was changed.  This list of files represents files
   * whose state may have changed as part of an update operation, but
   * in ways that may not be able to be extracted solely by performing
   * source control diff operations on the from/to hashes.
   */
  6: list<PathString> uncleanPaths;
  /**
   * Contains the list of commit transitions in this range. If only files
   * have been changed, the list has one entry. Otherwise, it has size N + 1,
   * where N is the number of checkout operations.
   *
   * This list's items may not be unique: [A, B, A] is a common sequence,
   * and [A, B, C] has a different meaning than [A, C, B].
   *
   * Subsumes fromPosition.snapshotHash and toPosition.snapshotHash.
   */
  7: list<ThriftRootId> snapshotTransitions;
}

struct DebugGetRawJournalParams {
  1: PathString mountPoint;
  2: optional i32 limit;
  3: i32 fromSequenceNumber;
}

struct DebugPathChangeInfo {
  1: bool existedBefore;
  2: bool existedAfter;
}

/**
 * A fairly direct modeling of the underlying JournalDelta data structure.
 */
struct DebugJournalDelta {
  1: JournalPosition fromPosition;
  2: JournalPosition toPosition;
  3: map<PathString, DebugPathChangeInfo> changedPaths;
  4: set<PathString> uncleanPaths;
}

struct DebugGetRawJournalResponse {
  2: list<DebugJournalDelta> allDeltas;
}

/**
 * Classifies the change of the state of a file between and old and new state
 * of the repository. Most commonly, the "old state" is the parent commit while
 * the "new state" is the working copy.
 */
enum ScmFileStatus {
  /**
   * File is present in the new state, but was not present in old state.
   */
  ADDED = 0x0,

  /**
   * File is present in both the new and old states, but its contents or
   * file permissions have changed.
   */
  MODIFIED = 0x1,

  /**
   * File was present in the old state, but is not present in the new state.
   */
  REMOVED = 0x2,

  /**
   * File is present in the new state, but it is ignored according to the rules
   * of the new state.
   */
  IGNORED = 0x3,
}

struct ScmStatus {
  1: map<PathString, ScmFileStatus> entries;

  /**
   * A map of { path -> error message }
   *
   * If any errors occured while computing the diff they will be reported here.
   * The results listed in the entries field may not be accurate for any paths
   * listed in this error field.
   *
   * This map will be empty if no errors occurred.
   */
  2: map<PathString, string> errors;
}

/** Option for use with checkOutRevision(). */
enum CheckoutMode {
  /**
   * Perform a "normal" checkout, analogous to `hg checkout` in Mercurial. Files
   * in the working copy will be changed to reflect the destination snapshot,
   * though files with conflicts will not be modified.
   */
  NORMAL = 0,

  /**
   * Do not checkout: exercise the checkout logic to discover potential
   * conflicts.
   */
  DRY_RUN = 1,

  /**
   * Perform a "forced" checkout, analogous to `hg checkout --clean` in
   * Mercurial. Conflicts between the working copy and destination snapshot will
   * be forcibly ignored in favor of the state of the new snapshot.
   */
  FORCE = 2,
}

enum ConflictType {
  /**
   * We failed to update this particular path due to an error
   */
  ERROR = 0,
  /**
   * A locally modified file was deleted in the new Tree
   */
  MODIFIED_REMOVED = 1,
  /**
   * An untracked local file exists in the new Tree
   */
  UNTRACKED_ADDED = 2,
  /**
   * The file was removed locally, but modified in the new Tree
   */
  REMOVED_MODIFIED = 3,
  /**
   * The file was removed locally, and also removed in the new Tree.
   */
  MISSING_REMOVED = 4,
  /**
   * A locally modified file was modified in the new Tree
   * This may be contents modifications, or a file type change (directory to
   * file or vice-versa), or permissions changes.
   */
  MODIFIED_MODIFIED = 5,
  /**
   * A directory was supposed to be removed or replaced with a file,
   * but it contains untracked files preventing us from updating it.
   */
  DIRECTORY_NOT_EMPTY = 6,
}

/**
 * Details about conflicts or errors that occurred during a checkout operation
 */
struct CheckoutConflict {
  1: PathString path;
  2: ConflictType type;
  3: string message;
}

struct ScmBlobMetadata {
  1: i64 size;
  2: BinaryHash contentsSha1;
}

struct ScmTreeEntry {
  1: binary name;
  2: i32 mode;
  3: ThriftObjectId id;
}

/*
 * Bits passed into debugInodeStatus to control the result set.
 * 0 is legacy behavior, equivalent to DIS_REQUIRE_LOADED | DIS_COMPUTE_BLOB_SIZES
 */

/**
 * No effect other than avoiding the legacy behavior.
 */
const i64 DIS_ENABLE_FLAGS = 1;

/**
 * Only return inodes currently loaded in memory.
 */
const i64 DIS_REQUIRE_LOADED = 2;

/**
 * Only return materialized inodes.
 */
const i64 DIS_REQUIRE_MATERIALIZED = 4;

/**
 * Return accurate blob sizes, which may require fetching blob metadata from
 * the backing store.
 */
const i64 DIS_COMPUTE_BLOB_SIZES = 8;

/**
 * Returns accurate mode_t bits, including ownership. When unset, only
 * the dtype bits are set.
 */
const i64 DIS_COMPUTE_ACCURATE_MODE = 16;

struct TreeInodeEntryDebugInfo {
  /**
   * The entry name.  This is just a PathComponent, not the full path
   */
  1: binary name;
  /**
   * The inode number, or 0 if no inode number has been assigned to
   * this entry
   */
  2: i64 inodeNumber;
  /**
   * The entry mode_t value
   */
  3: i32 mode;
  /**
   * True if an InodeBase object exists for this inode or not.
   */
  4: bool loaded;
  /**
   * True if an the inode is materialized in the overlay
   */
  5: bool materialized;
  /**
   * If materialized is false, hash contains the ID of the underlying source
   * control Blob or Tree.
   */
  6: ThriftObjectId hash;
  /**
   * Size of the file in bytes. It won't be set for directories.
   */
  7: optional i64 fileSize;
}

struct GetFetchedFilesResult {
  1: map<string, set<PathString>> fetchedFilePaths;
}

struct WorkingDirectoryParents {
  1: ThriftRootId parent1;
  // This field is never used by EdenFS.
  2: optional ThriftRootId parent2;
}

struct TreeInodeDebugInfo {
  1: i64 inodeNumber;
  2: binary path;
  3: bool materialized;
  // Traditionally, treeHash was a 20-byte binary hash, but now it's an
  // arbitrary-length human-readable string.
  4: ThriftObjectId treeHash;
  5: list<TreeInodeEntryDebugInfo> entries;
  6: i64 refcount;
}

struct InodePathDebugInfo {
  1: PathString path;
  2: bool loaded;
  3: bool linked;
}

struct ActivityRecorderResult {
  // 0 if the operation has failed. For example,
  // fail to start recording due to file permission issue
  // or fail to stop recording due to no active subscriber.
  1: i64 unique;
  2: optional PathString path;
}

struct ListActivityRecordingsResult {
  1: list<ActivityRecorderResult> recordings;
}

struct SetLogLevelResult {
  1: bool categoryCreated;
}

struct JournalInfo {
  1: i64 entryCount;
  // The estimated memory used by the journal in bytes
  2: i64 memoryUsage;
  // The duration of the journal in seconds
  3: i64 durationSeconds;
}

/**
 * Struct to store Information about inodes in a mount point.
 */
struct MountInodeInfo {
  2: i64 unloadedInodeCount;
  4: i64 loadedFileCount;
  5: i64 loadedTreeCount;
}

struct CacheStats {
  1: i64 entryCount;
  2: i64 totalSizeInBytes;
  3: i64 hitCount;
  4: i64 missCount;
  5: i64 evictionCount;
  6: i64 dropCount;
}

/*
 * Bits that control the stats returned from  getStatInfo
 */
const i64 STATS_MOUNTS_STATS = 0x1;
const i64 STATS_COUNTERS = 0x2;
const i64 STATS_SMAPS = 0x4;
const i64 STATS_PRIVATE_BYTES = 0x8;
const i64 STATS_RSS_BYTES = 0x10;
const i64 STATS_CACHE_STATS = 0x20;
const i64 STATS_ALL = 0xFFFF;

/**
 * Struct to store fb303 counters from ServiceData.getCounters() and inode
 * information of all the mount points.
 */
struct InternalStats {
  /**
  * fbf303 counter of inodes unloaded by periodic job.
  * Populated if STATS_COUNTERS is set.
  */
  1: optional i64 periodicUnloadCount;
  /**
   * counters is the list of fb303 counters, key is the counter name, value is the
   * counter value.
   * Populated if STATS_COUNTERS is set.
   */
  2: optional map<string, i64> counters;
  /**
   * mountPointInfo is a map whose key is the path of the mount point and value
   * is the details like number of loaded inodes,unloaded inodes in that mount
   * and number of materialized inodes in that mountpoint.
   * Populated if STATS_MOUNTS_STATS is set.
   */
  3: optional map<PathString, MountInodeInfo> mountPointInfo;
  /**
   * Linux-only: the contents of /proc/self/smaps, to be parsed by the caller.
   * Populated if STATS_SMAPS is set.
   */
  4: optional binary smaps;
  /**
   * Linux-only: privateBytes populated from contents of /proc/self/smaps.
   * Populated with current value (the fb303 counters value is an average).
   * Populated if STATS_PRIVATE_BYTES is set.
   */
  5: optional i64 privateBytes;
  /**
   * Linux-only: vmRSS bytes is populated from contents of /proc/self/stats.
   * Populated with current value (the fb303 counters value is an average).
   * Populated if STATS_RSS_BYTES is set.
   */
  6: optional i64 vmRSSBytes;
  /**
   * Statistics about the in-memory blob cache.
   * Populated if STATS_CACHE_STATS is set.
   */
  7: optional CacheStats blobCacheStats;
  /**
   * mountPointJournalInfo is a map whose key is the path of the mount point
   * and whose value is information about the journal on that mount
   * Populated if STATS_MOUNTS_STATS is set.
   */
  8: optional map<PathString, JournalInfo> mountPointJournalInfo;
  /**
   * Statistics about the in-memory tree cache.
   * Populated if STATS_CACHE_STATS is set.
   */
  9: optional CacheStats treeCacheStats;
}

struct FuseCall {
  // This field is deprecated because its use is not worth the TraceBus
  // storage. It may be brought back in some other form.
  //1: i32 len;

  2: i32 opcode;
  // FUSE supplies a unique ID, but it is recycled so quickly that it's not
  // very useful. We report our own process-unique ID.
  3: i64 unique;
  4: i64 nodeid;
  5: i32 uid;
  6: i32 gid;
  7: pid_t pid;

  8: string opcodeName;
  9: optional string processName;
}

struct NfsCall {
  1: i32 xid;
  2: i32 procNumber;
  3: string procName;
}

enum PrjfsTraceCallType {
  INVALID = 0,
  /* Write operations */
  FILE_OPENED = 1,
  NEW_FILE_CREATED = 2,
  FILE_OVERWRITTEN = 3,
  PRE_DELETE = 4,
  PRE_RENAME = 5,
  PRE_SET_HARDLINK = 6,
  FILE_RENAMED = 7,
  HARDLINK_CREATED = 8,
  FILE_HANDLE_CLOSED_NO_MODIFICATION = 9,
  FILE_HANDLE_CLOSED_FILE_MODIFIED = 10,
  FILE_HANDLE_CLOSED_FILE_DELETED = 11,
  FILE_PRE_CONVERT_TO_FULL = 12,
  /* Read operations */
  START_ENUMERATION = 13,
  END_ENUMERATION = 14,
  GET_ENUMERATION_DATA = 15,
  GET_PLACEHOLDER_INFO = 16,
  QUERY_FILE_NAME = 17,
  GET_FILE_DATA = 18,
  CANCEL_COMMAND = 19,
}

struct PrjfsCall {
  1: i32 commandId;
  2: i32 pid;
  3: PrjfsTraceCallType callType;
}

struct GetConfigParams {
  // Whether to reload the config from disk to make sure it is up-to-date
  1: eden_config.ConfigReloadBehavior reload = eden_config.ConfigReloadBehavior.AutoReload;
}

struct GetStatInfoParams {
  // a bitset that indicates the requested stats. 0 indicates all stats are requested.
  1: i64 statsMask;
}

/**
 * A representation of the system-dependent dirent::d_type field.
 * The bits and their interpretation is system dependent.
 * This value is u8 on all systems that implement it.  We
 * use i16 to pass this through thrift, which doesn't have unsigned
 * numbers
 */
typedef i16 OsDtype

/**
 * These numbers match up with Linux and macOS.
 * Windows doesn't have dtype_t, but a subset of these map to and from
 * the GetFileType and dwFileAttributes equivalents.
 *
 * Dtype and OsDtype can be cast between each other on all platforms.
 */
enum Dtype {
  UNKNOWN = 0,
  FIFO = 1, // DT_FIFO
  CHAR = 2, // DT_CHR
  DIR = 4, // DT_DIR
  BLOCK = 6, // DT_BLK
  REGULAR = 8, // DT_REG
  LINK = 10, // DT_LNK
  SOCKET = 12, // DT_SOCK
  WHITEOUT = 14, // DT_WHT
}

struct PredictiveFetch {
  // Number of directories to glob. If not specified, a default value (predictivePrefetchProfileSize in EdenConfig.h) is used.
  1: optional i32 numTopDirectories;
  // Fetch the most accessed diectories by user specified. If not specified, user is derived from the server state.
  2: optional string user;
  // Fetch the most accessed diectories in repository specified. If not specified, repo is derived from the mount.
  3: optional string repo;
  // Optional query parameter: fetch top most accessed directories with specified Operating System
  4: optional string os;
  // Optional query parameter: fetch top most accessed directories after startTime
  5: optional unsigned64 startTime;
  // Optional query parameter: fetch top most accessed directories before endTime
  6: optional unsigned64 endTime;
}
/** Params for globFiles(). */
struct GlobParams {
  1: PathString mountPoint;
  2: list<string> globs;
  3: bool includeDotfiles;
  // if true, prefetch matching blobs
  4: bool prefetchFiles;
  // if true, don't populate matchingFiles in the Glob
  // results.  This only really makes sense with prefetchFiles.
  5: bool suppressFileList;
  6: bool wantDtype;
  // Commit hashes for the revisions against which the globs should be
  // evaluated, if this is empty then globFiles will fall back to using only
  // the current revision.
  // If eden moves away from commit hashes this may become the tree hash
  // for the root tree agains which this glob should be evaluated.
  // There should be no duplicates in this list. If there are then
  // there maybe duplicate machingFile and originHash pairs in the coresponding
  // output Glob.
  7: list<ThriftRootId> revisions;
  // This has no effect.
  8: bool prefetchMetadata = true;
  // The directory from which the glob should be evaluated. Defaults to the
  // repository root.
  9: PathString searchRoot;
  // If set, will run the prefetch but will not wait for the result.
  10: bool background = false;
  // When set, the globs list must be empty and the globbing pattern will be obtained
  // from an online service.
  11: optional PredictiveFetch predictiveGlob;
  // Normally the returned file list will contain both files and directories.
  // Some clients would like to see only lists of files, this option tells us
  // wether to filter or not.
  // Note for Eden developers: when this is false the matchingFiles fileList
  // will not actually be the list that is fed into the backing store to prefetch.
  12: bool listOnlyFiles = false;
  // Should this glob query also synchronize the working copy?
  13: SyncBehavior sync;
}

struct Glob {
  /**
   * matchingFiles can contain duplicate values and is not guaranteed to be
   * sorted. However, no duplicates may have the same originCommits (note this
   * is not true should the input GlobParams contain duplicate revisions) .
   */
  1: list<PathString> matchingFiles;
  2: list<OsDtype> dtypes;
  /**
   * Currently these are the commit hash for the commit to which this file
   * belongs. But should eden move away from commit hashes this may become
   * the tree hash of the root tree to which this file belongs.
   */
  3: list<binary> originHashes;
}

struct AccessCounts {
  1: i64 fsChannelTotal;
  2: i64 fsChannelReads;
  3: i64 fsChannelWrites;
  4: i64 fsChannelBackingStoreImports;
  5: i64 fsChannelDurationNs;
  6: i64 fsChannelMemoryCacheImports;
  7: i64 fsChannelDiskCacheImports;
}

struct MountAccesses {
  1: map<pid_t, AccessCounts> accessCountsByPid;
  2: map<pid_t, i64> fetchCountsByPid;
}

struct GetAccessCountsResult {
  1: map<pid_t, binary> cmdsByPid;
  2: map<PathString, MountAccesses> accessesByMount;
// TODO: Count the number of thrift requests
// 3: map<pid_t, AccessCount> thriftAccesses
}

enum TracePointEvent {
  // Start of a new block
  START = 0,
  // End of a block
  STOP = 1,
}

struct TracePoint {
  // Holds nanoseconds since the epoch
  1: i64 timestamp;
  // Opaque identifier for the entire trace - used to associate this
  // tracepoint with other tracepoints across an entire request
  2: i64 traceId;
  // Opaque identifier for this "block" where a block is some logical
  // piece of work with a well-defined start and stop point
  3: i64 blockId;
  // Opaque identifer for the parent block from which the current
  // block was constructed - used to create causal relationships
  // between blocks
  4: i64 parentBlockId;
  // The name of the block, only set on the tracepoint starting the
  // block, must point to a statically allocated cstring
  5: string name = "";
  // What event this trace point represents
  6: TracePointEvent event;
}

struct FaultDefinition {
  1: string keyClass;
  2: string keyValueRegex;
  // If count is non-zero this fault will automatically expire after it has
  // been hit count times.
  3: i64 count;
  // If block is true the fault will block until explicitly unblocked later.
  // delayMilliseconds and errorMessage will be ignored if block is true
  4: bool block;
  5: i64 delayMilliseconds;
  6: optional string errorType;
  7: optional string errorMessage;
}

struct RemoveFaultArg {
  1: string keyClass;
  2: string keyValueRegex;
}

struct UnblockFaultArg {
  1: optional string keyClass;
  2: optional string keyValueRegex;
  3: optional string errorType;
  4: optional string errorMessage;
}

struct GetScmStatusResult {
  1: ScmStatus status;
  // The version of the EdenFS daemon.
  // This is returned since we usually want status calls to be able to check
  // the current EdenFS version and warn the user if EdenFS is running an old
  // or known-bad version.
  2: string version;
}

struct GetScmStatusParams {
  /**
   * The Eden checkout to query
   */
  1: PathString mountPoint;

  /**
   * The commit ID of the current working directory parent commit.
   *
   * An error will be returned if this is not actually the current parent
   * commit.  This behavior exists to support callers that do not perform their
   * own external synchronization around access to the current parent commit,
   * like Mercurial.
   */
  2: ThriftRootId commit;

  /**
   * Whether ignored files should be reported in the results.
   *
   * Some special source-control related files (e.g., inside the .hg or .git
   * directory) will never be reported even when listIgnored is true.
   */
  3: bool listIgnored = false;
}

/**
  * BackingStore object type. Caller will response to verify the type of the content
  * matching the parameters passed. Exception will be thrown if type mismatch.
  */
enum ObjectType {
  TREE = 0,
  REGULAR_FILE = 1,
  EXECUTABLE_FILE = 2,
  SYMLINK = 3,
}

struct SetPathObjectIdParams {
  1: PathString mountPoint;
  2: PathString path;
  3: ThriftObjectId objectId;
  4: ObjectType type;
  5: CheckoutMode mode;
  // Extra request infomation. i.e. build uuid, cache session id.
  6: optional map<string, string> requestInfo;
}

struct SetPathObjectIdResult {
  1: list<CheckoutConflict> conflicts;
}

struct CheckOutRevisionParams {
  /**
   * The hg root manifest that corresponds to the commit (if known).
   *
   * When a commit is newly created, EdenFS won't know the commit
   * to root-manifest mapping for the commit, and won't be able to find
   * out from the import helper until the import helper re-opens the
   * repo.  To speed this up, Mercurial clients may optionally provide
   * the hash of the root manifest directly, so that EdenFS doesn't
   * need to look it up.
   */
  1: optional BinaryHash hgRootManifest;
}

struct ResetParentCommitsParams {
  /**
   * The hg root manifest that corresponds to the commit (if known).
   *
   * When a commit is newly created, EdenFS won't know the commit
   * to root-manifest mapping for the commit, and won't be able to find
   * out from the import helper until the import helper re-opens the
   * repo.  To speed this up, Mercurial clients may optionally provide
   * the hash of the root manifest directly, so that EdenFS doesn't
   * need to look it up.
   */
  1: optional BinaryHash hgRootManifest;
}

struct RemoveRecursivelyParams {
  1: PathString mountPoint;
  2: PathString path;
  3: SyncBehavior sync;
}

struct SynchronizeWorkingCopyParams {
  1: SyncBehavior sync;
}

service EdenService extends fb303_core.BaseService {
  list<MountInfo> listMounts() throws (1: EdenError ex);
  void mount(1: MountArgument info) throws (1: EdenError ex);
  void unmount(1: PathString mountPoint) throws (1: EdenError ex);

  /**
   * Potentially check out the specified snapshot, reporting conflicts (and
   * possibly errors), as appropriate.
   *
   * If the checkoutMode is FORCE, the working directory will be forcibly
   * updated to the contents of the new snapshot, even if there were conflicts.
   * Conflicts will still be reported in the return value, but the files will be
   * updated to their new state.
   *
   * If the checkoutMode is NORMAL, files with conflicts will be left
   * unmodified. Files that are untracked in both the source and destination
   * snapshots are always left unchanged, even if force is true.
   *
   * If the checkoutMode is DRY_RUN, then no files are modified in the working
   * copy and the current snapshot does not change. However, potential conflicts
   * are still reported in the return value.
   *
   * On successful return from this function (unless it is a DRY_RUN), the mount
   * point will point to the new snapshot, even if some paths had conflicts or
   * errors. The caller is responsible for taking appropriate action to update
   * these paths as desired after checkOutRevision() returns.
   *
   * Note: this internally synchronize the working copy.
   */
  list<CheckoutConflict> checkOutRevision(
    1: PathString mountPoint,
    2: ThriftRootId snapshotHash,
    3: CheckoutMode checkoutMode,
    4: CheckOutRevisionParams params,
  ) throws (1: EdenError ex);

  /**
   * Reset the working directory's parent commits, without changing the working
   * directory contents.
   *
   * This operation is equivalent to `git reset --soft` or `hg reset --keep`
   */
  void resetParentCommits(
    1: PathString mountPoint,
    2: WorkingDirectoryParents parents,
    3: ResetParentCommitsParams params,
  ) throws (1: EdenError ex);

  /**
   * Ensure that all inflight working copy modification have completed.
   *
   * On some platforms, EdenFS is processing working copy modifications
   * callbacks from the platform in an asynchronous manner, which means that by
   * the time a write/creat/mkdir/unlink/etc syscall returns from the kernel,
   * EdenFS may not have updated its internal state.
   *
   * Thus, an application making changes to the working copy and quickly
   * requesting EdenFS to perform an operation on it will race with EdenFS
   * updating its internal state and may thus get stale data.
   *
   * To avoid this, applications can call this method prior to issuing other
   * Thrift requests (such as getSHA1, globFiles, etc) to wait for EdenFS to
   * update its internal state. Applications that care about synchronizing
   * EdenFS up to a certain point in time are expected to call this once and
   * then issue all their thrift requests without synchronizing.
   *
   * As an alternative, applications may also set the SyncBehavior of a Thrift
   * method to a non-zero value to achieve the same result.
   *
   * Some Thrift methods are implicitely synchronizing, their documentation
   * will state it.
   */
  void synchronizeWorkingCopy(
    1: PathString mountPoint,
    2: SynchronizeWorkingCopyParams params,
  ) throws (1: EdenError ex);

  /**
   * For each path, returns an EdenError instead of the SHA-1 if any of the
   * following occur:
   * - path is the empty string.
   * - path identifies a non-existent file.
   * - path identifies something that is not an ordinary file (e.g., symlink
   *   or directory).
   *
   * Note: may return stale data if synchronizeWorkingCopy isn't called, and if
   * the SyncBehavior specify a 0 timeout. see the documentation for both of
   * these for more details.
   */
  list<SHA1Result> getSHA1(
    1: PathString mountPoint,
    2: list<PathString> paths,
    3: SyncBehavior sync,
  ) throws (1: EdenError ex);

  /**
   * Returns a list of paths relative to the mountPoint. DEPRECATED!
   */
  list<PathString> getBindMounts(1: PathString mountPoint) throws (
    1: EdenError ex,
  );

  /**
   * On systems that support bind mounts, establish a bind mount within the
   * repo such that `mountPoint / repoPath` is redirected to `targetPath`.
   * If `repoPath` is already a bind mount managed by eden, this function
   * will throw an error.
   * If `repoPath` is not a directory then it will be created similar to
   * running `mkdir -p mountPoint/repoPath` and then the bind mount
   * will be established.
   * If `repoPath` exists and is not a directory, an error will be thrown.
   * If the bind mount cannot be set up, an error will be thrown.
   */
  void addBindMount(
    1: PathString mountPoint,
    2: PathString repoPath,
    3: PathString targetPath,
  ) throws (1: EdenError ex);

  /**
   * Removes the bind mount specified by `repoPath` from the set of managed
   * bind mounts.
   * If `repoPath` is not a bind mount managed by eden, this function
   * will throw an error.
   * If the bind mount cannot be removed, an error will be thrown.
   */
  void removeBindMount(
    1: PathString mountPoint,
    2: PathString repoPath,
  ) throws (1: EdenError ex);

  /** Returns the sequence position at the time the method is called.
   * Returns the instantaneous value of the journal sequence number.
   */
  JournalPosition getCurrentJournalPosition(1: PathString mountPoint) throws (
    1: EdenError ex,
  );

  /** Returns the set of files (and dirs) that changed since a prior point.
   * If fromPosition.mountGeneration is mismatched with the current
   * mountGeneration, throws an EdenError with errorCode = ERANGE.
   * If the domain required by fromPosition goes past the Journal's memory,
   * throws an EdenError with errorCode = EDOM.
   * This indicates that eden cannot compute the delta for the requested
   * range.  The client will need to recompute a new baseline using
   * other available functions in EdenService.
   */
  FileDelta getFilesChangedSince(
    1: PathString mountPoint,
    2: JournalPosition fromPosition,
  ) throws (1: EdenError ex);

  /** Sets the memory limit on the journal such that the journal will forget
   * old data to keep itself under a certain estimated memory use.
   */
  void setJournalMemoryLimit(1: PathString mountPoint, 2: i64 limit) throws (
    1: EdenError ex,
  );

  /** Gets the memory limit on the journal
   */
  i64 getJournalMemoryLimit(1: PathString mountPoint) throws (1: EdenError ex);

  /** Forces the journal to flush, sending a truncated result to subscribers
   */
  void flushJournal(1: PathString mountPoint) throws (1: EdenError ex);

  /**
   * Returns the journal entries for the specified params. Useful for auditing
   * the changes that Eden has sent to Watchman. Note that the most recent
   * journal entries will be at the front of the list in
   * DebugGetRawJournalResponse.
   */
  DebugGetRawJournalResponse debugGetRawJournal(
    1: DebugGetRawJournalParams params,
  ) throws (1: EdenError ex);

  /**
   * Returns the subset of information about a list of paths that can
   * be determined from each's parent directory tree. For now, that
   * includes whether the entry exists and its dtype.
   *
   * Note: may return stale data if synchronizeWorkingCopy isn't called, and if
   * the SyncBehavior specify a 0 timeout. see the documentation for both of
   * these for more details.
   */
  list<EntryInformationOrError> getEntryInformation(
    1: PathString mountPoint,
    2: list<PathString> paths,
    3: SyncBehavior sync,
  ) throws (1: EdenError ex);

  /**
   * Returns a subset of the stat() information for a list of paths.
   * The returned list of information corresponds to the input list of
   * paths; eg; result[0] holds the information for paths[0].
   * We only support returning the instantaneous information about
   * these paths, as we cannot answer with historical information about
   * files in the overlay.
   *
   * Note: may return stale data if synchronizeWorkingCopy isn't called, and if
   * the SyncBehavior specify a 0 timeout. see the documentation for both of
   * these for more details.
   */
  list<FileInformationOrError> getFileInformation(
    1: PathString mountPoint,
    2: list<PathString> paths,
    3: SyncBehavior sync,
  ) throws (1: EdenError ex);

  /**
   * Returns the requested file attributes for the provided list of files.
   * The result maps the files to attribute results which may be an EdenError
   * or a FileAttributeData struct.
   *
   * Note: may return stale data if synchronizeWorkingCopy isn't called, and if
   * the SyncBehavior specify a 0 timeout. see the documentation for both of
   * these for more details.
   */
  GetAttributesFromFilesResult getAttributesFromFiles(
    1: GetAttributesFromFilesParams params,
  ) throws (1: EdenError ex);
<commit_msg>add file type to attributes endpoint<commit_after>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This software may be used and distributed according to the terms of the
 * GNU General Public License version 2.
 */

include "eden/fs/config/eden_config.thrift"
include "fb303/thrift/fb303_core.thrift"

namespace cpp2 facebook.eden
namespace java com.facebook.eden.thrift
namespace py facebook.eden
namespace py3 eden.fs.service

/** Thrift doesn't really do unsigned numbers, but we can sort of fake it.
 * This type is serialized as an integer value that is 64-bits wide and
 * should round-trip with full fidelity for C++ client/server, but for
 * other runtimes will have crazy results if the sign bit is ever set.
 * In practice it is impossible for us to have files that large in eden,
 * and sequence numbers will take an incredibly long time to ever roll
 * over and cause problems.
 * Once t13345978 is done, we can uncomment the cpp.type below.
 */
typedef i64 /* (cpp.type = "std::uint64_t") */
unsigned64

typedef i32 pid_t

/**
 * A backing-store-specific identifier for the root tree. For Mercurial or
 * Git, this is a 20-byte binary hash or a 40-byte hexadecimal hash.
 *
 * For other backing stores, this string may have variable length and its
 * meaning is defined by the backing-store. If possible, prefer human-readable
 * strings so they can be read in log files and error messages.
 *
 * This is named ThriftRootId to not conflict with the RootId class, but
 * perhaps this Thrift module should be placed in its own namespace.
 */
typedef binary ThriftRootId

typedef binary ThriftObjectId

/**
 * A source control hash.
 *
 * This should normally be a 20-byte binary value, however the edenfs server
 * will accept BinaryHash arguments as 40-byte hexadecimal strings as well.
 * Data returned by the edenfs server in a BinaryHash field will always be a
 * 20-byte binary value.
 */
typedef binary BinaryHash

/**
 * So, you thought that a path was a string?
 * Paths in posix are arbitrary byte strings with some pre-defined special
 * characters.  On modern systems they tend to be represented as UTF-8 but
 * there is no guarantee.  We use the `PathString` type as symbolic way
 * to indicate that you may need to perform special processing to safely
 * interpret the path data on your system.
 */
typedef binary PathString

/**
 * A customizable type to be returned with an EdenError, helpful for catching
 * and having custom client logic to handle specfic error cases
 */
enum EdenErrorType {
  /** The errorCode property is a posix errno value */
  POSIX_ERROR = 0,
  /** The errorCode property is a win32 error value */
  WIN32_ERROR = 1,
  /** The errorCode property is a windows NT HResult error value */
  HRESULT_ERROR = 2,
  /**
   * An argument passed to thrift was invalid. errorCode will be set to EINVAL
   */
  ARGUMENT_ERROR = 3,
  /** An error occurred. errorCode will be not set */
  GENERIC_ERROR = 4,
  /** The mount generation changed. errorCode will be set to ERANGE */
  MOUNT_GENERATION_CHANGED = 5,
  /** The journal has been truncated. errorCode will be set to EDOM */
  JOURNAL_TRUNCATED = 6,
  /**
   * The thrift funtion that receives this in an error is being called while
   * a checkout is in progress. errorCode will not be set.
   */
  CHECKOUT_IN_PROGRESS = 7,
  /**
  * The thrift function that receives this is an error is being called with a
  * parent that is not the current parent. errorCode will not be set.
  */
  OUT_OF_DATE_PARENT = 8,
}

exception EdenError {
  1: required string message;
  2: optional i32 errorCode;
  3: EdenErrorType errorType;
} (message = 'message')

exception NoValueForKeyError {
  1: string key;
}

/**
 * Information about the running edenfs daemon.
 */
struct DaemonInfo {
  1: i32 pid;
  /**
   * List of command line arguments, including the executable name,
   * given to the edenfs process.
   */
  2: list<string> commandLine;
  /**
   * The service status.
   *
   * This is almost the same value reported by
   * fb303_core.BaseService.getStatus(). fb303_core.BaseService.getStatus()
   * only returns the Thrift server status and does not understand mounts or
   * graceful restarts.
   */
  3: optional fb303_core.fb303_status status;
  /**
   * The uptime of the edenfs daemon
   * Same data from /proc/pid/stat
   */
  4: optional float uptime;
}

/**
* Information about the privhelper process
*/
struct PrivHelperInfo {
  1: bool connected;
}

/**
 * The current running state of an EdenMount.
 */
enum MountState {
  /**
   * The EdenMount object has been constructed but has not started
   * initializing.
   */
  UNINITIALIZED = 0,
  /**
   * The mount point is currently initializing and loading necessary state
   * (such as the root directory contents) before it can ask the kernel to
   * mount it.
   */
  INITIALIZING = 1,
  /**
   * The mount point has loaded its local state needed to start mounting
   * but has not actually started mounting yet.
   */
  INITIALIZED = 2,
  /**
   * Starting to mount fuse.
   */
  STARTING = 3,
  /**
   * The EdenMount is running normally.
   */
  RUNNING = 4,
  /**
   * Encountered an error while starting fuse mount.
   */
  FUSE_ERROR = 5,
  /**
   * EdenMount::shutdown() has been called, but it is not complete yet.
   */
  SHUTTING_DOWN = 6,
  /**
   * EdenMount::shutdown() has completed, but there are still outstanding
   * references so EdenMount::destroy() has not been called yet.
   *
   * When EdenMount::destroy() is called the object can be destroyed
   * immediately.
   */
  SHUT_DOWN = 7,
  /**
   * EdenMount::destroy() has been called, but the shutdown is not complete
   * yet.  There are no remaining references to the EdenMount at this point,
   * so when the shutdown completes it will be automatically destroyed.
   */
  DESTROYING = 8,
  /**
   * An error occurred during mount initialization.
   *
   * This state is used for errors that occur during the INITIALIZING phase,
   * before we have attempted to start the FUSE mount.
   */
  INIT_ERROR = 9,
} (cpp2.enum_type = 'uint32_t')

struct MountInfo {
  1: PathString mountPoint;
  2: PathString edenClientPath;
  3: MountState state;
  4: optional PathString backingRepoPath;
}

struct MountArgument {
  1: PathString mountPoint;
  2: PathString edenClientPath;
  3: bool readOnly;
}

union SHA1Result {
  1: BinaryHash sha1;
  2: EdenError error;
}

/**
 * Effectively a `struct timespec`
 */
struct TimeSpec {
  1: i64 seconds;
  2: i64 nanoSeconds;
}

/**
 * Information about filesystem entries that can be retrieved solely
 * from the tree structure, without having to fetch the actual child
 * objects from source control.
 */
struct EntryInformation {
  1: Dtype dtype;
}

union EntryInformationOrError {
  1: EntryInformation info;
  2: EdenError error;
}

/**
 * Subset of stat() data returned from getFileInformation())
 */
struct FileInformation {
  1: unsigned64 size; // wish thrift had unsigned numbers
  2: TimeSpec mtime;
  3: i32 mode; // mode_t
}

/** Holds information about a file, or an error in retrieving that info.
 * The most likely error will be ENOENT, implying that the file doesn't exist.
 */
union FileInformationOrError {
  1: FileInformation info;
  2: EdenError error;
}

/**
 * File Attributes that can be requested with getAttributesFromFiles(). All attributes
 * should be a power of 2. OR the requested attributes together to get a bitmask.
 */
enum FileAttributes {
  NONE = 0,
  SHA1_HASH = 1,
  FILE_SIZE = 2,
  SOURCE_CONTROL_TYPE = 4,
/* NEXT_ATTR = 2^x */
} (cpp2.enum_type = 'uint64_t')

/**
 * Subset of attributes for a single file returned by getAttributesFromFiles()
 */
struct FileAttributeData {
  1: optional BinaryHash sha1;
  2: optional i64 fileSize;
  3: optional SourceControlType type;
}

/**
 * Attributes for a file or information about error encountered when accessing file attributes.
 * The most likely error will be ENOENT, implying that the file doesn't exist.
 */
union FileAttributeDataOrError {
  1: FileAttributeData data;
  2: EdenError error;
}

/**
 *
 * Ensure that all inflight working copy modification have completed.
 *
 * On some platforms, EdenFS is processing working copy modifications
 * callbacks from the platform in an asynchronous manner, which means that by
 * the time a write/creat/mkdir/unlink/etc syscall returns from the kernel,
 * EdenFS may not have updated its internal state.
 *
 * Thus, an application making changes to the working copy and quickly
 * requesting EdenFS to perform an operation on it will race with EdenFS
 * updating its internal state and may thus get stale data.
 *
 * To avoid this, EdenFS queries need to internally synchronize the working
 * copy before performing the query itself. This structure defines how EdenFS
 * will do this.
 *
 * Applications that care about synchronizing EdenFS up to a certain point in
 * time are expected to set a non-zero syncTimeout once to synchronize EdenFS
 * and then issue all their thrift requests with a syncTimeout of 0.
 */
struct SyncBehavior {
  // How many seconds to wait for the working copy to be synchronized. A value
  // of 0 will not perform any working copy synchronization.
  // If left unset, EdenFS will use a default synchronization timeout.
  1: optional i64 syncTimeoutSeconds;
}

/**
 * Parameters for the getAttributesFromFiles() function
 */
struct GetAttributesFromFilesParams {
  1: PathString mountPoint;
  2: list<PathString> paths;
  3: unsigned64 requestedAttributes;
  4: SyncBehavior sync;
}

/**
 * Return value for the getAttributesFromFiles() function.
 * The returned list of attributes corresponds to the input list of
 * paths; eg; res[0] holds the information for paths[0].
 */
struct GetAttributesFromFilesResult {
  1: list<FileAttributeDataOrError> res;
}

/** reference a point in time in the journal.
 * This can be used to reason about a point in time in a given mount point.
 * The mountGeneration value is opaque to the client.
 */
struct JournalPosition {
  /** An opaque but unique number within the scope of a given mount point.
   * This is used to determine when sequenceNumber has been invalidated. */
  1: i64 mountGeneration;

  /** Monotonically incrementing number
   * Each journalled change causes this number to increment. */
  2: unsigned64 sequenceNumber;

  /** Records the snapshot hash at the appropriate point in the journal */
  3: ThriftRootId snapshotHash;
}

/**
 * Holds information about a set of paths that changed between two points.
 * fromPosition, toPosition define the time window.
 * paths holds the list of paths that changed in that window.
 *
 * This type is quasi-deprecated. It has multiple API problems and should be
 * rethought when we have a chance to make a breaking change.
 */
struct FileDelta {
  /**
   * The fromPosition passed to getFilesChangedSince
   */
  1: JournalPosition fromPosition;
  /**
   * The current position at the time that getFilesChangedSince was called
  */
  2: JournalPosition toPosition;
  /**
   * The union of changedPaths and createdPaths contains the total set of paths
   * changed in the overlay between fromPosition and toPosition.
   * Disjoint with createdPaths.
   */
  3: list<PathString> changedPaths;
  /**
   * The set of paths created between fromPosition and toPosition.
   * Used by Watchman to search for cookies and to populate its 'new' field.
   * Disjoint with changedPaths.
   */
  4: list<PathString> createdPaths;
  /**
   * Deprecated - always empty.
   */
  5: list<PathString> removedPaths;
  /**
   * When fromPosition.snapshotHash != toPosition.snapshotHash this holds
   * the union of the set of files whose ScmFileStatus differed from the
   * committed fromPosition hash before the hash changed, and the set of
   * files whose ScmFileStatus differed from the committed toPosition hash
   * after the hash was changed.  This list of files represents files
   * whose state may have changed as part of an update operation, but
   * in ways that may not be able to be extracted solely by performing
   * source control diff operations on the from/to hashes.
   */
  6: list<PathString> uncleanPaths;
  /**
   * Contains the list of commit transitions in this range. If only files
   * have been changed, the list has one entry. Otherwise, it has size N + 1,
   * where N is the number of checkout operations.
   *
   * This list's items may not be unique: [A, B, A] is a common sequence,
   * and [A, B, C] has a different meaning than [A, C, B].
   *
   * Subsumes fromPosition.snapshotHash and toPosition.snapshotHash.
   */
  7: list<ThriftRootId> snapshotTransitions;
}

struct DebugGetRawJournalParams {
  1: PathString mountPoint;
  2: optional i32 limit;
  3: i32 fromSequenceNumber;
}

struct DebugPathChangeInfo {
  1: bool existedBefore;
  2: bool existedAfter;
}

/**
 * A fairly direct modeling of the underlying JournalDelta data structure.
 */
struct DebugJournalDelta {
  1: JournalPosition fromPosition;
  2: JournalPosition toPosition;
  3: map<PathString, DebugPathChangeInfo> changedPaths;
  4: set<PathString> uncleanPaths;
}

struct DebugGetRawJournalResponse {
  2: list<DebugJournalDelta> allDeltas;
}

/**
 * Classifies the change of the state of a file between and old and new state
 * of the repository. Most commonly, the "old state" is the parent commit while
 * the "new state" is the working copy.
 */
enum ScmFileStatus {
  /**
   * File is present in the new state, but was not present in old state.
   */
  ADDED = 0x0,

  /**
   * File is present in both the new and old states, but its contents or
   * file permissions have changed.
   */
  MODIFIED = 0x1,

  /**
   * File was present in the old state, but is not present in the new state.
   */
  REMOVED = 0x2,

  /**
   * File is present in the new state, but it is ignored according to the rules
   * of the new state.
   */
  IGNORED = 0x3,
}

struct ScmStatus {
  1: map<PathString, ScmFileStatus> entries;

  /**
   * A map of { path -> error message }
   *
   * If any errors occured while computing the diff they will be reported here.
   * The results listed in the entries field may not be accurate for any paths
   * listed in this error field.
   *
   * This map will be empty if no errors occurred.
   */
  2: map<PathString, string> errors;
}

/** Option for use with checkOutRevision(). */
enum CheckoutMode {
  /**
   * Perform a "normal" checkout, analogous to `hg checkout` in Mercurial. Files
   * in the working copy will be changed to reflect the destination snapshot,
   * though files with conflicts will not be modified.
   */
  NORMAL = 0,

  /**
   * Do not checkout: exercise the checkout logic to discover potential
   * conflicts.
   */
  DRY_RUN = 1,

  /**
   * Perform a "forced" checkout, analogous to `hg checkout --clean` in
   * Mercurial. Conflicts between the working copy and destination snapshot will
   * be forcibly ignored in favor of the state of the new snapshot.
   */
  FORCE = 2,
}

enum ConflictType {
  /**
   * We failed to update this particular path due to an error
   */
  ERROR = 0,
  /**
   * A locally modified file was deleted in the new Tree
   */
  MODIFIED_REMOVED = 1,
  /**
   * An untracked local file exists in the new Tree
   */
  UNTRACKED_ADDED = 2,
  /**
   * The file was removed locally, but modified in the new Tree
   */
  REMOVED_MODIFIED = 3,
  /**
   * The file was removed locally, and also removed in the new Tree.
   */
  MISSING_REMOVED = 4,
  /**
   * A locally modified file was modified in the new Tree
   * This may be contents modifications, or a file type change (directory to
   * file or vice-versa), or permissions changes.
   */
  MODIFIED_MODIFIED = 5,
  /**
   * A directory was supposed to be removed or replaced with a file,
   * but it contains untracked files preventing us from updating it.
   */
  DIRECTORY_NOT_EMPTY = 6,
}

/**
 * Details about conflicts or errors that occurred during a checkout operation
 */
struct CheckoutConflict {
  1: PathString path;
  2: ConflictType type;
  3: string message;
}

struct ScmBlobMetadata {
  1: i64 size;
  2: BinaryHash contentsSha1;
}

struct ScmTreeEntry {
  1: binary name;
  2: i32 mode;
  3: ThriftObjectId id;
}

/*
 * Bits passed into debugInodeStatus to control the result set.
 * 0 is legacy behavior, equivalent to DIS_REQUIRE_LOADED | DIS_COMPUTE_BLOB_SIZES
 */

/**
 * No effect other than avoiding the legacy behavior.
 */
const i64 DIS_ENABLE_FLAGS = 1;

/**
 * Only return inodes currently loaded in memory.
 */
const i64 DIS_REQUIRE_LOADED = 2;

/**
 * Only return materialized inodes.
 */
const i64 DIS_REQUIRE_MATERIALIZED = 4;

/**
 * Return accurate blob sizes, which may require fetching blob metadata from
 * the backing store.
 */
const i64 DIS_COMPUTE_BLOB_SIZES = 8;

/**
 * Returns accurate mode_t bits, including ownership. When unset, only
 * the dtype bits are set.
 */
const i64 DIS_COMPUTE_ACCURATE_MODE = 16;

struct TreeInodeEntryDebugInfo {
  /**
   * The entry name.  This is just a PathComponent, not the full path
   */
  1: binary name;
  /**
   * The inode number, or 0 if no inode number has been assigned to
   * this entry
   */
  2: i64 inodeNumber;
  /**
   * The entry mode_t value
   */
  3: i32 mode;
  /**
   * True if an InodeBase object exists for this inode or not.
   */
  4: bool loaded;
  /**
   * True if an the inode is materialized in the overlay
   */
  5: bool materialized;
  /**
   * If materialized is false, hash contains the ID of the underlying source
   * control Blob or Tree.
   */
  6: ThriftObjectId hash;
  /**
   * Size of the file in bytes. It won't be set for directories.
   */
  7: optional i64 fileSize;
}

struct GetFetchedFilesResult {
  1: map<string, set<PathString>> fetchedFilePaths;
}

struct WorkingDirectoryParents {
  1: ThriftRootId parent1;
  // This field is never used by EdenFS.
  2: optional ThriftRootId parent2;
}

struct TreeInodeDebugInfo {
  1: i64 inodeNumber;
  2: binary path;
  3: bool materialized;
  // Traditionally, treeHash was a 20-byte binary hash, but now it's an
  // arbitrary-length human-readable string.
  4: ThriftObjectId treeHash;
  5: list<TreeInodeEntryDebugInfo> entries;
  6: i64 refcount;
}

struct InodePathDebugInfo {
  1: PathString path;
  2: bool loaded;
  3: bool linked;
}

struct ActivityRecorderResult {
  // 0 if the operation has failed. For example,
  // fail to start recording due to file permission issue
  // or fail to stop recording due to no active subscriber.
  1: i64 unique;
  2: optional PathString path;
}

struct ListActivityRecordingsResult {
  1: list<ActivityRecorderResult> recordings;
}

struct SetLogLevelResult {
  1: bool categoryCreated;
}

struct JournalInfo {
  1: i64 entryCount;
  // The estimated memory used by the journal in bytes
  2: i64 memoryUsage;
  // The duration of the journal in seconds
  3: i64 durationSeconds;
}

/**
 * Struct to store Information about inodes in a mount point.
 */
struct MountInodeInfo {
  2: i64 unloadedInodeCount;
  4: i64 loadedFileCount;
  5: i64 loadedTreeCount;
}

struct CacheStats {
  1: i64 entryCount;
  2: i64 totalSizeInBytes;
  3: i64 hitCount;
  4: i64 missCount;
  5: i64 evictionCount;
  6: i64 dropCount;
}

/*
 * Bits that control the stats returned from  getStatInfo
 */
const i64 STATS_MOUNTS_STATS = 0x1;
const i64 STATS_COUNTERS = 0x2;
const i64 STATS_SMAPS = 0x4;
const i64 STATS_PRIVATE_BYTES = 0x8;
const i64 STATS_RSS_BYTES = 0x10;
const i64 STATS_CACHE_STATS = 0x20;
const i64 STATS_ALL = 0xFFFF;

/**
 * Struct to store fb303 counters from ServiceData.getCounters() and inode
 * information of all the mount points.
 */
struct InternalStats {
  /**
  * fbf303 counter of inodes unloaded by periodic job.
  * Populated if STATS_COUNTERS is set.
  */
  1: optional i64 periodicUnloadCount;
  /**
   * counters is the list of fb303 counters, key is the counter name, value is the
   * counter value.
   * Populated if STATS_COUNTERS is set.
   */
  2: optional map<string, i64> counters;
  /**
   * mountPointInfo is a map whose key is the path of the mount point and value
   * is the details like number of loaded inodes,unloaded inodes in that mount
   * and number of materialized inodes in that mountpoint.
   * Populated if STATS_MOUNTS_STATS is set.
   */
  3: optional map<PathString, MountInodeInfo> mountPointInfo;
  /**
   * Linux-only: the contents of /proc/self/smaps, to be parsed by the caller.
   * Populated if STATS_SMAPS is set.
   */
  4: optional binary smaps;
  /**
   * Linux-only: privateBytes populated from contents of /proc/self/smaps.
   * Populated with current value (the fb303 counters value is an average).
   * Populated if STATS_PRIVATE_BYTES is set.
   */
  5: optional i64 privateBytes;
  /**
   * Linux-only: vmRSS bytes is populated from contents of /proc/self/stats.
   * Populated with current value (the fb303 counters value is an average).
   * Populated if STATS_RSS_BYTES is set.
   */
  6: optional i64 vmRSSBytes;
  /**
   * Statistics about the in-memory blob cache.
   * Populated if STATS_CACHE_STATS is set.
   */
  7: optional CacheStats blobCacheStats;
  /**
   * mountPointJournalInfo is a map whose key is the path of the mount point
   * and whose value is information about the journal on that mount
   * Populated if STATS_MOUNTS_STATS is set.
   */
  8: optional map<PathString, JournalInfo> mountPointJournalInfo;
  /**
   * Statistics about the in-memory tree cache.
   * Populated if STATS_CACHE_STATS is set.
   */
  9: optional CacheStats treeCacheStats;
}

struct FuseCall {
  // This field is deprecated because its use is not worth the TraceBus
  // storage. It may be brought back in some other form.
  //1: i32 len;

  2: i32 opcode;
  // FUSE supplies a unique ID, but it is recycled so quickly that it's not
  // very useful. We report our own process-unique ID.
  3: i64 unique;
  4: i64 nodeid;
  5: i32 uid;
  6: i32 gid;
  7: pid_t pid;

  8: string opcodeName;
  9: optional string processName;
}

struct NfsCall {
  1: i32 xid;
  2: i32 procNumber;
  3: string procName;
}

enum PrjfsTraceCallType {
  INVALID = 0,
  /* Write operations */
  FILE_OPENED = 1,
  NEW_FILE_CREATED = 2,
  FILE_OVERWRITTEN = 3,
  PRE_DELETE = 4,
  PRE_RENAME = 5,
  PRE_SET_HARDLINK = 6,
  FILE_RENAMED = 7,
  HARDLINK_CREATED = 8,
  FILE_HANDLE_CLOSED_NO_MODIFICATION = 9,
  FILE_HANDLE_CLOSED_FILE_MODIFIED = 10,
  FILE_HANDLE_CLOSED_FILE_DELETED = 11,
  FILE_PRE_CONVERT_TO_FULL = 12,
  /* Read operations */
  START_ENUMERATION = 13,
  END_ENUMERATION = 14,
  GET_ENUMERATION_DATA = 15,
  GET_PLACEHOLDER_INFO = 16,
  QUERY_FILE_NAME = 17,
  GET_FILE_DATA = 18,
  CANCEL_COMMAND = 19,
}

struct PrjfsCall {
  1: i32 commandId;
  2: i32 pid;
  3: PrjfsTraceCallType callType;
}

struct GetConfigParams {
  // Whether to reload the config from disk to make sure it is up-to-date
  1: eden_config.ConfigReloadBehavior reload = eden_config.ConfigReloadBehavior.AutoReload;
}

struct GetStatInfoParams {
  // a bitset that indicates the requested stats. 0 indicates all stats are requested.
  1: i64 statsMask;
}

/**
 * A representation of the system-dependent dirent::d_type field.
 * The bits and their interpretation is system dependent.
 * This value is u8 on all systems that implement it.  We
 * use i16 to pass this through thrift, which doesn't have unsigned
 * numbers
 */
typedef i16 OsDtype

enum SourceControlType {
  TREE = 0,
  REGULAR_FILE = 1,
  EXECUTABLE_FILE = 2,
  SYMLINK = 3,
}

/**
 * These numbers match up with Linux and macOS.
 * Windows doesn't have dtype_t, but a subset of these map to and from
 * the GetFileType and dwFileAttributes equivalents.
 *
 * Dtype and OsDtype can be cast between each other on all platforms.
 */
enum Dtype {
  UNKNOWN = 0,
  FIFO = 1, // DT_FIFO
  CHAR = 2, // DT_CHR
  DIR = 4, // DT_DIR
  BLOCK = 6, // DT_BLK
  REGULAR = 8, // DT_REG
  LINK = 10, // DT_LNK
  SOCKET = 12, // DT_SOCK
  WHITEOUT = 14, // DT_WHT
}

struct PredictiveFetch {
  // Number of directories to glob. If not specified, a default value (predictivePrefetchProfileSize in EdenConfig.h) is used.
  1: optional i32 numTopDirectories;
  // Fetch the most accessed diectories by user specified. If not specified, user is derived from the server state.
  2: optional string user;
  // Fetch the most accessed diectories in repository specified. If not specified, repo is derived from the mount.
  3: optional string repo;
  // Optional query parameter: fetch top most accessed directories with specified Operating System
  4: optional string os;
  // Optional query parameter: fetch top most accessed directories after startTime
  5: optional unsigned64 startTime;
  // Optional query parameter: fetch top most accessed directories before endTime
  6: optional unsigned64 endTime;
}
/** Params for globFiles(). */
struct GlobParams {
  1: PathString mountPoint;
  2: list<string> globs;
  3: bool includeDotfiles;
  // if true, prefetch matching blobs
  4: bool prefetchFiles;
  // if true, don't populate matchingFiles in the Glob
  // results.  This only really makes sense with prefetchFiles.
  5: bool suppressFileList;
  6: bool wantDtype;
  // Commit hashes for the revisions against which the globs should be
  // evaluated, if this is empty then globFiles will fall back to using only
  // the current revision.
  // If eden moves away from commit hashes this may become the tree hash
  // for the root tree agains which this glob should be evaluated.
  // There should be no duplicates in this list. If there are then
  // there maybe duplicate machingFile and originHash pairs in the coresponding
  // output Glob.
  7: list<ThriftRootId> revisions;
  // This has no effect.
  8: bool prefetchMetadata = true;
  // The directory from which the glob should be evaluated. Defaults to the
  // repository root.
  9: PathString searchRoot;
  // If set, will run the prefetch but will not wait for the result.
  10: bool background = false;
  // When set, the globs list must be empty and the globbing pattern will be obtained
  // from an online service.
  11: optional PredictiveFetch predictiveGlob;
  // Normally the returned file list will contain both files and directories.
  // Some clients would like to see only lists of files, this option tells us
  // wether to filter or not.
  // Note for Eden developers: when this is false the matchingFiles fileList
  // will not actually be the list that is fed into the backing store to prefetch.
  12: bool listOnlyFiles = false;
  // Should this glob query also synchronize the working copy?
  13: SyncBehavior sync;
}

struct Glob {
  /**
   * matchingFiles can contain duplicate values and is not guaranteed to be
   * sorted. However, no duplicates may have the same originCommits (note this
   * is not true should the input GlobParams contain duplicate revisions) .
   */
  1: list<PathString> matchingFiles;
  2: list<OsDtype> dtypes;
  /**
   * Currently these are the commit hash for the commit to which this file
   * belongs. But should eden move away from commit hashes this may become
   * the tree hash of the root tree to which this file belongs.
   */
  3: list<binary> originHashes;
}

struct AccessCounts {
  1: i64 fsChannelTotal;
  2: i64 fsChannelReads;
  3: i64 fsChannelWrites;
  4: i64 fsChannelBackingStoreImports;
  5: i64 fsChannelDurationNs;
  6: i64 fsChannelMemoryCacheImports;
  7: i64 fsChannelDiskCacheImports;
}

struct MountAccesses {
  1: map<pid_t, AccessCounts> accessCountsByPid;
  2: map<pid_t, i64> fetchCountsByPid;
}

struct GetAccessCountsResult {
  1: map<pid_t, binary> cmdsByPid;
  2: map<PathString, MountAccesses> accessesByMount;
// TODO: Count the number of thrift requests
// 3: map<pid_t, AccessCount> thriftAccesses
}

enum TracePointEvent {
  // Start of a new block
  START = 0,
  // End of a block
  STOP = 1,
}

struct TracePoint {
  // Holds nanoseconds since the epoch
  1: i64 timestamp;
  // Opaque identifier for the entire trace - used to associate this
  // tracepoint with other tracepoints across an entire request
  2: i64 traceId;
  // Opaque identifier for this "block" where a block is some logical
  // piece of work with a well-defined start and stop point
  3: i64 blockId;
  // Opaque identifer for the parent block from which the current
  // block was constructed - used to create causal relationships
  // between blocks
  4: i64 parentBlockId;
  // The name of the block, only set on the tracepoint starting the
  // block, must point to a statically allocated cstring
  5: string name = "";
  // What event this trace point represents
  6: TracePointEvent event;
}

struct FaultDefinition {
  1: string keyClass;
  2: string keyValueRegex;
  // If count is non-zero this fault will automatically expire after it has
  // been hit count times.
  3: i64 count;
  // If block is true the fault will block until explicitly unblocked later.
  // delayMilliseconds and errorMessage will be ignored if block is true
  4: bool block;
  5: i64 delayMilliseconds;
  6: optional string errorType;
  7: optional string errorMessage;
}

struct RemoveFaultArg {
  1: string keyClass;
  2: string keyValueRegex;
}

struct UnblockFaultArg {
  1: optional string keyClass;
  2: optional string keyValueRegex;
  3: optional string errorType;
  4: optional string errorMessage;
}

struct GetScmStatusResult {
  1: ScmStatus status;
  // The version of the EdenFS daemon.
  // This is returned since we usually want status calls to be able to check
  // the current EdenFS version and warn the user if EdenFS is running an old
  // or known-bad version.
  2: string version;
}

struct GetScmStatusParams {
  /**
   * The Eden checkout to query
   */
  1: PathString mountPoint;

  /**
   * The commit ID of the current working directory parent commit.
   *
   * An error will be returned if this is not actually the current parent
   * commit.  This behavior exists to support callers that do not perform their
   * own external synchronization around access to the current parent commit,
   * like Mercurial.
   */
  2: ThriftRootId commit;

  /**
   * Whether ignored files should be reported in the results.
   *
   * Some special source-control related files (e.g., inside the .hg or .git
   * directory) will never be reported even when listIgnored is true.
   */
  3: bool listIgnored = false;
}

/**
  * BackingStore object type. Caller will response to verify the type of the content
  * matching the parameters passed. Exception will be thrown if type mismatch.
  */
enum ObjectType {
  TREE = 0,
  REGULAR_FILE = 1,
  EXECUTABLE_FILE = 2,
  SYMLINK = 3,
}

struct SetPathObjectIdParams {
  1: PathString mountPoint;
  2: PathString path;
  3: ThriftObjectId objectId;
  4: ObjectType type;
  5: CheckoutMode mode;
  // Extra request infomation. i.e. build uuid, cache session id.
  6: optional map<string, string> requestInfo;
}

struct SetPathObjectIdResult {
  1: list<CheckoutConflict> conflicts;
}

struct CheckOutRevisionParams {
  /**
   * The hg root manifest that corresponds to the commit (if known).
   *
   * When a commit is newly created, EdenFS won't know the commit
   * to root-manifest mapping for the commit, and won't be able to find
   * out from the import helper until the import helper re-opens the
   * repo.  To speed this up, Mercurial clients may optionally provide
   * the hash of the root manifest directly, so that EdenFS doesn't
   * need to look it up.
   */
  1: optional BinaryHash hgRootManifest;
}

struct ResetParentCommitsParams {
  /**
   * The hg root manifest that corresponds to the commit (if known).
   *
   * When a commit is newly created, EdenFS won't know the commit
   * to root-manifest mapping for the commit, and won't be able to find
   * out from the import helper until the import helper re-opens the
   * repo.  To speed this up, Mercurial clients may optionally provide
   * the hash of the root manifest directly, so that EdenFS doesn't
   * need to look it up.
   */
  1: optional BinaryHash hgRootManifest;
}

struct RemoveRecursivelyParams {
  1: PathString mountPoint;
  2: PathString path;
  3: SyncBehavior sync;
}

struct SynchronizeWorkingCopyParams {
  1: SyncBehavior sync;
}

service EdenService extends fb303_core.BaseService {
  list<MountInfo> listMounts() throws (1: EdenError ex);
  void mount(1: MountArgument info) throws (1: EdenError ex);
  void unmount(1: PathString mountPoint) throws (1: EdenError ex);

  /**
   * Potentially check out the specified snapshot, reporting conflicts (and
   * possibly errors), as appropriate.
   *
   * If the checkoutMode is FORCE, the working directory will be forcibly
   * updated to the contents of the new snapshot, even if there were conflicts.
   * Conflicts will still be reported in the return value, but the files will be
   * updated to their new state.
   *
   * If the checkoutMode is NORMAL, files with conflicts will be left
   * unmodified. Files that are untracked in both the source and destination
   * snapshots are always left unchanged, even if force is true.
   *
   * If the checkoutMode is DRY_RUN, then no files are modified in the working
   * copy and the current snapshot does not change. However, potential conflicts
   * are still reported in the return value.
   *
   * On successful return from this function (unless it is a DRY_RUN), the mount
   * point will point to the new snapshot, even if some paths had conflicts or
   * errors. The caller is responsible for taking appropriate action to update
   * these paths as desired after checkOutRevision() returns.
   *
   * Note: this internally synchronize the working copy.
   */
  list<CheckoutConflict> checkOutRevision(
    1: PathString mountPoint,
    2: ThriftRootId snapshotHash,
    3: CheckoutMode checkoutMode,
    4: CheckOutRevisionParams params,
  ) throws (1: EdenError ex);

  /**
   * Reset the working directory's parent commits, without changing the working
   * directory contents.
   *
   * This operation is equivalent to `git reset --soft` or `hg reset --keep`
   */
  void resetParentCommits(
    1: PathString mountPoint,
    2: WorkingDirectoryParents parents,
    3: ResetParentCommitsParams params,
  ) throws (1: EdenError ex);

  /**
   * Ensure that all inflight working copy modification have completed.
   *
   * On some platforms, EdenFS is processing working copy modifications
   * callbacks from the platform in an asynchronous manner, which means that by
   * the time a write/creat/mkdir/unlink/etc syscall returns from the kernel,
   * EdenFS may not have updated its internal state.
   *
   * Thus, an application making changes to the working copy and quickly
   * requesting EdenFS to perform an operation on it will race with EdenFS
   * updating its internal state and may thus get stale data.
   *
   * To avoid this, applications can call this method prior to issuing other
   * Thrift requests (such as getSHA1, globFiles, etc) to wait for EdenFS to
   * update its internal state. Applications that care about synchronizing
   * EdenFS up to a certain point in time are expected to call this once and
   * then issue all their thrift requests without synchronizing.
   *
   * As an alternative, applications may also set the SyncBehavior of a Thrift
   * method to a non-zero value to achieve the same result.
   *
   * Some Thrift methods are implicitely synchronizing, their documentation
   * will state it.
   */
  void synchronizeWorkingCopy(
    1: PathString mountPoint,
    2: SynchronizeWorkingCopyParams params,
  ) throws (1: EdenError ex);

  /**
   * For each path, returns an EdenError instead of the SHA-1 if any of the
   * following occur:
   * - path is the empty string.
   * - path identifies a non-existent file.
   * - path identifies something that is not an ordinary file (e.g., symlink
   *   or directory).
   *
   * Note: may return stale data if synchronizeWorkingCopy isn't called, and if
   * the SyncBehavior specify a 0 timeout. see the documentation for both of
   * these for more details.
   */
  list<SHA1Result> getSHA1(
    1: PathString mountPoint,
    2: list<PathString> paths,
    3: SyncBehavior sync,
  ) throws (1: EdenError ex);

  /**
   * Returns a list of paths relative to the mountPoint. DEPRECATED!
   */
  list<PathString> getBindMounts(1: PathString mountPoint) throws (
    1: EdenError ex,
  );

  /**
   * On systems that support bind mounts, establish a bind mount within the
   * repo such that `mountPoint / repoPath` is redirected to `targetPath`.
   * If `repoPath` is already a bind mount managed by eden, this function
   * will throw an error.
   * If `repoPath` is not a directory then it will be created similar to
   * running `mkdir -p mountPoint/repoPath` and then the bind mount
   * will be established.
   * If `repoPath` exists and is not a directory, an error will be thrown.
   * If the bind mount cannot be set up, an error will be thrown.
   */
  void addBindMount(
    1: PathString mountPoint,
    2: PathString repoPath,
    3: PathString targetPath,
  ) throws (1: EdenError ex);

  /**
   * Removes the bind mount specified by `repoPath` from the set of managed
   * bind mounts.
   * If `repoPath` is not a bind mount managed by eden, this function
   * will throw an error.
   * If the bind mount cannot be removed, an error will be thrown.
   */
  void removeBindMount(
    1: PathString mountPoint,
    2: PathString repoPath,
  ) throws (1: EdenError ex);

  /** Returns the sequence position at the time the method is called.
   * Returns the instantaneous value of the journal sequence number.
   */
  JournalPosition getCurrentJournalPosition(1: PathString mountPoint) throws (
    1: EdenError ex,
  );

  /** Returns the set of files (and dirs) that changed since a prior point.
   * If fromPosition.mountGeneration is mismatched with the current
   * mountGeneration, throws an EdenError with errorCode = ERANGE.
   * If the domain required by fromPosition goes past the Journal's memory,
   * throws an EdenError with errorCode = EDOM.
   * This indicates that eden cannot compute the delta for the requested
   * range.  The client will need to recompute a new baseline using
   * other available functions in EdenService.
   */
  FileDelta getFilesChangedSince(
    1: PathString mountPoint,
    2: JournalPosition fromPosition,
  ) throws (1: EdenError ex);

  /** Sets the memory limit on the journal such that the journal will forget
   * old data to keep itself under a certain estimated memory use.
   */
  void setJournalMemoryLimit(1: PathString mountPoint, 2: i64 limit) throws (
    1: EdenError ex,
  );

  /** Gets the memory limit on the journal
   */
  i64 getJournalMemoryLimit(1: PathString mountPoint) throws (1: EdenError ex);

  /** Forces the journal to flush, sending a truncated result to subscribers
   */
  void flushJournal(1: PathString mountPoint) throws (1: EdenError ex);

  /**
   * Returns the journal entries for the specified params. Useful for auditing
   * the changes that Eden has sent to Watchman. Note that the most recent
   * journal entries will be at the front of the list in
   * DebugGetRawJournalResponse.
   */
  DebugGetRawJournalResponse debugGetRawJournal(
    1: DebugGetRawJournalParams params,
  ) throws (1: EdenError ex);

  /**
   * Returns the subset of information about a list of paths that can
   * be determined from each's parent directory tree. For now, that
   * includes whether the entry exists and its dtype.
   *
   * Note: may return stale data if synchronizeWorkingCopy isn't called, and if
   * the SyncBehavior specify a 0 timeout. see the documentation for both of
   * these for more details.
   */
  list<EntryInformationOrError> getEntryInformation(
    1: PathString mountPoint,
    2: list<PathString> paths,
    3: SyncBehavior sync,
  ) throws (1: EdenError ex);

  /**
   * Returns a subset of the stat() information for a list of paths.
   * The returned list of information corresponds to the input list of
   * paths; eg; result[0] holds the information for paths[0].
   * We only support returning the instantaneous information about
   * these paths, as we cannot answer with historical information about
   * files in the overlay.
   *
   * Note: may return stale data if synchronizeWorkingCopy isn't called, and if
   * the SyncBehavior specify a 0 timeout. see the documentation for both of
   * these for more details.
   */
  list<FileInformationOrError> getFileInformation(
    1: PathString mountPoint,
    2: list<PathString> paths,
    3: SyncBehavior sync,
  ) throws (1: EdenError ex);

  /**
   * Returns the requested file attributes for the provided list of files.
   * The result maps the files to attribute results which may be an EdenError
   * or a FileAttributeData struct.
   *
   * Currently, this API assumes all the given paths corespond to regular files.
   * We return EdenErrors instead of attributes for paths that correspond to
   * directories or symlinks.
   *
   * Note: may return stale data if synchronizeWorkingCopy isn't called, and if
   * the SyncBehavior specify a 0 timeout. see the documentation for both of
   * these for more details.
   */
  GetAttributesFromFilesResult getAttributesFromFiles(
    1: GetAttributesFromFilesParams params,
  ) throws (1: EdenError ex);

{'fraction_non_alphanumeric': 0.07082435705505045, 'fraction_numerical': 0.015603510181229538, 'mean_word_length': 3.345356462872858, 'pattern_counts': {'":': 0, '<': 85, '<?xml version=': 0, '>': 87, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '92385', 'n_tokens_mistral': 24812, 'n_tokens_neox': 23681, 'n_words': 10603}