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