• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright 2015 The TensorFlow Authors. All Rights Reserved.
2 
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
6 
7     http://www.apache.org/licenses/LICENSE-2.0
8 
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
14 ==============================================================================*/
15 
16 #ifndef TENSORFLOW_CORE_PLATFORM_ENV_H_
17 #define TENSORFLOW_CORE_PLATFORM_ENV_H_
18 
19 #include <stdint.h>
20 
21 #include <memory>
22 #include <string>
23 #include <unordered_map>
24 #include <vector>
25 
26 #include "tensorflow/core/platform/env_time.h"
27 #include "tensorflow/core/platform/errors.h"
28 #include "tensorflow/core/platform/file_system.h"
29 #include "tensorflow/core/platform/macros.h"
30 #include "tensorflow/core/platform/mutex.h"
31 #include "tensorflow/core/platform/numa.h"
32 #include "tensorflow/core/platform/platform.h"
33 #include "tensorflow/core/platform/protobuf.h"
34 #include "tensorflow/core/platform/status.h"
35 #include "tensorflow/core/platform/stringpiece.h"
36 #include "tensorflow/core/platform/types.h"
37 
38 // Delete leaked Windows definitions.
39 #ifdef PLATFORM_WINDOWS
40 #undef CopyFile
41 #undef DeleteFile
42 #endif
43 
44 namespace tensorflow {
45 
46 class Thread;
47 struct ThreadOptions;
48 
49 /// \brief An interface used by the tensorflow implementation to
50 /// access operating system functionality like the filesystem etc.
51 ///
52 /// Callers may wish to provide a custom Env object to get fine grain
53 /// control.
54 ///
55 /// All Env implementations are safe for concurrent access from
56 /// multiple threads without any external synchronization.
57 class Env {
58  public:
59   Env();
60   virtual ~Env() = default;
61 
62   /// \brief Returns a default environment suitable for the current operating
63   /// system.
64   ///
65   /// Sophisticated users may wish to provide their own Env
66   /// implementation instead of relying on this default environment.
67   ///
68   /// The result of Default() belongs to this library and must never be deleted.
69   static Env* Default();
70 
71   /// \brief Returns the FileSystem object to handle operations on the file
72   /// specified by 'fname'. The FileSystem object is used as the implementation
73   /// for the file system related (non-virtual) functions that follow.
74   /// Returned FileSystem object is still owned by the Env object and will
75   // (might) be destroyed when the environment is destroyed.
76   virtual Status GetFileSystemForFile(const std::string& fname,
77                                       FileSystem** result);
78 
79   /// \brief Returns the file system schemes registered for this Env.
80   virtual Status GetRegisteredFileSystemSchemes(
81       std::vector<std::string>* schemes);
82 
83   /// \brief Register a file system for a scheme.
84   virtual Status RegisterFileSystem(const std::string& scheme,
85                                     FileSystemRegistry::Factory factory);
86 
87   /// \brief Register a modular file system for a scheme.
88   ///
89   /// Same as `RegisterFileSystem` but for filesystems provided by plugins.
90   ///
91   /// TODO(mihaimaruseac): After all filesystems are converted, make this be the
92   /// canonical registration function.
93   virtual Status RegisterFileSystem(const std::string& scheme,
94                                     std::unique_ptr<FileSystem> filesystem);
95 
96   Status SetOption(const std::string& scheme, const std::string& key,
97                    const std::vector<string>& values);
98 
99   Status SetOption(const std::string& scheme, const std::string& key,
100                    const std::vector<int64>& values);
101 
102   Status SetOption(const std::string& scheme, const std::string& key,
103                    const std::vector<double>& values);
104 
105   /// \brief Flush filesystem caches for all registered filesystems.
106   Status FlushFileSystemCaches();
107 
108   /// \brief Creates a brand new random access read-only file with the
109   /// specified name.
110 
111   /// On success, stores a pointer to the new file in
112   /// *result and returns OK.  On failure stores NULL in *result and
113   /// returns non-OK.  If the file does not exist, returns a non-OK
114   /// status.
115   ///
116   /// The returned file may be concurrently accessed by multiple threads.
117   ///
118   /// The ownership of the returned RandomAccessFile is passed to the caller
119   /// and the object should be deleted when is not used. The file object
120   /// shouldn't live longer than the Env object.
121   Status NewRandomAccessFile(const std::string& fname,
122                              std::unique_ptr<RandomAccessFile>* result);
123 
NewRandomAccessFile(const std::string & fname,TransactionToken * token,std::unique_ptr<RandomAccessFile> * result)124   Status NewRandomAccessFile(const std::string& fname, TransactionToken* token,
125                              std::unique_ptr<RandomAccessFile>* result) {
126     // We duplicate these methods due to Google internal coding style prevents
127     // virtual functions with default arguments. See PR #41615.
128     return Status::OK();
129   }
130 
131   /// \brief Creates an object that writes to a new file with the specified
132   /// name.
133   ///
134   /// Deletes any existing file with the same name and creates a
135   /// new file.  On success, stores a pointer to the new file in
136   /// *result and returns OK.  On failure stores NULL in *result and
137   /// returns non-OK.
138   ///
139   /// The returned file will only be accessed by one thread at a time.
140   ///
141   /// The ownership of the returned WritableFile is passed to the caller
142   /// and the object should be deleted when is not used. The file object
143   /// shouldn't live longer than the Env object.
144   Status NewWritableFile(const std::string& fname,
145                          std::unique_ptr<WritableFile>* result);
146 
NewWritableFile(const std::string & fname,TransactionToken * token,std::unique_ptr<WritableFile> * result)147   Status NewWritableFile(const std::string& fname, TransactionToken* token,
148                          std::unique_ptr<WritableFile>* result) {
149     return Status::OK();
150   }
151 
152   /// \brief Creates an object that either appends to an existing file, or
153   /// writes to a new file (if the file does not exist to begin with).
154   ///
155   /// On success, stores a pointer to the new file in *result and
156   /// returns OK.  On failure stores NULL in *result and returns
157   /// non-OK.
158   ///
159   /// The returned file will only be accessed by one thread at a time.
160   ///
161   /// The ownership of the returned WritableFile is passed to the caller
162   /// and the object should be deleted when is not used. The file object
163   /// shouldn't live longer than the Env object.
164   Status NewAppendableFile(const std::string& fname,
165                            std::unique_ptr<WritableFile>* result);
166 
NewAppendableFile(const std::string & fname,TransactionToken * token,std::unique_ptr<WritableFile> * result)167   Status NewAppendableFile(const std::string& fname, TransactionToken* token,
168                            std::unique_ptr<WritableFile>* result) {
169     return Status::OK();
170   }
171   /// \brief Creates a readonly region of memory with the file context.
172   ///
173   /// On success, it returns a pointer to read-only memory region
174   /// from the content of file fname. The ownership of the region is passed to
175   /// the caller. On failure stores nullptr in *result and returns non-OK.
176   ///
177   /// The returned memory region can be accessed from many threads in parallel.
178   ///
179   /// The ownership of the returned ReadOnlyMemoryRegion is passed to the caller
180   /// and the object should be deleted when is not used. The memory region
181   /// object shouldn't live longer than the Env object.
182   Status NewReadOnlyMemoryRegionFromFile(
183       const std::string& fname, std::unique_ptr<ReadOnlyMemoryRegion>* result);
184 
NewReadOnlyMemoryRegionFromFile(const std::string & fname,TransactionToken * token,std::unique_ptr<ReadOnlyMemoryRegion> * result)185   Status NewReadOnlyMemoryRegionFromFile(
186       const std::string& fname, TransactionToken* token,
187       std::unique_ptr<ReadOnlyMemoryRegion>* result) {
188     return Status::OK();
189   }
190 
191   /// Returns OK if the named path exists and NOT_FOUND otherwise.
192   Status FileExists(const std::string& fname);
193 
FileExists(const std::string & fname,TransactionToken * token)194   Status FileExists(const std::string& fname, TransactionToken* token) {
195     return Status::OK();
196   }
197 
198   /// Returns true if all the listed files exist, false otherwise.
199   /// if status is not null, populate the vector with a detailed status
200   /// for each file.
201   bool FilesExist(const std::vector<string>& files,
202                   std::vector<Status>* status);
203 
FilesExist(const std::vector<string> & files,TransactionToken * token,std::vector<Status> * status)204   bool FilesExist(const std::vector<string>& files, TransactionToken* token,
205                   std::vector<Status>* status) {
206     return true;
207   }
208 
209   /// \brief Stores in *result the names of the children of the specified
210   /// directory. The names are relative to "dir".
211   ///
212   /// Original contents of *results are dropped.
213   Status GetChildren(const std::string& dir, std::vector<string>* result);
214 
GetChildren(const std::string & dir,TransactionToken * token,std::vector<string> * result)215   Status GetChildren(const std::string& dir, TransactionToken* token,
216                      std::vector<string>* result) {
217     return Status::OK();
218   }
219 
220   /// \brief Returns true if the path matches the given pattern. The wildcards
221   /// allowed in pattern are described in FileSystem::GetMatchingPaths.
222   virtual bool MatchPath(const std::string& path,
223                          const std::string& pattern) = 0;
224 
225   /// \brief Given a pattern, stores in *results the set of paths that matches
226   /// that pattern. *results is cleared.
227   ///
228   /// More details about `pattern` in FileSystem::GetMatchingPaths.
229   virtual Status GetMatchingPaths(const std::string& pattern,
230                                   std::vector<string>* results);
231 
GetMatchingPaths(const std::string & pattern,TransactionToken * token,std::vector<string> * results)232   Status GetMatchingPaths(const std::string& pattern, TransactionToken* token,
233                           std::vector<string>* results) {
234     return Status::OK();
235   }
236 
237   /// Deletes the named file.
238   Status DeleteFile(const std::string& fname);
239 
DeleteFile(const std::string & fname,TransactionToken * token)240   Status DeleteFile(const std::string& fname, TransactionToken* token) {
241     return Status::OK();
242   }
243 
244   /// \brief Deletes the specified directory and all subdirectories and files
245   /// underneath it. This is accomplished by traversing the directory tree
246   /// rooted at dirname and deleting entries as they are encountered.
247   ///
248   /// If dirname itself is not readable or does not exist, *undeleted_dir_count
249   /// is set to 1, *undeleted_file_count is set to 0 and an appropriate status
250   /// (e.g. NOT_FOUND) is returned.
251   ///
252   /// If dirname and all its descendants were successfully deleted, TF_OK is
253   /// returned and both error counters are set to zero.
254   ///
255   /// Otherwise, while traversing the tree, undeleted_file_count and
256   /// undeleted_dir_count are updated if an entry of the corresponding type
257   /// could not be deleted. The returned error status represents the reason that
258   /// any one of these entries could not be deleted.
259   ///
260   /// REQUIRES: undeleted_files, undeleted_dirs to be not null.
261   ///
262   /// Typical return codes:
263   ///  * OK - dirname exists and we were able to delete everything underneath.
264   ///  * NOT_FOUND - dirname doesn't exist
265   ///  * PERMISSION_DENIED - dirname or some descendant is not writable
266   ///  * UNIMPLEMENTED - Some underlying functions (like Delete) are not
267   ///                    implemented
268   Status DeleteRecursively(const std::string& dirname, int64* undeleted_files,
269                            int64* undeleted_dirs);
270 
DeleteRecursively(const std::string & dirname,TransactionToken * token,int64 * undeleted_files,int64 * undeleted_dirs)271   Status DeleteRecursively(const std::string& dirname, TransactionToken* token,
272                            int64* undeleted_files, int64* undeleted_dirs) {
273     return Status::OK();
274   }
275 
276   /// \brief Creates the specified directory and all the necessary
277   /// subdirectories. Typical return codes.
278   ///  * OK - successfully created the directory and sub directories, even if
279   ///         they were already created.
280   ///  * PERMISSION_DENIED - dirname or some subdirectory is not writable.
281   Status RecursivelyCreateDir(const std::string& dirname);
282 
RecursivelyCreateDir(const std::string & dirname,TransactionToken * token)283   Status RecursivelyCreateDir(const std::string& dirname,
284                               TransactionToken* token) {
285     return Status::OK();
286   }
287   /// \brief Creates the specified directory. Typical return codes
288   ///  * OK - successfully created the directory.
289   ///  * ALREADY_EXISTS - directory already exists.
290   ///  * PERMISSION_DENIED - dirname is not writable.
291   Status CreateDir(const std::string& dirname);
292 
CreateDir(const std::string & dirname,TransactionToken * token)293   Status CreateDir(const std::string& dirname, TransactionToken* token) {
294     return Status::OK();
295   }
296 
297   /// Deletes the specified directory.
298   Status DeleteDir(const std::string& dirname);
299 
DeleteDir(const std::string & dirname,TransactionToken * token)300   Status DeleteDir(const std::string& dirname, TransactionToken* token) {
301     return Status::OK();
302   }
303 
304   /// Obtains statistics for the given path.
305   Status Stat(const std::string& fname, FileStatistics* stat);
306 
Stat(const std::string & fname,TransactionToken * token,FileStatistics * stat)307   Status Stat(const std::string& fname, TransactionToken* token,
308               FileStatistics* stat) {
309     return Status::OK();
310   }
311 
312   /// \brief Returns whether the given path is a directory or not.
313   /// Typical return codes (not guaranteed exhaustive):
314   ///  * OK - The path exists and is a directory.
315   ///  * FAILED_PRECONDITION - The path exists and is not a directory.
316   ///  * NOT_FOUND - The path entry does not exist.
317   ///  * PERMISSION_DENIED - Insufficient permissions.
318   ///  * UNIMPLEMENTED - The file factory doesn't support directories.
319   Status IsDirectory(const std::string& fname);
320 
321   /// \brief Returns whether the given path is on a file system
322   /// that has atomic move capabilities. This can be used
323   /// to determine if there needs to be a temp location to safely write objects.
324   /// The second boolean argument has_atomic_move contains this information.
325   ///
326   /// Returns one of the following status codes (not guaranteed exhaustive):
327   ///  * OK - The path is on a recognized file system,
328   ///         so has_atomic_move holds the above information.
329   ///  * UNIMPLEMENTED - The file system of the path hasn't been implemented in
330   ///  TF
331   Status HasAtomicMove(const std::string& path, bool* has_atomic_move);
332 
333   /// Stores the size of `fname` in `*file_size`.
334   Status GetFileSize(const std::string& fname, uint64* file_size);
335 
GetFileSize(const std::string & fname,TransactionToken * token,uint64 * file_size)336   Status GetFileSize(const std::string& fname, TransactionToken* token,
337                      uint64* file_size) {
338     return Status::OK();
339   }
340 
341   /// \brief Renames file src to target. If target already exists, it will be
342   /// replaced.
343   Status RenameFile(const std::string& src, const std::string& target);
344 
RenameFile(const std::string & src,const std::string & target,TransactionToken * token)345   Status RenameFile(const std::string& src, const std::string& target,
346                     TransactionToken* token) {
347     return Status::OK();
348   }
349 
350   /// \brief Copy the src to target.
351   Status CopyFile(const std::string& src, const std::string& target);
352 
CopyFile(const std::string & src,const std::string & target,TransactionToken * token)353   Status CopyFile(const std::string& src, const std::string& target,
354                   TransactionToken* token) {
355     return Status::OK();
356   }
357 
358   /// \brief starts a new transaction on the filesystem that handles filename
StartTransaction(const std::string & filename,TransactionToken ** token)359   Status StartTransaction(const std::string& filename,
360                           TransactionToken** token) {
361     *token = nullptr;
362     return Status::OK();
363   }
364 
365   /// \brief Adds `path` to transaction in `token` if token belongs to
366   /// filesystem that handles the path.
AddToTransaction(const std::string & path,TransactionToken * token)367   Status AddToTransaction(const std::string& path, TransactionToken* token) {
368     return Status::OK();
369   }
370 
371   /// \brief Get token for `path` or start a new transaction and add `path` to
372   /// it.
GetTokenOrStartTransaction(const std::string & path,TransactionToken ** token)373   Status GetTokenOrStartTransaction(const std::string& path,
374                                     TransactionToken** token) {
375     *token = nullptr;
376     return Status::OK();
377   }
378 
379   /// \brief Returns the transaction for `path` or nullptr in `token`
GetTransactionForPath(const std::string & path,TransactionToken ** token)380   Status GetTransactionForPath(const std::string& path,
381                                TransactionToken** token) {
382     *token = nullptr;
383     return Status::OK();
384   }
385 
386   /// \brief Finalizes the transaction
EndTransaction(TransactionToken * token)387   Status EndTransaction(TransactionToken* token) { return Status::OK(); }
388 
389   /// \brief Returns the absolute path of the current executable. It resolves
390   /// symlinks if there is any.
391   std::string GetExecutablePath();
392 
393   /// Creates a local unique temporary file name. Returns true if success.
394   bool LocalTempFilename(std::string* filename);
395 
396   /// Creates a local unique file name that starts with |prefix| and ends with
397   /// |suffix|. Returns true if success.
398   bool CreateUniqueFileName(std::string* prefix, const std::string& suffix);
399 
400   /// \brief Return the runfiles directory if running under bazel. Returns
401   /// the directory the executable is located in if not running under bazel.
402   virtual std::string GetRunfilesDir() = 0;
403 
404   // TODO(jeff,sanjay): Add back thread/thread-pool support if needed.
405   // TODO(jeff,sanjay): if needed, tighten spec so relative to epoch, or
406   // provide a routine to get the absolute time.
407 
408   /// \brief Returns the number of nano-seconds since the Unix epoch.
NowNanos()409   virtual uint64 NowNanos() const { return EnvTime::NowNanos(); }
410 
411   /// \brief Returns the number of micro-seconds since the Unix epoch.
NowMicros()412   virtual uint64 NowMicros() const { return EnvTime::NowMicros(); }
413 
414   /// \brief Returns the number of seconds since the Unix epoch.
NowSeconds()415   virtual uint64 NowSeconds() const { return EnvTime::NowSeconds(); }
416 
417   /// Sleeps/delays the thread for the prescribed number of micro-seconds.
418   virtual void SleepForMicroseconds(int64_t micros) = 0;
419 
420   /// Returns the process ID of the calling process.
421   int32 GetProcessId();
422 
423   /// \brief Returns a new thread that is running fn() and is identified
424   /// (for debugging/performance-analysis) by "name".
425   ///
426   /// Caller takes ownership of the result and must delete it eventually
427   /// (the deletion will block until fn() stops running).
428   virtual Thread* StartThread(const ThreadOptions& thread_options,
429                               const std::string& name,
430                               std::function<void()> fn) TF_MUST_USE_RESULT = 0;
431 
432   // Returns the thread id of calling thread.
433   // Posix: Returns pthread id which is only guaranteed to be unique within a
434   //        process.
435   // Windows: Returns thread id which is unique.
436   virtual int32 GetCurrentThreadId() = 0;
437 
438   // Copies current thread name to "name". Returns true if success.
439   virtual bool GetCurrentThreadName(std::string* name) = 0;
440 
441   // \brief Schedules the given closure on a thread-pool.
442   //
443   // NOTE(mrry): This closure may block.
444   virtual void SchedClosure(std::function<void()> closure) = 0;
445 
446   // \brief Schedules the given closure on a thread-pool after the given number
447   // of microseconds.
448   //
449   // NOTE(mrry): This closure must not block.
450   virtual void SchedClosureAfter(int64_t micros,
451                                  std::function<void()> closure) = 0;
452 
453   // \brief Load a dynamic library.
454   //
455   // Pass "library_filename" to a platform-specific mechanism for dynamically
456   // loading a library.  The rules for determining the exact location of the
457   // library are platform-specific and are not documented here.
458   //
459   // On success, returns a handle to the library in "*handle" and returns
460   // OK from the function.
461   // Otherwise returns nullptr in "*handle" and an error status from the
462   // function.
463   virtual Status LoadDynamicLibrary(const char* library_filename,
464                                     void** handle) = 0;
465 
466   // \brief Get a pointer to a symbol from a dynamic library.
467   //
468   // "handle" should be a pointer returned from a previous call to LoadLibrary.
469   // On success, store a pointer to the located symbol in "*symbol" and return
470   // OK from the function. Otherwise, returns nullptr in "*symbol" and an error
471   // status from the function.
472   virtual Status GetSymbolFromLibrary(void* handle, const char* symbol_name,
473                                       void** symbol) = 0;
474 
475   // \brief build the name of dynamic library.
476   //
477   // "name" should be name of the library.
478   // "version" should be the version of the library or NULL
479   // returns the name that LoadLibrary() can use
480   virtual std::string FormatLibraryFileName(const std::string& name,
481                                             const std::string& version) = 0;
482 
483   // Returns a possible list of local temporary directories.
484   virtual void GetLocalTempDirectories(std::vector<string>* list) = 0;
485 
486  private:
487   std::unique_ptr<FileSystemRegistry> file_system_registry_;
488   TF_DISALLOW_COPY_AND_ASSIGN(Env);
489 };
490 
491 /// \brief An implementation of Env that forwards all calls to another Env.
492 ///
493 /// May be useful to clients who wish to override just part of the
494 /// functionality of another Env.
495 class EnvWrapper : public Env {
496  public:
497   /// Initializes an EnvWrapper that delegates all calls to *t
EnvWrapper(Env * t)498   explicit EnvWrapper(Env* t) : target_(t) {}
499   ~EnvWrapper() override;
500 
501   /// Returns the target to which this Env forwards all calls
target()502   Env* target() const { return target_; }
503 
GetFileSystemForFile(const std::string & fname,FileSystem ** result)504   Status GetFileSystemForFile(const std::string& fname,
505                               FileSystem** result) override {
506     return target_->GetFileSystemForFile(fname, result);
507   }
508 
GetRegisteredFileSystemSchemes(std::vector<string> * schemes)509   Status GetRegisteredFileSystemSchemes(std::vector<string>* schemes) override {
510     return target_->GetRegisteredFileSystemSchemes(schemes);
511   }
512 
RegisterFileSystem(const std::string & scheme,FileSystemRegistry::Factory factory)513   Status RegisterFileSystem(const std::string& scheme,
514                             FileSystemRegistry::Factory factory) override {
515     return target_->RegisterFileSystem(scheme, factory);
516   }
517 
MatchPath(const std::string & path,const std::string & pattern)518   bool MatchPath(const std::string& path, const std::string& pattern) override {
519     return target_->MatchPath(path, pattern);
520   }
521 
NowMicros()522   uint64 NowMicros() const override { return target_->NowMicros(); }
SleepForMicroseconds(int64_t micros)523   void SleepForMicroseconds(int64_t micros) override {
524     target_->SleepForMicroseconds(micros);
525   }
StartThread(const ThreadOptions & thread_options,const std::string & name,std::function<void ()> fn)526   Thread* StartThread(const ThreadOptions& thread_options,
527                       const std::string& name,
528                       std::function<void()> fn) override {
529     return target_->StartThread(thread_options, name, fn);
530   }
GetCurrentThreadId()531   int32 GetCurrentThreadId() override { return target_->GetCurrentThreadId(); }
GetCurrentThreadName(std::string * name)532   bool GetCurrentThreadName(std::string* name) override {
533     return target_->GetCurrentThreadName(name);
534   }
SchedClosure(std::function<void ()> closure)535   void SchedClosure(std::function<void()> closure) override {
536     target_->SchedClosure(closure);
537   }
SchedClosureAfter(int64_t micros,std::function<void ()> closure)538   void SchedClosureAfter(int64_t micros,
539                          std::function<void()> closure) override {
540     target_->SchedClosureAfter(micros, closure);
541   }
LoadDynamicLibrary(const char * library_filename,void ** handle)542   Status LoadDynamicLibrary(const char* library_filename,
543                             void** handle) override {
544     return target_->LoadDynamicLibrary(library_filename, handle);
545   }
GetSymbolFromLibrary(void * handle,const char * symbol_name,void ** symbol)546   Status GetSymbolFromLibrary(void* handle, const char* symbol_name,
547                               void** symbol) override {
548     return target_->GetSymbolFromLibrary(handle, symbol_name, symbol);
549   }
FormatLibraryFileName(const std::string & name,const std::string & version)550   std::string FormatLibraryFileName(const std::string& name,
551                                     const std::string& version) override {
552     return target_->FormatLibraryFileName(name, version);
553   }
554 
GetRunfilesDir()555   std::string GetRunfilesDir() override { return target_->GetRunfilesDir(); }
556 
557  private:
GetLocalTempDirectories(std::vector<string> * list)558   void GetLocalTempDirectories(std::vector<string>* list) override {
559     target_->GetLocalTempDirectories(list);
560   }
561 
562   Env* target_;
563 };
564 
565 /// Represents a thread used to run a TensorFlow function.
566 class Thread {
567  public:
Thread()568   Thread() {}
569 
570   /// Blocks until the thread of control stops running.
571   virtual ~Thread();
572 
573  private:
574   TF_DISALLOW_COPY_AND_ASSIGN(Thread);
575 };
576 
577 /// \brief Cross-platform setenv.
578 ///
579 /// Since setenv() is not available on windows, we provide an
580 /// alternative with platform specific implementations here.
581 int setenv(const char* name, const char* value, int overwrite);
582 
583 /// Cross-platform unsetenv.
584 int unsetenv(const char* name);
585 
586 /// \brief Options to configure a Thread.
587 ///
588 /// Note that the options are all hints, and the
589 /// underlying implementation may choose to ignore it.
590 struct ThreadOptions {
591   /// Thread stack size to use (in bytes).
592   size_t stack_size = 0;  // 0: use system default value
593   /// Guard area size to use near thread stacks to use (in bytes)
594   size_t guard_size = 0;  // 0: use system default value
595   int numa_node = port::kNUMANoAffinity;
596 };
597 
598 /// A utility routine: copy contents of `src` in file system `src_fs`
599 /// to `target` in file system `target_fs`.
600 Status FileSystemCopyFile(FileSystem* src_fs, const std::string& src,
601                           FileSystem* target_fs, const std::string& target);
602 
603 /// A utility routine: reads contents of named file into `*data`
604 Status ReadFileToString(Env* env, const std::string& fname, std::string* data);
605 
606 /// A utility routine: write contents of `data` to file named `fname`
607 /// (overwriting existing contents, if any).
608 Status WriteStringToFile(Env* env, const std::string& fname,
609                          const StringPiece& data);
610 
611 /// Write binary representation of "proto" to the named file.
612 Status WriteBinaryProto(Env* env, const std::string& fname,
613                         const protobuf::MessageLite& proto);
614 
615 /// Reads contents of named file and parse as binary encoded proto data
616 /// and store into `*proto`.
617 Status ReadBinaryProto(Env* env, const std::string& fname,
618                        protobuf::MessageLite* proto);
619 
620 /// Write the text representation of "proto" to the named file.
WriteTextProto(Env *,const std::string &,const protobuf::MessageLite &)621 inline Status WriteTextProto(Env* /* env */, const std::string& /* fname */,
622                              const protobuf::MessageLite& /* proto */) {
623   return errors::Unimplemented("Can't write text protos with protolite.");
624 }
625 Status WriteTextProto(Env* env, const std::string& fname,
626                       const protobuf::Message& proto);
627 
628 /// Read contents of named file and parse as text encoded proto data
629 /// and store into `*proto`.
ReadTextProto(Env *,const std::string &,protobuf::MessageLite *)630 inline Status ReadTextProto(Env* /* env */, const std::string& /* fname */,
631                             protobuf::MessageLite* /* proto */) {
632   return errors::Unimplemented("Can't parse text protos with protolite.");
633 }
634 Status ReadTextProto(Env* env, const std::string& fname,
635                      protobuf::Message* proto);
636 
637 /// Read contents of named file and parse as either text or binary encoded proto
638 /// data and store into `*proto`.
639 Status ReadTextOrBinaryProto(Env* env, const std::string& fname,
640                              protobuf::Message* proto);
641 Status ReadTextOrBinaryProto(Env* env, const std::string& fname,
642                              protobuf::MessageLite* proto);
643 
644 // START_SKIP_DOXYGEN
645 
646 // The following approach to register filesystems is deprecated and will be
647 // replaced with modular filesystem plugins registration.
648 // TODO(mihaimaruseac): After all filesystems are converted, remove this.
649 namespace register_file_system {
650 
651 template <typename Factory>
652 struct Register {
RegisterRegister653   Register(Env* env, const std::string& scheme, bool try_modular_filesystems) {
654     // TODO(yongtang): Remove legacy file system registration for hdfs/s3/gcs
655     // after TF 2.6+.
656     if (try_modular_filesystems) {
657       const char* env_value = getenv("TF_USE_MODULAR_FILESYSTEM");
658       string load_plugin = env_value ? absl::AsciiStrToLower(env_value) : "";
659       if (load_plugin == "true" || load_plugin == "1") {
660         // We don't register the static filesystem and wait for SIG IO one
661         LOG(WARNING) << "Using modular file system for '" << scheme << "'."
662                      << " Please switch to tensorflow-io"
663                      << " (https://github.com/tensorflow/io) for file system"
664                      << " support of '" << scheme << "'.";
665         return;
666       }
667       // If the envvar is missing or not "true"/"1", then fall back to legacy
668       // implementation to be backwards compatible.
669     }
670     // TODO(b/32704451): Don't just ignore the ::tensorflow::Status object!
671     env->RegisterFileSystem(scheme, []() -> FileSystem* { return new Factory; })
672         .IgnoreError();
673   }
674 };
675 
676 }  // namespace register_file_system
677 
678 // END_SKIP_DOXYGEN
679 
680 }  // namespace tensorflow
681 
682 // Register a FileSystem implementation for a scheme. Files with names that have
683 // "scheme://" prefixes are routed to use this implementation.
684 #define REGISTER_FILE_SYSTEM_ENV(env, scheme, factory, modular) \
685   REGISTER_FILE_SYSTEM_UNIQ_HELPER(__COUNTER__, env, scheme, factory, modular)
686 #define REGISTER_FILE_SYSTEM_UNIQ_HELPER(ctr, env, scheme, factory, modular) \
687   REGISTER_FILE_SYSTEM_UNIQ(ctr, env, scheme, factory, modular)
688 #define REGISTER_FILE_SYSTEM_UNIQ(ctr, env, scheme, factory, modular)        \
689   static ::tensorflow::register_file_system::Register<factory>               \
690       register_ff##ctr TF_ATTRIBUTE_UNUSED =                                 \
691           ::tensorflow::register_file_system::Register<factory>(env, scheme, \
692                                                                 modular)
693 
694 #define REGISTER_FILE_SYSTEM(scheme, factory)                             \
695   REGISTER_FILE_SYSTEM_ENV(::tensorflow::Env::Default(), scheme, factory, \
696                            false);
697 
698 #define REGISTER_LEGACY_FILE_SYSTEM(scheme, factory) \
699   REGISTER_FILE_SYSTEM_ENV(::tensorflow::Env::Default(), scheme, factory, true);
700 
701 #endif  // TENSORFLOW_CORE_PLATFORM_ENV_H_
702