1/* Copyright 2018 The TensorFlow Authors. All Rights Reserved.
2
3Licensed under the Apache License, Version 2.0 (the "License");
4you may not use this file except in compliance with the License.
5You may obtain a copy of the License at
6
7 http://www.apache.org/licenses/LICENSE-2.0
8
9Unless required by applicable law or agreed to in writing, software
10distributed under the License is distributed on an "AS IS" BASIS,
11WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12See the License for the specific language governing permissions and
13limitations under the License.
14==============================================================================*/
15
16#include "tensorflow/c/env.h"
17
18#include "tensorflow/c/c_api_macros.h"
19#include "tensorflow/c/tf_status.h"
20#include "tensorflow/c/tf_status_helper.h"
21#include "tensorflow/core/platform/env.h"
22#include "tensorflow/core/platform/path.h"
23#include "tensorflow/core/platform/types.h"
24
25struct TF_StringStream {
26 std::vector<::tensorflow::string>* list;
27 size_t position;
28};
29
30void TF_CreateDir(const char* dirname, TF_Status* status) {
31 TF_SetStatus(status, TF_OK, "");
32 ::tensorflow::Set_TF_Status_from_Status(
33 status, ::tensorflow::Env::Default()->CreateDir(dirname));
34}
35
36void TF_DeleteDir(const char* dirname, TF_Status* status) {
37 TF_SetStatus(status, TF_OK, "");
38 ::tensorflow::Set_TF_Status_from_Status(
39 status, ::tensorflow::Env::Default()->DeleteDir(dirname));
40}
41
42void TF_DeleteRecursively(const char* dirname, int64_t* undeleted_file_count,
43 int64_t* undeleted_dir_count, TF_Status* status) {
44 ::int64_t f, d;
45
46 TF_SetStatus(status, TF_OK, "");
47 ::tensorflow::Set_TF_Status_from_Status(
48 status, ::tensorflow::Env::Default()->DeleteRecursively(dirname, &f, &d));
49 *undeleted_file_count = f;
50 *undeleted_dir_count = d;
51}
52
53void TF_FileStat(const char* filename, TF_FileStatistics* stats,
54 TF_Status* status) {
55 ::tensorflow::FileStatistics cc_stats;
56 TF_SetStatus(status, TF_OK, "");
57 ::tensorflow::Status s =
58 ::tensorflow::Env::Default()->Stat(filename, &cc_stats);
59 ::tensorflow::Set_TF_Status_from_Status(status, s);
60 if (s.ok()) {
61 stats->length = cc_stats.length;
62 stats->mtime_nsec = cc_stats.mtime_nsec;
63 stats->is_directory = cc_stats.is_directory;
64 }
65}
66
67void TF_NewWritableFile(const char* filename, TF_WritableFileHandle** handle,
68 TF_Status* status) {
69 std::unique_ptr<::tensorflow::WritableFile> f;
70 TF_SetStatus(status, TF_OK, "");
71 ::tensorflow::Status s =
72 ::tensorflow::Env::Default()->NewWritableFile(filename, &f);
73 ::tensorflow::Set_TF_Status_from_Status(status, s);
74
75 if (s.ok()) {
76 *handle = reinterpret_cast<TF_WritableFileHandle*>(f.release());
77 }
78}
79
80void TF_CloseWritableFile(TF_WritableFileHandle* handle, TF_Status* status) {
81 auto* cc_file = reinterpret_cast<::tensorflow::WritableFile*>(handle);
82 TF_SetStatus(status, TF_OK, "");
83 ::tensorflow::Set_TF_Status_from_Status(status, cc_file->Close());
84 delete cc_file;
85}
86
87void TF_SyncWritableFile(TF_WritableFileHandle* handle, TF_Status* status) {
88 auto* cc_file = reinterpret_cast<::tensorflow::WritableFile*>(handle);
89 TF_SetStatus(status, TF_OK, "");
90 ::tensorflow::Set_TF_Status_from_Status(status, cc_file->Sync());
91}
92
93void TF_FlushWritableFile(TF_WritableFileHandle* handle, TF_Status* status) {
94 auto* cc_file = reinterpret_cast<::tensorflow::WritableFile*>(handle);
95 TF_SetStatus(status, TF_OK, "");
96 ::tensorflow::Set_TF_Status_from_Status(status, cc_file->Flush());
97}
98
99void TF_AppendWritableFile(TF_WritableFileHandle* handle, const char* data,
100 size_t length, TF_Status* status) {
101 auto* cc_file = reinterpret_cast<::tensorflow::WritableFile*>(handle);
102 TF_SetStatus(status, TF_OK, "");
103 ::tensorflow::Set_TF_Status_from_Status(
104 status, cc_file->Append(::tensorflow::StringPiece{data, length}));
105}
106
107void TF_DeleteFile(const char* filename, TF_Status* status) {
108 TF_SetStatus(status, TF_OK, "");
109 ::tensorflow::Set_TF_Status_from_Status(
110 status, ::tensorflow::Env::Default()->DeleteFile(filename));
111}
112
113bool TF_StringStreamNext(TF_StringStream* list, const char** result) {
114 if (list->position >= list->list->size()) {
115 *result = nullptr;
116 return false;
117 }
118
119 *result = list->list->at(list->position++).c_str();
120 return true;
121}
122
123void TF_StringStreamDone(TF_StringStream* list) {
124 delete list->list;
125 delete list;
126}
127TF_StringStream* TF_GetChildren(const char* dirname, TF_Status* status) {
128 auto* children = new std::vector<::tensorflow::string>;
129
130 TF_SetStatus(status, TF_OK, "");
131 ::tensorflow::Set_TF_Status_from_Status(
132 status, ::tensorflow::Env::Default()->GetChildren(dirname, children));
133
134 auto* list = new TF_StringStream;
135 list->list = children;
136 list->position = 0;
137 return list;
138}
139
140TF_StringStream* TF_GetLocalTempDirectories() {
141 auto* tmpdirs = new std::vector<::tensorflow::string>;
142
143 ::tensorflow::Env::Default()->GetLocalTempDirectories(tmpdirs);
144
145 auto* list = new TF_StringStream;
146 list->list = tmpdirs;
147 list->position = 0;
148 return list;
149}
150
151char* TF_GetTempFileName(const char* extension) {
152 return strdup(::tensorflow::io::GetTempFilename(extension).c_str());
153}
154
155TF_CAPI_EXPORT extern uint64_t TF_NowNanos(void) {
156 return ::tensorflow::Env::Default()->NowNanos();
157}
158
159// Returns the number of microseconds since the Unix epoch.
160TF_CAPI_EXPORT extern uint64_t TF_NowMicros(void) {
161 return ::tensorflow::Env::Default()->NowMicros();
162}
163
164// Returns the number of seconds since the Unix epoch.
165TF_CAPI_EXPORT extern uint64_t TF_NowSeconds(void) {
166 return ::tensorflow::Env::Default()->NowSeconds();
167}
168
169void TF_DefaultThreadOptions(TF_ThreadOptions* options) {
170 options->stack_size = 0;
171 options->guard_size = 0;
172 options->numa_node = -1;
173}
174
175TF_Thread* TF_StartThread(const TF_ThreadOptions* options,
176 const char* thread_name, void (*work_func)(void*),
177 void* param) {
178 ::tensorflow::ThreadOptions cc_options;
179 cc_options.stack_size = options->stack_size;
180 cc_options.guard_size = options->guard_size;
181 cc_options.numa_node = options->numa_node;
182 return reinterpret_cast<TF_Thread*>(::tensorflow::Env::Default()->StartThread(
183 cc_options, thread_name, [=]() { (*work_func)(param); }));
184}
185
186void TF_JoinThread(TF_Thread* thread) {
187 // ::tensorflow::Thread joins on destruction
188 delete reinterpret_cast<::tensorflow::Thread*>(thread);
189}
190
191void* TF_LoadSharedLibrary(const char* library_filename, TF_Status* status) {
192 void* handle = nullptr;
193 TF_SetStatus(status, TF_OK, "");
194 ::tensorflow::Set_TF_Status_from_Status(
195 status, ::tensorflow::Env::Default()->LoadDynamicLibrary(library_filename,
196 &handle));
197 return handle;
198}
199
200void* TF_GetSymbolFromLibrary(void* handle, const char* symbol_name,
201 TF_Status* status) {
202 void* symbol = nullptr;
203 TF_SetStatus(status, TF_OK, "");
204 ::tensorflow::Set_TF_Status_from_Status(
205 status, ::tensorflow::Env::Default()->GetSymbolFromLibrary(
206 handle, symbol_name, &symbol));
207 return symbol;
208}
209