1 /* Copyright 2018 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 #include "tensorflow/c/env.h"
17 
18 #include "tensorflow/c/c_api_internal.h"
19 #include "tensorflow/c/tf_status_helper.h"
20 #include "tensorflow/core/platform/env.h"
21 #include "tensorflow/core/platform/types.h"
22 
23 struct TF_StringStream {
24   std::vector<::tensorflow::string>* list;
25   size_t position;
26 };
27 
TF_CreateDir(const char * dirname,TF_Status * status)28 void TF_CreateDir(const char* dirname, TF_Status* status) {
29   TF_SetStatus(status, TF_OK, "");
30   ::tensorflow::Set_TF_Status_from_Status(
31       status, ::tensorflow::Env::Default()->CreateDir(dirname));
32 }
33 
TF_DeleteDir(const char * dirname,TF_Status * status)34 void TF_DeleteDir(const char* dirname, TF_Status* status) {
35   TF_SetStatus(status, TF_OK, "");
36   ::tensorflow::Set_TF_Status_from_Status(
37       status, ::tensorflow::Env::Default()->DeleteDir(dirname));
38 }
39 
TF_DeleteRecursively(const char * dirname,int64_t * undeleted_file_count,int64_t * undeleted_dir_count,TF_Status * status)40 void TF_DeleteRecursively(const char* dirname, int64_t* undeleted_file_count,
41                           int64_t* undeleted_dir_count, TF_Status* status) {
42   ::tensorflow::int64 f, d;
43 
44   TF_SetStatus(status, TF_OK, "");
45   ::tensorflow::Set_TF_Status_from_Status(
46       status, ::tensorflow::Env::Default()->DeleteRecursively(dirname, &f, &d));
47   *undeleted_file_count = f;
48   *undeleted_dir_count = d;
49 }
50 
TF_FileStat(const char * filename,TF_FileStatistics * stats,TF_Status * status)51 void TF_FileStat(const char* filename, TF_FileStatistics* stats,
52                  TF_Status* status) {
53   ::tensorflow::FileStatistics cc_stats;
54   TF_SetStatus(status, TF_OK, "");
55   ::tensorflow::Status s =
56       ::tensorflow::Env::Default()->Stat(filename, &cc_stats);
57   ::tensorflow::Set_TF_Status_from_Status(status, s);
58   if (s.ok()) {
59     stats->length = cc_stats.length;
60     stats->mtime_nsec = cc_stats.mtime_nsec;
61     stats->is_directory = cc_stats.is_directory;
62   }
63 }
64 
TF_NewWritableFile(const char * filename,TF_WritableFileHandle ** handle,TF_Status * status)65 void TF_NewWritableFile(const char* filename, TF_WritableFileHandle** handle,
66                         TF_Status* status) {
67   std::unique_ptr<::tensorflow::WritableFile> f;
68   TF_SetStatus(status, TF_OK, "");
69   ::tensorflow::Status s =
70       ::tensorflow::Env::Default()->NewWritableFile(filename, &f);
71   ::tensorflow::Set_TF_Status_from_Status(status, s);
72 
73   if (s.ok()) {
74     *handle = reinterpret_cast<TF_WritableFileHandle*>(f.release());
75   }
76 }
77 
TF_CloseWritableFile(TF_WritableFileHandle * handle,TF_Status * status)78 void TF_CloseWritableFile(TF_WritableFileHandle* handle, TF_Status* status) {
79   auto* cc_file = reinterpret_cast<::tensorflow::WritableFile*>(handle);
80   TF_SetStatus(status, TF_OK, "");
81   ::tensorflow::Set_TF_Status_from_Status(status, cc_file->Close());
82   delete cc_file;
83 }
84 
TF_SyncWritableFile(TF_WritableFileHandle * handle,TF_Status * status)85 void TF_SyncWritableFile(TF_WritableFileHandle* handle, TF_Status* status) {
86   auto* cc_file = reinterpret_cast<::tensorflow::WritableFile*>(handle);
87   TF_SetStatus(status, TF_OK, "");
88   ::tensorflow::Set_TF_Status_from_Status(status, cc_file->Sync());
89 }
90 
TF_FlushWritableFile(TF_WritableFileHandle * handle,TF_Status * status)91 void TF_FlushWritableFile(TF_WritableFileHandle* handle, TF_Status* status) {
92   auto* cc_file = reinterpret_cast<::tensorflow::WritableFile*>(handle);
93   TF_SetStatus(status, TF_OK, "");
94   ::tensorflow::Set_TF_Status_from_Status(status, cc_file->Flush());
95 }
96 
TF_AppendWritableFile(TF_WritableFileHandle * handle,const char * data,size_t length,TF_Status * status)97 void TF_AppendWritableFile(TF_WritableFileHandle* handle, const char* data,
98                            size_t length, TF_Status* status) {
99   auto* cc_file = reinterpret_cast<::tensorflow::WritableFile*>(handle);
100   TF_SetStatus(status, TF_OK, "");
101   ::tensorflow::Set_TF_Status_from_Status(
102       status, cc_file->Append(::tensorflow::StringPiece{data, length}));
103 }
104 
TF_DeleteFile(const char * filename,TF_Status * status)105 void TF_DeleteFile(const char* filename, TF_Status* status) {
106   TF_SetStatus(status, TF_OK, "");
107   ::tensorflow::Set_TF_Status_from_Status(
108       status, ::tensorflow::Env::Default()->DeleteFile(filename));
109 }
110 
TF_StringStreamNext(TF_StringStream * list,const char ** result)111 bool TF_StringStreamNext(TF_StringStream* list, const char** result) {
112   if (list->position >= list->list->size()) {
113     *result = nullptr;
114     return false;
115   }
116 
117   *result = list->list->at(list->position++).c_str();
118   return true;
119 }
120 
TF_StringStreamDone(TF_StringStream * list)121 void TF_StringStreamDone(TF_StringStream* list) {
122   delete list->list;
123   delete list;
124 }
TF_GetChildren(const char * dirname,TF_Status * status)125 TF_StringStream* TF_GetChildren(const char* dirname, TF_Status* status) {
126   auto* children = new std::vector<::tensorflow::string>;
127 
128   TF_SetStatus(status, TF_OK, "");
129   ::tensorflow::Set_TF_Status_from_Status(
130       status, ::tensorflow::Env::Default()->GetChildren(dirname, children));
131 
132   auto* list = new TF_StringStream;
133   list->list = children;
134   list->position = 0;
135   return list;
136 }
137 
TF_GetLocalTempDirectories()138 TF_StringStream* TF_GetLocalTempDirectories() {
139   auto* tmpdirs = new std::vector<::tensorflow::string>;
140 
141   ::tensorflow::Env::Default()->GetLocalTempDirectories(tmpdirs);
142 
143   auto* list = new TF_StringStream;
144   list->list = tmpdirs;
145   list->position = 0;
146   return list;
147 }
148 
TF_NowNanos(void)149 TF_CAPI_EXPORT extern uint64_t TF_NowNanos(void) {
150   return ::tensorflow::Env::Default()->NowNanos();
151 }
152 
153 // Returns the number of microseconds since the Unix epoch.
TF_NowMicros(void)154 TF_CAPI_EXPORT extern uint64_t TF_NowMicros(void) {
155   return ::tensorflow::Env::Default()->NowMicros();
156 }
157 
158 // Returns the number of seconds since the Unix epoch.
TF_NowSeconds(void)159 TF_CAPI_EXPORT extern uint64_t TF_NowSeconds(void) {
160   return ::tensorflow::Env::Default()->NowSeconds();
161 }
162 
TF_DefaultThreadOptions(TF_ThreadOptions * options)163 void TF_DefaultThreadOptions(TF_ThreadOptions* options) {
164   options->stack_size = 0;
165   options->guard_size = 0;
166   options->numa_node = -1;
167 }
168 
TF_StartThread(const TF_ThreadOptions * options,const char * thread_name,void (* work_func)(void *),void * param)169 TF_Thread* TF_StartThread(const TF_ThreadOptions* options,
170                           const char* thread_name, void (*work_func)(void*),
171                           void* param) {
172   ::tensorflow::ThreadOptions cc_options;
173   cc_options.stack_size = options->stack_size;
174   cc_options.guard_size = options->guard_size;
175   cc_options.numa_node = options->numa_node;
176   return reinterpret_cast<TF_Thread*>(::tensorflow::Env::Default()->StartThread(
177       cc_options, thread_name, [=]() { (*work_func)(param); }));
178 }
179 
TF_JoinThread(TF_Thread * thread)180 void TF_JoinThread(TF_Thread* thread) {
181   // ::tensorflow::Thread joins on destruction
182   delete reinterpret_cast<::tensorflow::Thread*>(thread);
183 }
184