diff options
author | A. Unique TensorFlower <gardener@tensorflow.org> | 2016-10-10 10:26:22 -0800 |
---|---|---|
committer | TensorFlower Gardener <gardener@tensorflow.org> | 2016-10-10 11:35:00 -0700 |
commit | edaf3b342db4afa1c872da541fb0ac176a4e8ef9 (patch) | |
tree | b976073fdc2a6404cbdc3ee323a637e2e1b16846 /tensorflow/core/platform/windows | |
parent | d1518c26530daaee854e73365bd7dfb9a2f69dbd (diff) |
Merge changes from github.
Change: 135698415
Diffstat (limited to 'tensorflow/core/platform/windows')
-rw-r--r-- | tensorflow/core/platform/windows/env.cc | 113 | ||||
-rw-r--r-- | tensorflow/core/platform/windows/net.cc | 131 | ||||
-rw-r--r-- | tensorflow/core/platform/windows/port.cc | 99 | ||||
-rw-r--r-- | tensorflow/core/platform/windows/windows_file_system.cc | 266 | ||||
-rw-r--r-- | tensorflow/core/platform/windows/windows_file_system.h | 71 |
5 files changed, 680 insertions, 0 deletions
diff --git a/tensorflow/core/platform/windows/env.cc b/tensorflow/core/platform/windows/env.cc new file mode 100644 index 0000000000..a2182a831c --- /dev/null +++ b/tensorflow/core/platform/windows/env.cc @@ -0,0 +1,113 @@ +/* Copyright 2015 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/core/platform/env.h" + +#include <Shlwapi.h> +#include <Windows.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <time.h> +#undef LoadLibrary +#undef ERROR + +#include <thread> +#include <vector> + +#include "tensorflow/core/lib/core/error_codes.pb.h" +#include "tensorflow/core/platform/load_library.h" +#include "tensorflow/core/platform/logging.h" +#include "tensorflow/core/platform/windows/windows_file_system.h" + +namespace tensorflow { + +namespace { + +class StdThread : public Thread { + public: + // name and thread_options are both ignored. + StdThread(const ThreadOptions& thread_options, const string& name, + std::function<void()> fn) + : thread_(fn) {} + ~StdThread() { thread_.join(); } + + private: + std::thread thread_; +}; + +class WindowsEnv : public Env { + public: + WindowsEnv() {} + ~WindowsEnv() override { + LOG(FATAL) << "Env::Default() must not be destroyed"; + } + + bool MatchPath(const string& path, const string& pattern) override { + return PathMatchSpec(path.c_str(), pattern.c_str()) == S_OK; + } + + uint64 NowMicros() override { + FILETIME temp; + GetSystemTimeAsFileTime(&temp); + uint64 now_ticks = + (uint64)temp.dwLowDateTime + ((uint64)(temp.dwHighDateTime) << 32LL); + return now_ticks / 10LL; + } + + void SleepForMicroseconds(int64 micros) override { Sleep(micros / 1000); } + + Thread* StartThread(const ThreadOptions& thread_options, const string& name, + std::function<void()> fn) override { + return new StdThread(thread_options, name, fn); + } + + void SchedClosure(std::function<void()> closure) override { + // TODO(b/27290852): Spawning a new thread here is wasteful, but + // needed to deal with the fact that many `closure` functions are + // blocking in the current codebase. + std::thread closure_thread(closure); + closure_thread.detach(); + } + + void SchedClosureAfter(int64 micros, std::function<void()> closure) override { + // TODO(b/27290852): Consuming a thread here is wasteful, but this + // code is (currently) only used in the case where a step fails + // (AbortStep). This could be replaced by a timer thread + SchedClosure([this, micros, closure]() { + SleepForMicroseconds(micros); + closure(); + }); + } + + Status LoadLibrary(const char* library_filename, void** handle) override { + return errors::Unimplemented("WindowsEnv::LoadLibrary"); + } + + Status GetSymbolFromLibrary(void* handle, const char* symbol_name, + void** symbol) override { + return errors::Unimplemented("WindowsEnv::GetSymbolFromLibrary"); + } +}; + +} // namespace + +REGISTER_FILE_SYSTEM("", WindowsFileSystem); +Env* Env::Default() { + static Env* default_env = new WindowsEnv; + return default_env; +} + +} // namespace tensorflow diff --git a/tensorflow/core/platform/windows/net.cc b/tensorflow/core/platform/windows/net.cc new file mode 100644 index 0000000000..fbc0c39c9c --- /dev/null +++ b/tensorflow/core/platform/windows/net.cc @@ -0,0 +1,131 @@ +/* Copyright 2016 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow/core/platform/net.h" + +#include <cerrno> +#include <cstdlib> +#include <unordered_set> + +#include <sys/types.h> +#include <winsock.h> + +#include "tensorflow/core/lib/strings/strcat.h" +#include "tensorflow/core/platform/logging.h" + +#undef ERROR + +namespace tensorflow { +namespace internal { + +namespace { +bool IsPortAvailable(int* port, bool is_tcp) { + const int protocol = is_tcp ? IPPROTO_TCP : 0; + const int fd = socket(AF_INET, is_tcp ? SOCK_STREAM : SOCK_DGRAM, protocol); + + struct sockaddr_in addr; + int addr_len = static_cast<int>(sizeof(addr)); + int actual_port; + + CHECK_GE(*port, 0); + CHECK_LE(*port, 65535); + if (fd < 0) { + LOG(ERROR) << "socket() failed: " << strerror(errno); + return false; + } + + // SO_REUSEADDR lets us start up a server immediately after it exists. + int one = 1; + if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&one, sizeof(one)) < + 0) { + LOG(ERROR) << "setsockopt() failed: " << strerror(errno); + closesocket(fd); + return false; + } + + // Try binding to port. + addr.sin_family = AF_INET; + addr.sin_addr.s_addr = INADDR_ANY; + addr.sin_port = htons((uint16_t)*port); + if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + LOG(WARNING) << "bind(port=" << *port << ") failed: " << strerror(errno); + closesocket(fd); + return false; + } + + // Get the bound port number. + if (getsockname(fd, (struct sockaddr*)&addr, &addr_len) < 0) { + LOG(WARNING) << "getsockname() failed: " << strerror(errno); + closesocket(fd); + return false; + } + CHECK_LE(addr_len, sizeof(addr)); + actual_port = ntohs(addr.sin_port); + CHECK_GT(actual_port, 0); + if (*port == 0) { + *port = actual_port; + } else { + CHECK_EQ(*port, actual_port); + } + closesocket(fd); + return true; +} + +const int kNumRandomPortsToPick = 100; +const int kMaximumTrials = 1000; + +} // namespace + +int PickUnusedPortOrDie() { + static std::unordered_set<int> chosen_ports; + + // Type of port to first pick in the next iteration. + bool is_tcp = true; + int trial = 0; + while (true) { + int port; + trial++; + CHECK_LE(trial, kMaximumTrials) + << "Failed to pick an unused port for testing."; + if (trial == 1) { + port = GetCurrentProcessId() % (65536 - 30000) + 30000; + } else if (trial <= kNumRandomPortsToPick) { + port = rand() % (65536 - 30000) + 30000; + } else { + port = 0; + } + + if (chosen_ports.find(port) != chosen_ports.end()) { + continue; + } + if (!IsPortAvailable(&port, is_tcp)) { + continue; + } + + CHECK_GT(port, 0); + if (!IsPortAvailable(&port, !is_tcp)) { + is_tcp = !is_tcp; + continue; + } + + chosen_ports.insert(port); + return port; + } + + return 0; +} + +} // namespace internal +} // namespace tensorflow diff --git a/tensorflow/core/platform/windows/port.cc b/tensorflow/core/platform/windows/port.cc new file mode 100644 index 0000000000..b08c1cf9f4 --- /dev/null +++ b/tensorflow/core/platform/windows/port.cc @@ -0,0 +1,99 @@ +/* Copyright 2016 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifdef SNAPPY +#include <snappy.h> +#endif +#include <WinSock2.h> + +#include "tensorflow/core/platform/cpu_info.h" +#include "tensorflow/core/platform/demangle.h" +#include "tensorflow/core/platform/host_info.h" +#include "tensorflow/core/platform/init_main.h" +#include "tensorflow/core/platform/logging.h" +#include "tensorflow/core/platform/mem.h" +#include "tensorflow/core/platform/snappy.h" +#include "tensorflow/core/platform/types.h" + +namespace tensorflow { +namespace port { + +void InitMain(const char* usage, int* argc, char*** argv) {} + +string Hostname() { + char hostname[1024]; + gethostname(hostname, sizeof hostname); + hostname[sizeof hostname - 1] = 0; + return string(hostname); +} + +int NumSchedulableCPUs() { + SYSTEM_INFO system_info; + GetSystemInfo(&system_info); + return system_info.dwNumberOfProcessors; +} + +void* aligned_malloc(size_t size, int minimum_alignment) { + return _aligned_malloc(size, minimum_alignment); +} + +void aligned_free(void* aligned_memory) { _aligned_free(aligned_memory); } + +void MallocExtension_ReleaseToSystem(std::size_t num_bytes) { + // No-op. +} + +std::size_t MallocExtension_GetAllocatedSize(const void* p) { return 0; } + +void AdjustFilenameForLogging(string* filename) { + // Nothing to do +} + +bool Snappy_Compress(const char* input, size_t length, string* output) { +#ifdef SNAPPY + output->resize(snappy::MaxCompressedLength(length)); + size_t outlen; + snappy::RawCompress(input, length, &(*output)[0], &outlen); + output->resize(outlen); + return true; +#else + return false; +#endif +} + +bool Snappy_GetUncompressedLength(const char* input, size_t length, + size_t* result) { +#ifdef SNAPPY + return snappy::GetUncompressedLength(input, length, result); +#else + return false; +#endif +} + +bool Snappy_Uncompress(const char* input, size_t length, char* output) { +#ifdef SNAPPY + return snappy::RawUncompress(input, length, output); +#else + return false; +#endif +} + +string Demangle(const char* mangled) { return mangled; } + +} // namespace port +} // namespace tensorflow diff --git a/tensorflow/core/platform/windows/windows_file_system.cc b/tensorflow/core/platform/windows/windows_file_system.cc new file mode 100644 index 0000000000..44b26d94e8 --- /dev/null +++ b/tensorflow/core/platform/windows/windows_file_system.cc @@ -0,0 +1,266 @@ +/* Copyright 2015 Google Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include <Windows.h> +#include <direct.h> +#include <errno.h> +#include <fcntl.h> +#include <io.h> +#include <Shlwapi.h> +#undef StrCat +#include <stdio.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <time.h> + +#include "tensorflow/core/lib/core/error_codes.pb.h" +#include "tensorflow/core/lib/strings/strcat.h" +#include "tensorflow/core/platform/env.h" +#include "tensorflow/core/platform/logging.h" +#include "tensorflow/core/platform/posix/error.h" +#include "tensorflow/core/platform/windows/windows_file_system.h" + +// TODO(mrry): Prevent this Windows.h #define from leaking out of our headers. +#undef DeleteFile + +namespace tensorflow { + +namespace { + +// read() based random-access +class WindowsRandomAccessFile : public RandomAccessFile { + private: + string filename_; + FILE* file_; + + public: + WindowsRandomAccessFile(const string& fname, FILE* f) + : filename_(fname), file_(f) {} + ~WindowsRandomAccessFile() override { + if (file_ != NULL) { + // Ignoring any potential errors + fclose(file_); + } + } + + Status Read(uint64 offset, size_t n, StringPiece* result, + char* scratch) const override { + Status s; + char* dst = scratch; + int seek_result = fseek(file_, offset, SEEK_SET); + if (seek_result) { + return IOError(filename_, errno); + } + while (n > 0 && s.ok()) { + size_t r = fread(dst, 1, n, file_); + if (r > 0) { + dst += r; + n -= r; + } else if (r == 0) { + s = Status(error::OUT_OF_RANGE, "Read fewer bytes than requested"); + } else if (errno == EINTR || errno == EAGAIN) { + // Retry + } else { + s = IOError(filename_, errno); + } + } + *result = StringPiece(scratch, dst - scratch); + return s; + } +}; + +class WindowsWritableFile : public WritableFile { + private: + string filename_; + FILE* file_; + + public: + WindowsWritableFile(const string& fname, FILE* f) + : filename_(fname), file_(f) {} + + ~WindowsWritableFile() override { + if (file_ != NULL) { + // Ignoring any potential errors + fclose(file_); + } + } + + Status Append(const StringPiece& data) override { + size_t r = fwrite(data.data(), 1, data.size(), file_); + if (r != data.size()) { + return IOError(filename_, errno); + } + return Status::OK(); + } + + Status Close() override { + Status result; + if (fclose(file_) != 0) { + result = IOError(filename_, errno); + } + file_ = NULL; + return result; + } + + Status Flush() override { + if (fflush(file_) != 0) { + return IOError(filename_, errno); + } + return Status::OK(); + } + + Status Sync() override { + Status s; + if (fflush(file_) != 0) { + s = IOError(filename_, errno); + } + return s; + } +}; + +} // namespace + +Status WindowsFileSystem::NewRandomAccessFile( + const string& fname, std::unique_ptr<RandomAccessFile>* result) { + string translated_fname = TranslateName(fname); + result->reset(); + Status s; + FILE* f = fopen(translated_fname.c_str(), "r"); + if (f == NULL) { + s = IOError(fname, errno); + } else { + result->reset(new WindowsRandomAccessFile(translated_fname, f)); + } + return s; +} + +Status WindowsFileSystem::NewWritableFile( + const string& fname, std::unique_ptr<WritableFile>* result) { + string translated_fname = TranslateName(fname); + Status s; + FILE* f = fopen(translated_fname.c_str(), "w"); + if (f == NULL) { + result->reset(); + s = IOError(fname, errno); + } else { + result->reset(new WindowsWritableFile(translated_fname, f)); + } + return s; +} + +Status WindowsFileSystem::NewAppendableFile( + const string& fname, std::unique_ptr<WritableFile>* result) { + string translated_fname = TranslateName(fname); + Status s; + FILE* f = fopen(translated_fname.c_str(), "a"); + if (f == NULL) { + result->reset(); + s = IOError(fname, errno); + } else { + result->reset(new WindowsWritableFile(translated_fname, f)); + } + return s; +} + +Status WindowsFileSystem::NewReadOnlyMemoryRegionFromFile( + const string& fname, std::unique_ptr<ReadOnlyMemoryRegion>* result) { + return errors::Unimplemented( + "WindowsFileSystem::NewReadOnlyMemoryRegionFromFile"); +} + +bool WindowsFileSystem::FileExists(const string& fname) { + return _access(TranslateName(fname).c_str(), 0) == 0; +} + +Status WindowsFileSystem::GetChildren(const string& dir, + std::vector<string>* result) { + string translated_dir = TranslateName(dir); + result->clear(); + + WIN32_FIND_DATA find_data; + HANDLE find_handle = FindFirstFile(translated_dir.c_str(), &find_data); + if (find_handle == INVALID_HANDLE_VALUE) { + // TODO(mrry): Convert to a more specific error. + return errors::Unknown("Error code: ", GetLastError()); + } + result->push_back(find_data.cFileName); + while (FindNextFile(find_handle, &find_data)) { + result->push_back(find_data.cFileName); + } + if (!FindClose(find_handle)) { + // TODO(mrry): Convert to a more specific error. + return errors::Unknown("Error closing find handle: ", GetLastError()); + } + return Status::OK(); +} + +Status WindowsFileSystem::DeleteFile(const string& fname) { + Status result; + if (unlink(TranslateName(fname).c_str()) != 0) { + result = IOError(fname, errno); + } + return result; +} + +Status WindowsFileSystem::CreateDir(const string& name) { + Status result; + if (_mkdir(TranslateName(name).c_str()) != 0) { + result = IOError(name, errno); + } + return result; +} + +Status WindowsFileSystem::DeleteDir(const string& name) { + Status result; + if (_rmdir(TranslateName(name).c_str()) != 0) { + result = IOError(name, errno); + } + return result; +} + +Status WindowsFileSystem::GetFileSize(const string& fname, uint64* size) { + Status s; + struct _stat sbuf; + if (_stat(TranslateName(fname).c_str(), &sbuf) != 0) { + *size = 0; + s = IOError(fname, errno); + } else { + *size = sbuf.st_size; + } + return s; +} + +Status WindowsFileSystem::RenameFile(const string& src, const string& target) { + Status result; + if (rename(TranslateName(src).c_str(), TranslateName(target).c_str()) != 0) { + result = IOError(src, errno); + } + return result; +} + +Status WindowsFileSystem::Stat(const string& fname, FileStatistics* stat) { + Status s; + struct _stat sbuf; + if (_stat(TranslateName(fname).c_str(), &sbuf) != 0) { + s = IOError(fname, errno); + } else { + stat->mtime_nsec = sbuf.st_mtime * 1e9; + stat->length = sbuf.st_size; + stat->is_directory = PathIsDirectory(TranslateName(fname).c_str()); + } + return s; +} + +} // namespace tensorflow
\ No newline at end of file diff --git a/tensorflow/core/platform/windows/windows_file_system.h b/tensorflow/core/platform/windows/windows_file_system.h new file mode 100644 index 0000000000..68b391fb10 --- /dev/null +++ b/tensorflow/core/platform/windows/windows_file_system.h @@ -0,0 +1,71 @@ +/* Copyright 2015 Google Inc. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_CORE_PLATFORM_WINDOWS_WINDOWS_FILE_SYSTEM_H_ +#define TENSORFLOW_CORE_PLATFORM_WINDOWS_WINDOWS_FILE_SYSTEM_H_ + +#include "tensorflow/core/platform/file_system.h" + +#ifdef PLATFORM_WINDOWS +#undef DeleteFile +#endif + +namespace tensorflow { + +class WindowsFileSystem : public FileSystem { + public: + WindowsFileSystem() {} + + ~WindowsFileSystem() {} + + Status NewRandomAccessFile( + const string& fname, std::unique_ptr<RandomAccessFile>* result) override; + + Status NewWritableFile(const string& fname, + std::unique_ptr<WritableFile>* result) override; + + Status NewAppendableFile(const string& fname, + std::unique_ptr<WritableFile>* result) override; + + Status NewReadOnlyMemoryRegionFromFile( + const string& fname, + std::unique_ptr<ReadOnlyMemoryRegion>* result) override; + + bool FileExists(const string& fname) override; + + Status GetChildren(const string& dir, std::vector<string>* result) override; + + Status Stat(const string& fname, FileStatistics* stat) override; + + Status DeleteFile(const string& fname) override; + + Status CreateDir(const string& name) override; + + Status DeleteDir(const string& name) override; + + Status GetFileSize(const string& fname, uint64* size) override; + + Status RenameFile(const string& src, const string& target) override; + + string TranslateName(const string& name) const override { + return name; + } +}; + +Status IOError(const string& context, int err_number); + +} // namespace tensorflow + +#endif // TENSORFLOW_CORE_PLATFORM_WINDOWS_WINDOWS_FILE_SYSTEM_H_ |