mirror of
https://github.com/zebrajr/tensorflow.git
synced 2025-12-07 12:20:24 +01:00
New reader for LMDB databases (#9950)
* Add LMDBReader op and test case * Add testcase to load LMDB from a folder * Add tensorflow/core/lib/lmdb/testdata/data.mdb * Add EOF test * Add license export * Blacklist the test data in pip_smoke_test.py * Address issues with respect to review * Add LICENSE to BUILD rules * Remove the prefx of LICENSE * Wrap key with compat.as_bytes() * Fixed a compilation flag * Improve BUILD rules * Support LMDB build in cmake * Fix BUILD file format with buildifier * Add fake unistd.h for lmdb to build on Windows * Avoid building lmdb tools which depends on unistd.h * Fix the string encoding issue in Python3 * Update lmdb library name in CMakeList.txt
This commit is contained in:
parent
8a46d7a299
commit
e6f5818636
|
|
@ -113,6 +113,7 @@ include(zlib)
|
||||||
include(gif)
|
include(gif)
|
||||||
include(png)
|
include(png)
|
||||||
include(jpeg)
|
include(jpeg)
|
||||||
|
include(lmdb)
|
||||||
include(eigen)
|
include(eigen)
|
||||||
include(gemmlowp)
|
include(gemmlowp)
|
||||||
include(jsoncpp)
|
include(jsoncpp)
|
||||||
|
|
@ -129,6 +130,7 @@ set(tensorflow_EXTERNAL_LIBRARIES
|
||||||
${gif_STATIC_LIBRARIES}
|
${gif_STATIC_LIBRARIES}
|
||||||
${png_STATIC_LIBRARIES}
|
${png_STATIC_LIBRARIES}
|
||||||
${jpeg_STATIC_LIBRARIES}
|
${jpeg_STATIC_LIBRARIES}
|
||||||
|
${lmdb_STATIC_LIBRARIES}
|
||||||
${jsoncpp_STATIC_LIBRARIES}
|
${jsoncpp_STATIC_LIBRARIES}
|
||||||
${farmhash_STATIC_LIBRARIES}
|
${farmhash_STATIC_LIBRARIES}
|
||||||
${fft2d_STATIC_LIBRARIES}
|
${fft2d_STATIC_LIBRARIES}
|
||||||
|
|
@ -140,6 +142,7 @@ set(tensorflow_EXTERNAL_DEPENDENCIES
|
||||||
gif_copy_headers_to_destination
|
gif_copy_headers_to_destination
|
||||||
png_copy_headers_to_destination
|
png_copy_headers_to_destination
|
||||||
jpeg_copy_headers_to_destination
|
jpeg_copy_headers_to_destination
|
||||||
|
lmdb_copy_headers_to_destination
|
||||||
jsoncpp
|
jsoncpp
|
||||||
farmhash_copy_headers_to_destination
|
farmhash_copy_headers_to_destination
|
||||||
highwayhash_copy_headers_to_destination
|
highwayhash_copy_headers_to_destination
|
||||||
|
|
@ -158,6 +161,7 @@ include_directories(
|
||||||
${gif_INCLUDE_DIR}
|
${gif_INCLUDE_DIR}
|
||||||
${png_INCLUDE_DIR}
|
${png_INCLUDE_DIR}
|
||||||
${jpeg_INCLUDE_DIR}
|
${jpeg_INCLUDE_DIR}
|
||||||
|
${lmdb_INCLUDE_DIR}
|
||||||
${eigen_INCLUDE_DIRS}
|
${eigen_INCLUDE_DIRS}
|
||||||
${gemmlowp_INCLUDE_DIR}
|
${gemmlowp_INCLUDE_DIR}
|
||||||
${jsoncpp_INCLUDE_DIR}
|
${jsoncpp_INCLUDE_DIR}
|
||||||
|
|
|
||||||
60
tensorflow/contrib/cmake/external/lmdb.cmake
vendored
Normal file
60
tensorflow/contrib/cmake/external/lmdb.cmake
vendored
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
# Copyright 2017 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 (ExternalProject)
|
||||||
|
|
||||||
|
set(lmdb_INCLUDE_DIR ${CMAKE_CURRENT_BINARY_DIR}/external/lmdb)
|
||||||
|
set(lmdb_URL http://mirror.bazel.build/github.com/LMDB/lmdb/archive/LMDB_0.9.19.tar.gz)
|
||||||
|
set(lmdb_HASH SHA256=108532fb94c6f227558d45be3f3347b52539f0f58290a7bb31ec06c462d05326)
|
||||||
|
set(lmdb_BUILD ${CMAKE_BINARY_DIR}/lmdb/src/lmdb)
|
||||||
|
set(lmdb_INSTALL ${CMAKE_BINARY_DIR}/lmdb/install)
|
||||||
|
|
||||||
|
ExternalProject_Add(lmdb
|
||||||
|
PREFIX lmdb
|
||||||
|
URL ${lmdb_URL}
|
||||||
|
URL_HASH ${lmdb_HASH}
|
||||||
|
PATCH_COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/patches/lmdb/CMakeLists.txt ${lmdb_BUILD}
|
||||||
|
INSTALL_DIR ${lmdb_INSTALL}
|
||||||
|
DOWNLOAD_DIR "${DOWNLOAD_LOCATION}"
|
||||||
|
CMAKE_CACHE_ARGS
|
||||||
|
-DCMAKE_BUILD_TYPE:STRING=Release
|
||||||
|
-DCMAKE_VERBOSE_MAKEFILE:BOOL=OFF
|
||||||
|
-DCMAKE_INSTALL_PREFIX:STRING=${lmdb_INSTALL}
|
||||||
|
-DCMAKE_POSITION_INDEPENDENT_CODE:BOOL=ON
|
||||||
|
)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
set(lmdb_STATIC_LIBRARIES ${lmdb_INSTALL}/lib/lmdb.lib)
|
||||||
|
else()
|
||||||
|
set(lmdb_STATIC_LIBRARIES ${lmdb_INSTALL}/lib/liblmdb.a)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(lmdb_HEADERS
|
||||||
|
"${lmdb_INSTALL}/include/lmdb.h"
|
||||||
|
"${lmdb_INSTALL}/include/midl.h"
|
||||||
|
)
|
||||||
|
|
||||||
|
## put lmdb includes in the directory where they are expected
|
||||||
|
add_custom_target(lmdb_create_destination_dir
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E make_directory ${lmdb_INCLUDE_DIR}
|
||||||
|
DEPENDS lmdb)
|
||||||
|
|
||||||
|
add_custom_target(lmdb_copy_headers_to_destination
|
||||||
|
DEPENDS lmdb_create_destination_dir)
|
||||||
|
|
||||||
|
foreach(header_file ${lmdb_HEADERS})
|
||||||
|
add_custom_command(TARGET lmdb_copy_headers_to_destination PRE_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${header_file} ${lmdb_INCLUDE_DIR}/)
|
||||||
|
endforeach()
|
||||||
26
tensorflow/contrib/cmake/patches/lmdb/CMakeLists.txt
Normal file
26
tensorflow/contrib/cmake/patches/lmdb/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
cmake_minimum_required(VERSION 2.8.3)
|
||||||
|
|
||||||
|
project(liblmdb)
|
||||||
|
|
||||||
|
set(LIBLMDB_SRCS
|
||||||
|
"libraries/liblmdb/mdb.c"
|
||||||
|
"libraries/liblmdb/midl.c"
|
||||||
|
)
|
||||||
|
|
||||||
|
set(LIBLMDB_INCLUDES
|
||||||
|
"libraries/liblmdb/lmdb.h"
|
||||||
|
"libraries/liblmdb/midl.h"
|
||||||
|
)
|
||||||
|
|
||||||
|
include_directories("${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
|
||||||
|
add_library(lmdb ${LIBLMDB_SRCS})
|
||||||
|
|
||||||
|
install(TARGETS lmdb
|
||||||
|
RUNTIME DESTINATION bin COMPONENT RuntimeLibraries
|
||||||
|
LIBRARY DESTINATION lib COMPONENT RuntimeLibraries
|
||||||
|
ARCHIVE DESTINATION lib COMPONENT Development)
|
||||||
|
|
||||||
|
foreach(LIBLMDB_INCLUDE ${LIBLMDB_INCLUDES})
|
||||||
|
install(FILES ${LIBLMDB_INCLUDE} DESTINATION include COMPONENT Development)
|
||||||
|
endforeach()
|
||||||
|
|
@ -2886,6 +2886,20 @@ filegroup(
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
filegroup(
|
||||||
|
name = "lmdb_testdata",
|
||||||
|
testonly = 1,
|
||||||
|
srcs = [
|
||||||
|
# A simple key-value store:
|
||||||
|
# 0 : 'a'
|
||||||
|
# 1 : 'b'
|
||||||
|
# ...
|
||||||
|
# 9 : 'j'
|
||||||
|
"lib/lmdb/testdata/data.mdb",
|
||||||
|
],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
||||||
|
|
||||||
filegroup(
|
filegroup(
|
||||||
name = "example_parser_configuration_testdata",
|
name = "example_parser_configuration_testdata",
|
||||||
srcs = [
|
srcs = [
|
||||||
|
|
|
||||||
|
|
@ -481,7 +481,7 @@ Status GraphConstructor::ValidateShape(Node* node) {
|
||||||
"MutableHashTableOfTensors", "Mutex", "CuckooTable", "IndexTable",
|
"MutableHashTableOfTensors", "Mutex", "CuckooTable", "IndexTable",
|
||||||
"WholeFileReader", "TextLineReader", "FixedLengthRecordReader",
|
"WholeFileReader", "TextLineReader", "FixedLengthRecordReader",
|
||||||
"TFRecordReader", "IdentityReader", "RefSwitch", "RefEnter",
|
"TFRecordReader", "IdentityReader", "RefSwitch", "RefEnter",
|
||||||
"RefNextIteration", "RefMerge", "RefIdentity",
|
"RefNextIteration", "RefMerge", "RefIdentity", "LMDBReader",
|
||||||
// To be removed after 2017/04/24.
|
// To be removed after 2017/04/24.
|
||||||
"ConditionalAccumulator", "SparseConditionalAccumulator", "Table",
|
"ConditionalAccumulator", "SparseConditionalAccumulator", "Table",
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1904,6 +1904,7 @@ cc_library(
|
||||||
deps = [
|
deps = [
|
||||||
":fixed_length_record_reader_op",
|
":fixed_length_record_reader_op",
|
||||||
":identity_reader_op",
|
":identity_reader_op",
|
||||||
|
":lmdb_reader_op",
|
||||||
":matching_files_op",
|
":matching_files_op",
|
||||||
":reader_ops",
|
":reader_ops",
|
||||||
":restore_op",
|
":restore_op",
|
||||||
|
|
@ -1938,6 +1939,14 @@ tf_kernel_library(
|
||||||
deps = IO_DEPS,
|
deps = IO_DEPS,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
tf_kernel_library(
|
||||||
|
name = "lmdb_reader_op",
|
||||||
|
prefix = "lmdb_reader_op",
|
||||||
|
deps = IO_DEPS + [
|
||||||
|
"@lmdb",
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
tf_kernel_library(
|
tf_kernel_library(
|
||||||
name = "matching_files_op",
|
name = "matching_files_op",
|
||||||
prefix = "matching_files_op",
|
prefix = "matching_files_op",
|
||||||
|
|
@ -4313,6 +4322,7 @@ filegroup(
|
||||||
# not used on Android. Those ops also do not compile if included,
|
# not used on Android. Those ops also do not compile if included,
|
||||||
# unless we add the additional deps they need.
|
# unless we add the additional deps they need.
|
||||||
"tf_record_reader_op.*",
|
"tf_record_reader_op.*",
|
||||||
|
"lmdb_reader_op.*",
|
||||||
"string_to_hash_bucket_op.*",
|
"string_to_hash_bucket_op.*",
|
||||||
"sdca_ops.*",
|
"sdca_ops.*",
|
||||||
"sdca_internal.*",
|
"sdca_internal.*",
|
||||||
|
|
|
||||||
134
tensorflow/core/kernels/lmdb_reader_op.cc
Executable file
134
tensorflow/core/kernels/lmdb_reader_op.cc
Executable file
|
|
@ -0,0 +1,134 @@
|
||||||
|
/* 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 "lmdb.h"
|
||||||
|
#include "tensorflow/core/framework/reader_op_kernel.h"
|
||||||
|
#include "tensorflow/core/framework/reader_base.h"
|
||||||
|
#include "tensorflow/core/lib/core/errors.h"
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
namespace tensorflow {
|
||||||
|
|
||||||
|
inline void MDB_CHECK(int mdb_status) {
|
||||||
|
CHECK_EQ(mdb_status, MDB_SUCCESS) << mdb_strerror(mdb_status);
|
||||||
|
}
|
||||||
|
|
||||||
|
class LMDBReader : public ReaderBase {
|
||||||
|
public:
|
||||||
|
LMDBReader(const string& node_name, Env* env)
|
||||||
|
: ReaderBase(strings::StrCat("LMDBReader '", node_name, "'")),
|
||||||
|
env_(env),
|
||||||
|
mdb_env_(nullptr),
|
||||||
|
mdb_dbi_(0),
|
||||||
|
mdb_txn_(nullptr),
|
||||||
|
mdb_cursor_(nullptr) {}
|
||||||
|
|
||||||
|
Status OnWorkStartedLocked() override {
|
||||||
|
MDB_CHECK(mdb_env_create(&mdb_env_));
|
||||||
|
int flags = MDB_RDONLY | MDB_NOTLS;
|
||||||
|
|
||||||
|
// Check if the LMDB filename is actually a file instead of a directory.
|
||||||
|
// If so, set appropriate flags so we can open it.
|
||||||
|
struct stat source_stat;
|
||||||
|
if (stat(current_work().c_str(), &source_stat) == 0 &&
|
||||||
|
(source_stat.st_mode & S_IFREG)) {
|
||||||
|
flags |= MDB_NOSUBDIR;
|
||||||
|
}
|
||||||
|
|
||||||
|
MDB_CHECK(mdb_env_open(mdb_env_, current_work().c_str(), flags, 0664));
|
||||||
|
MDB_CHECK(mdb_txn_begin(mdb_env_, nullptr, MDB_RDONLY, &mdb_txn_));
|
||||||
|
MDB_CHECK(mdb_dbi_open(mdb_txn_, nullptr, 0, &mdb_dbi_));
|
||||||
|
|
||||||
|
return Status::OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
Status OnWorkFinishedLocked() override {
|
||||||
|
if (mdb_env_ != nullptr) {
|
||||||
|
if (mdb_cursor_) {
|
||||||
|
mdb_cursor_close(mdb_cursor_);
|
||||||
|
}
|
||||||
|
mdb_txn_abort(mdb_txn_);
|
||||||
|
mdb_dbi_close(mdb_env_, mdb_dbi_);
|
||||||
|
mdb_env_close(mdb_env_);
|
||||||
|
mdb_env_ = nullptr;
|
||||||
|
}
|
||||||
|
return Status::OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
Status ReadLocked(string* key, string* value, bool* produced,
|
||||||
|
bool* at_end) override {
|
||||||
|
if (mdb_cursor_ == nullptr) {
|
||||||
|
MDB_CHECK(mdb_cursor_open(mdb_txn_, mdb_dbi_, &mdb_cursor_));
|
||||||
|
if (Seek(MDB_FIRST) == false) {
|
||||||
|
*at_end = true;
|
||||||
|
return Status::OK();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (Seek(MDB_NEXT) == false) {
|
||||||
|
*at_end = true;
|
||||||
|
return Status::OK();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*key = string(static_cast<const char*>(mdb_key_.mv_data),
|
||||||
|
mdb_key_.mv_size);
|
||||||
|
*value = string(static_cast<const char*>(mdb_value_.mv_data),
|
||||||
|
mdb_value_.mv_size);
|
||||||
|
*produced = true;
|
||||||
|
return Status::OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
Status ResetLocked() override {
|
||||||
|
CHECK_EQ(Seek(MDB_FIRST), true);
|
||||||
|
return ReaderBase::ResetLocked();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool Seek(MDB_cursor_op op) {
|
||||||
|
CHECK_NOTNULL(mdb_cursor_);
|
||||||
|
int mdb_status = mdb_cursor_get(mdb_cursor_, &mdb_key_, &mdb_value_, op);
|
||||||
|
if (mdb_status == MDB_NOTFOUND) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
MDB_CHECK(mdb_status);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Env* const env_;
|
||||||
|
MDB_env* mdb_env_;
|
||||||
|
MDB_dbi mdb_dbi_;
|
||||||
|
|
||||||
|
MDB_txn* mdb_txn_;
|
||||||
|
MDB_cursor* mdb_cursor_;
|
||||||
|
MDB_val mdb_key_, mdb_value_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class LMDBReaderOp : public ReaderOpKernel {
|
||||||
|
public:
|
||||||
|
explicit LMDBReaderOp(OpKernelConstruction* context)
|
||||||
|
: ReaderOpKernel(context) {
|
||||||
|
Env* env = context->env();
|
||||||
|
SetReaderFactory([this, env]() {
|
||||||
|
return new LMDBReader(name(), env);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
REGISTER_KERNEL_BUILDER(Name("LMDBReader").Device(DEVICE_CPU),
|
||||||
|
LMDBReaderOp);
|
||||||
|
|
||||||
|
}
|
||||||
BIN
tensorflow/core/lib/lmdb/testdata/data.mdb
vendored
Normal file
BIN
tensorflow/core/lib/lmdb/testdata/data.mdb
vendored
Normal file
Binary file not shown.
|
|
@ -520,6 +520,21 @@ shared_name: If non-empty, this reader is named in the given bucket
|
||||||
with this shared_name. Otherwise, the node name is used instead.
|
with this shared_name. Otherwise, the node name is used instead.
|
||||||
)doc");
|
)doc");
|
||||||
|
|
||||||
|
REGISTER_OP("LMDBReader")
|
||||||
|
.Output("reader_handle: Ref(string)")
|
||||||
|
.Attr("container: string = ''")
|
||||||
|
.Attr("shared_name: string = ''")
|
||||||
|
.SetIsStateful()
|
||||||
|
.SetShapeFn(TwoElementOutput)
|
||||||
|
.Doc(R"doc(
|
||||||
|
A Reader that outputs the records from a LMDB file.
|
||||||
|
reader_handle: The handle to reference the Reader.
|
||||||
|
container: If non-empty, this reader is placed in the given container.
|
||||||
|
Otherwise, a default container is used.
|
||||||
|
shared_name: If non-empty, this reader is named in the given bucket
|
||||||
|
with this shared_name. Otherwise, the node name is used instead.
|
||||||
|
)doc");
|
||||||
|
|
||||||
// TODO(cwhipkey): mark this deprecated in favor of V2.
|
// TODO(cwhipkey): mark this deprecated in favor of V2.
|
||||||
REGISTER_OP("IdentityReader")
|
REGISTER_OP("IdentityReader")
|
||||||
.Output("reader_handle: Ref(string)")
|
.Output("reader_handle: Ref(string)")
|
||||||
|
|
|
||||||
|
|
@ -26049,6 +26049,33 @@ op {
|
||||||
summary: "A Reader that outputs the records from a TensorFlow Records file."
|
summary: "A Reader that outputs the records from a TensorFlow Records file."
|
||||||
is_stateful: true
|
is_stateful: true
|
||||||
}
|
}
|
||||||
|
op {
|
||||||
|
name: "LMDBReader"
|
||||||
|
output_arg {
|
||||||
|
name: "reader_handle"
|
||||||
|
description: "The handle to reference the Reader."
|
||||||
|
type: DT_STRING
|
||||||
|
is_ref: true
|
||||||
|
}
|
||||||
|
attr {
|
||||||
|
name: "container"
|
||||||
|
type: "string"
|
||||||
|
default_value {
|
||||||
|
s: ""
|
||||||
|
}
|
||||||
|
description: "If non-empty, this reader is placed in the given container.\nOtherwise, a default container is used."
|
||||||
|
}
|
||||||
|
attr {
|
||||||
|
name: "shared_name"
|
||||||
|
type: "string"
|
||||||
|
default_value {
|
||||||
|
s: ""
|
||||||
|
}
|
||||||
|
description: "If non-empty, this reader is named in the given bucket\nwith this shared_name. Otherwise, the node name is used instead."
|
||||||
|
}
|
||||||
|
summary: "A Reader that outputs the records from a LMDB database."
|
||||||
|
is_stateful: true
|
||||||
|
}
|
||||||
op {
|
op {
|
||||||
name: "TakeDataset"
|
name: "TakeDataset"
|
||||||
input_arg {
|
input_arg {
|
||||||
|
|
|
||||||
|
|
@ -437,6 +437,7 @@ def import_graph_def(graph_def, input_map=None, return_elements=None,
|
||||||
'WholeFileReader', 'TextLineReader',
|
'WholeFileReader', 'TextLineReader',
|
||||||
'FixedLengthRecordReader',
|
'FixedLengthRecordReader',
|
||||||
'TFRecordReader', 'IdentityReader',
|
'TFRecordReader', 'IdentityReader',
|
||||||
|
'LMDBReader',
|
||||||
'RefSwitch', 'RefEnter', 'RefNextIteration',
|
'RefSwitch', 'RefEnter', 'RefNextIteration',
|
||||||
'RefMerge', 'RefIdentity']:
|
'RefMerge', 'RefIdentity']:
|
||||||
pass
|
pass
|
||||||
|
|
|
||||||
|
|
@ -979,6 +979,7 @@ tf_py_test(
|
||||||
"//tensorflow/python:util",
|
"//tensorflow/python:util",
|
||||||
"//tensorflow/python:variables",
|
"//tensorflow/python:variables",
|
||||||
],
|
],
|
||||||
|
data = ["//tensorflow/core:lmdb_testdata"],
|
||||||
)
|
)
|
||||||
|
|
||||||
cuda_py_test(
|
cuda_py_test(
|
||||||
|
|
|
||||||
|
|
@ -858,5 +858,48 @@ class AsyncReaderTest(test.TestCase):
|
||||||
output.append(sess.run(args))
|
output.append(sess.run(args))
|
||||||
|
|
||||||
|
|
||||||
|
class LMDBReaderTest(test.TestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(LMDBReaderTest, self).setUp()
|
||||||
|
|
||||||
|
def testReadFromFile(self):
|
||||||
|
with self.test_session() as sess:
|
||||||
|
reader = io_ops.LMDBReader(name="test_read_from_file")
|
||||||
|
path = os.path.join("tensorflow", "core", "lib", "lmdb", "testdata",
|
||||||
|
"data.mdb")
|
||||||
|
queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=())
|
||||||
|
key, value = reader.read(queue)
|
||||||
|
|
||||||
|
queue.enqueue([path]).run()
|
||||||
|
queue.close().run()
|
||||||
|
for i in range(10):
|
||||||
|
k, v = sess.run([key, value])
|
||||||
|
self.assertAllEqual(compat.as_bytes(k), compat.as_bytes(str(i)))
|
||||||
|
self.assertAllEqual(compat.as_bytes(v), compat.as_bytes(str(chr(ord('a') + i))))
|
||||||
|
|
||||||
|
with self.assertRaisesOpError("is closed and has insufficient elements "
|
||||||
|
"\\(requested 1, current size 0\\)"):
|
||||||
|
k, v = sess.run([key, value])
|
||||||
|
|
||||||
|
def testReadFromFolder(self):
|
||||||
|
with self.test_session() as sess:
|
||||||
|
reader = io_ops.LMDBReader(name="test_read_from_folder")
|
||||||
|
path = os.path.join("tensorflow", "core", "lib", "lmdb", "testdata")
|
||||||
|
queue = data_flow_ops.FIFOQueue(99, [dtypes.string], shapes=())
|
||||||
|
key, value = reader.read(queue)
|
||||||
|
|
||||||
|
queue.enqueue([path]).run()
|
||||||
|
queue.close().run()
|
||||||
|
for i in range(10):
|
||||||
|
k, v = sess.run([key, value])
|
||||||
|
self.assertAllEqual(compat.as_bytes(k), compat.as_bytes(str(i)))
|
||||||
|
self.assertAllEqual(compat.as_bytes(v), compat.as_bytes(str(chr(ord('a') + i))))
|
||||||
|
|
||||||
|
with self.assertRaisesOpError("is closed and has insufficient elements "
|
||||||
|
"\\(requested 1, current size 0\\)"):
|
||||||
|
k, v = sess.run([key, value])
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
test.main()
|
test.main()
|
||||||
|
|
|
||||||
|
|
@ -191,6 +191,7 @@ WholeFileReader
|
||||||
TextLineReaderV2
|
TextLineReaderV2
|
||||||
TFRecordReaderV2
|
TFRecordReaderV2
|
||||||
WholeFileReaderV2
|
WholeFileReaderV2
|
||||||
|
LMDBReader
|
||||||
|
|
||||||
# linalg_ops
|
# linalg_ops
|
||||||
BatchCholesky
|
BatchCholesky
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ See the @{$python/io_ops} guide.
|
||||||
@@WholeFileReader
|
@@WholeFileReader
|
||||||
@@IdentityReader
|
@@IdentityReader
|
||||||
@@TFRecordReader
|
@@TFRecordReader
|
||||||
|
@@LMDBReader
|
||||||
@@FixedLengthRecordReader
|
@@FixedLengthRecordReader
|
||||||
@@decode_csv
|
@@decode_csv
|
||||||
@@decode_raw
|
@@decode_raw
|
||||||
|
|
@ -443,6 +444,25 @@ class TFRecordReader(ReaderBase):
|
||||||
ops.NotDifferentiable("TFRecordReader")
|
ops.NotDifferentiable("TFRecordReader")
|
||||||
|
|
||||||
|
|
||||||
|
class LMDBReader(ReaderBase):
|
||||||
|
"""A Reader that outputs the records from a LMDB file.
|
||||||
|
|
||||||
|
See ReaderBase for supported methods.
|
||||||
|
"""
|
||||||
|
def __init__(self, name=None, options=None):
|
||||||
|
"""Create a LMDBReader.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
name: A name for the operation (optional).
|
||||||
|
options: A LMDBRecordOptions object (optional).
|
||||||
|
"""
|
||||||
|
rr = gen_io_ops._lmdb_reader(name=name)
|
||||||
|
super(LMDBReader, self).__init__(rr)
|
||||||
|
|
||||||
|
|
||||||
|
ops.NotDifferentiable("LMDBReader")
|
||||||
|
|
||||||
|
|
||||||
class IdentityReader(ReaderBase):
|
class IdentityReader(ReaderBase):
|
||||||
"""A Reader that outputs the queued work as both the key and value.
|
"""A Reader that outputs the queued work as both the key and value.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,7 @@ genrule(
|
||||||
"@jemalloc//:COPYING",
|
"@jemalloc//:COPYING",
|
||||||
"@jpeg//:LICENSE.md",
|
"@jpeg//:LICENSE.md",
|
||||||
"@libxsmm_archive//:LICENSE",
|
"@libxsmm_archive//:LICENSE",
|
||||||
|
"@lmdb//:LICENSE",
|
||||||
"@local_config_sycl//sycl:LICENSE.text",
|
"@local_config_sycl//sycl:LICENSE.text",
|
||||||
"@png_archive//:LICENSE",
|
"@png_archive//:LICENSE",
|
||||||
"@protobuf//:LICENSE",
|
"@protobuf//:LICENSE",
|
||||||
|
|
@ -126,6 +127,7 @@ genrule(
|
||||||
"@jemalloc//:COPYING",
|
"@jemalloc//:COPYING",
|
||||||
"@jpeg//:LICENSE.md",
|
"@jpeg//:LICENSE.md",
|
||||||
"@libxsmm_archive//:LICENSE",
|
"@libxsmm_archive//:LICENSE",
|
||||||
|
"@lmdb//:LICENSE",
|
||||||
"@local_config_sycl//sycl:LICENSE.text",
|
"@local_config_sycl//sycl:LICENSE.text",
|
||||||
"@png_archive//:LICENSE",
|
"@png_archive//:LICENSE",
|
||||||
"@protobuf//:LICENSE",
|
"@protobuf//:LICENSE",
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,7 @@ filegroup(
|
||||||
"@jemalloc//:COPYING",
|
"@jemalloc//:COPYING",
|
||||||
"@jpeg//:LICENSE.md",
|
"@jpeg//:LICENSE.md",
|
||||||
"@libxsmm_archive//:LICENSE",
|
"@libxsmm_archive//:LICENSE",
|
||||||
|
"@lmdb//:LICENSE",
|
||||||
"@local_config_sycl//sycl:LICENSE.text",
|
"@local_config_sycl//sycl:LICENSE.text",
|
||||||
"@nanopb_git//:LICENSE.txt",
|
"@nanopb_git//:LICENSE.txt",
|
||||||
"@org_html5lib//:LICENSE",
|
"@org_html5lib//:LICENSE",
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ BLACKLIST = [
|
||||||
"//tensorflow/python:tf_optimizer",
|
"//tensorflow/python:tf_optimizer",
|
||||||
"//tensorflow/python:compare_test_proto_py",
|
"//tensorflow/python:compare_test_proto_py",
|
||||||
"//tensorflow/core:image_testdata",
|
"//tensorflow/core:image_testdata",
|
||||||
|
"//tensorflow/core:lmdb_testdata",
|
||||||
"//tensorflow/core/kernels/cloud:bigquery_reader_ops",
|
"//tensorflow/core/kernels/cloud:bigquery_reader_ops",
|
||||||
"//tensorflow/python/feature_column:vocabulary_testdata",
|
"//tensorflow/python/feature_column:vocabulary_testdata",
|
||||||
"//tensorflow/python:framework/test_file_system.so",
|
"//tensorflow/python:framework/test_file_system.so",
|
||||||
|
|
|
||||||
|
|
@ -507,6 +507,17 @@ def tf_workspace(path_prefix="", tf_repo_name=""):
|
||||||
repository = tf_repo_name,
|
repository = tf_repo_name,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
native.new_http_archive(
|
||||||
|
name = "lmdb",
|
||||||
|
urls = [
|
||||||
|
"http://mirror.bazel.build/github.com/LMDB/lmdb/archive/LMDB_0.9.19.tar.gz",
|
||||||
|
"https://github.com/LMDB/lmdb/archive/LMDB_0.9.19.tar.gz",
|
||||||
|
],
|
||||||
|
sha256 = "108532fb94c6f227558d45be3f3347b52539f0f58290a7bb31ec06c462d05326",
|
||||||
|
strip_prefix = "lmdb-LMDB_0.9.19/libraries/liblmdb",
|
||||||
|
build_file = str(Label("//third_party:lmdb.BUILD")),
|
||||||
|
)
|
||||||
|
|
||||||
native.new_http_archive(
|
native.new_http_archive(
|
||||||
name = "jsoncpp_git",
|
name = "jsoncpp_git",
|
||||||
urls = [
|
urls = [
|
||||||
|
|
|
||||||
25
third_party/lmdb.BUILD
vendored
Normal file
25
third_party/lmdb.BUILD
vendored
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
# Description:
|
||||||
|
# LMDB is the Lightning Memory-mapped Database.
|
||||||
|
|
||||||
|
licenses(["notice"]) # OpenLDAP Public License
|
||||||
|
|
||||||
|
exports_files(["LICENSE"])
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "lmdb",
|
||||||
|
srcs = [
|
||||||
|
"mdb.c",
|
||||||
|
"midl.c",
|
||||||
|
],
|
||||||
|
hdrs = [
|
||||||
|
"lmdb.h",
|
||||||
|
"midl.h",
|
||||||
|
],
|
||||||
|
copts = [
|
||||||
|
"-w",
|
||||||
|
],
|
||||||
|
linkopts = [
|
||||||
|
"-lpthread",
|
||||||
|
],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
)
|
||||||
Loading…
Reference in New Issue
Block a user