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