Reputation: 3
I'm trying to put()
binary data of large scale files into the leveldb using c++ library.
While put()
operation working on the leveldb warning abort() has been called
is generated if I execute my code.
FILE* file;
WriteOptions woptions;
woptions.sync = true'
DB* db;
Options options;
options.create_if_missing = true;
DBPATH.assign(DBName);
char key = '1';
Status s = DB::Open(options,DBPATH,&db);
assert(status.ok());
fopen_s(&file, "target.jpg", "rb");
fseek(file, 0, SEEK_END);
long long int size = ftell(file);
rewind(file);
char* buffer = (char*)calloc(1, size);
if(buffer == NULL) printf("mem error\n");
fread(buffer, size, 1, file);
Slice slice(buffer, size + 1);
Slice key_in(key, sizeof(char)+1);
status = db->Put(woptions, key, slice);
assert(status.ok());
free(buffer);
slice.clear();
key.clear();
fclose(file);
delete db;
I've tried to print the status to figure out what's the problem. But before printing status, the abort() message pops out. So I think there must be some problem in PUT(). Do I need to change config or any other envs? Or is there the size limitation of handling data exist on leveldb...? I tried berkeleydb and rocksdb in the same way,but no warning message popped. I looked up the doc of each DBs. And I can't find how to handle BLOBs at leveldb doc unlike other DBs. Now I wonder if the leveldb supports the BLOBs.....!
Upvotes: 0
Views: 137
Reputation: 118097
After looking at the LevelDB API I think this is what's wrong:
char key = '1';
// ...
Slice slice(buffer, size + 1); // + 1 is wrong
slice key_in(key, sizeof(char)+1); // `key_in` is invalid and +1 is wrong
status = db->Put(woptions, key, slice); // and `key_in` is unused
The Key you use is not a Slice
, it's a char
.
If you only want a single char
for the Key:
char key = '1';
// ...
Slice slice(buffer, size); // correct size
Slice key_in(&key, sizeof key); // take the address and size of the key
status = db->Put(woptions, key_in, slice); // and use `key_in`
Alternatively, create your Key Slice
from a char*
:
char key[] = "1";
// ...
Slice slice(buffer, size); // correct size
Slice key_in(key); // `key_in` created from C string
status = db->Put(woptions, key_in, slice); // and use `key_in`
I also suggest simplifying the code. Don't use calloc
. Use a std::vector<char>
instead.
#include <cerrno>
#include <cstring>
#include <fstream>
#include <iostream>
#include <iterator>
#include <vector>
// Read the whole file into a vector<char>
std::vector<char> get_file_content(const std::string& filename) {
std::ifstream is(filename, std::ios::binary);
if(!is) throw std::runtime_error(filename + ": " + std::strerror(errno));
return {std::istreambuf_iterator<char>(is),
std::istreambuf_iterator<char>{}};
}
int main() {
// Your current code up until you open the database.
// ..
Status s = DB::Open(options,DBPATH,&db);
assert(status.ok());
char key = '1';
auto buffer = get_file_content("target.jpg");
Slice key_in(&key, sizeof key);
Slice slice(buffer.data(), buffer.size());
status = db->Put(woptions, key_in, slice);
std::cout << status.ToString() << '\n';
delete db; // the only cleanup needed
std::cout << "Done\n";
}
Upvotes: 0