-
Notifications
You must be signed in to change notification settings - Fork 2
/
edit-leveldb.cc
104 lines (91 loc) · 3.05 KB
/
edit-leveldb.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
// Copyright (c) 2017 Nuxi, https://nuxi.nl/
//
// SPDX-License-Identifier: BSD-2-Clause
#include <program.h>
#include <argdata.hpp>
#include <cstdlib>
#include <memory>
#include <optional>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <leveldb/db.h>
#include <leveldb/env.h>
// Inserts key-value pairs into a LevelDB by reading them from a
// terminal. After detecting an end-of-file, it prints all of the
// key-value pairs in the LevelDB to the terminal.
//
// Usage:
//
// $ x86_64-unknown-cloudabi-c++ -std=c++1z -O2 \
// -o edit-leveldb edit-leveldb.cc \
// -lleveldb -lsnappy -lboost_iostreams
// $ cat edit-leveldb.yaml
// %TAG ! tag:nuxi.nl,2015:cloudabi/
// ---
// database: !file
// path: db
// terminal: !fd stdout
// $ mkdir db
// $ cloudabi-run edit-leveldb < edit-leveldb.yaml
static bool edit_leveldb(int fd_database, int fd_terminal) {
// Use Boost iostreams to access the terminal. Standard C++ iostreams
// cannot be constructed from file POSIX file descriptors.
boost::iostreams::stream<boost::iostreams::file_descriptor> terminal(
fd_terminal, boost::iostreams::never_close_handle);
// Open the LevelDB, using an environment with a custom base directory
// file descriptor.
std::unique_ptr<leveldb::Env> env(
leveldb::Env::DefaultWithDirectory(fd_database));
std::unique_ptr<leveldb::DB> database;
{
leveldb::Options options;
options.create_if_missing = true;
options.env = env.get();
leveldb::DB *database_ptr;
leveldb::Status status = leveldb::DB::Open(options, ".", &database_ptr);
if (!status.ok()) {
terminal << "Got error: " << status.ToString() << std::endl;
return false;
}
database.reset(database_ptr);
}
// Read key-value pairs from the terminal and insert them into the LevelDB.
for (;;) {
terminal << " Key: ";
std::string key;
std::getline(terminal, key);
if (!terminal.good())
break;
terminal << "Value: ";
std::string value;
std::getline(terminal, value);
if (!terminal.good())
break;
database->Put(leveldb::WriteOptions(), key, value);
}
terminal.clear();
terminal << std::endl;
// Print all of the key-value pairs to the terminal.
std::unique_ptr<leveldb::Iterator> it(
database->NewIterator(leveldb::ReadOptions()));
for (it->SeekToFirst(); it->Valid(); it->Next()) {
terminal << '|' << it->key().ToString() << "| -> |"
<< it->value().ToString() << '|' << std::endl;
}
return true;
}
void program_main(const argdata_t *ad) {
// Extract file descriptors from fields provided by cloudabi-run.
std::optional<int> fd_database, fd_terminal;
for (auto i : ad->as_map()) {
auto key = i.first->as_str();
if (key == "database")
fd_database = i.second->get_fd();
if (key == "terminal")
fd_terminal = i.second->get_fd();
}
std::exit(fd_database && fd_terminal &&
edit_leveldb(*fd_database, *fd_terminal)
? 0
: 1);
}