10 #include <boost/shared_ptr.hpp>
12 #include <eblob/blob.h>
15 static void copy_data(std::ifstream
&src
, std::ofstream
&dst
, size_t size
)
17 size_t sz
= 1024 * 1024;
19 char *buf
= new char[sz
];
40 static void em_usage(char *p
)
42 std::cerr
<< "Usage: " << p
<< "<options>" << std::endl
<<
43 " This utility will defragment and merge (multiple) blobs into larger one\n"
44 " -i path - input blob path (can be specified multiple times)\n"
45 " -o path - output blob path\n"
46 " -p - print all copied IDs\n"
54 std::ifstream index
, data
;
57 em_blob(const char *path
) : completed(0), path_(path
) {
59 data
.open(path
, std::ios_base::in
| std::ios_base::binary
);
60 std::string
index_path(path
);
61 index_path
+= ".index";
62 index
.open(index_path
.c_str(), std::ios_base::in
| std::ios_base::binary
);
71 em_blob(const struct em_blob
&e
) {
72 em_blob(e
.path_
.c_str());
81 typedef boost::shared_ptr
<em_blob
> em_blob_ptr
;
84 struct eblob_disk_control dc
;
87 em_ctl(em_blob_ptr b
) : blob(b
) {
88 memset(&dc
, 0, sizeof(struct eblob_disk_control
));
93 bool operator () (const em_ctl
&s1
, const em_ctl
&s2
) const {
94 return memcmp(s1
.dc
.key
.id
, s2
.dc
.key
.id
, EBLOB_ID_SIZE
);
98 int main(int argc
, char *argv
[])
103 struct eblob_disk_control ddc
;
104 long long total
= 0, removed
= 0, written
= 0, broken
= 0;
105 long long position
= 0;
107 std::vector
<em_blob_ptr
> blobs
;
110 while ((ch
= getopt(argc
, argv
, "i:o:ph")) != -1) {
114 em_blob_ptr
b(new em_blob(optarg
));
118 } catch (const std::exception
&e
) {
119 std::cerr
<< "could not open data or index file for blob " << optarg
<< ": " << e
.what() << std::endl
;
123 output
.assign(optarg
);
135 if (!blobs
.size() || !output
.size()) {
136 std::cerr
<< "You must specify input and output parameters" << std::endl
;
141 std::string data_path
= output
;
142 std::string index_path
= output
+ ".index";
144 std::ofstream
index_out(index_path
.c_str(), std::ios_base::out
| std::ios_base::binary
| std::ios::trunc
);
145 std::ofstream
data_out(data_path
.c_str(), std::ios_base::out
| std::ios_base::binary
| std::ios::trunc
);
147 while (blobs
.size() != 0) {
148 std::vector
<struct em_ctl
> ctl
;
150 for (std::vector
<em_blob_ptr
>::iterator b
= blobs
.begin(); b
< blobs
.end(); ++b
) {
153 struct em_blob
*blob
= b
->get();
159 blob
->index
.read((char *)&c
.dc
, sizeof(struct eblob_disk_control
));
161 if (blob
->index
.gcount() != sizeof(struct eblob_disk_control
)) {
164 std::cout
<< "Completed input stream " << blob
->path_
<<
165 ": total: " << total_input
<<
166 ", rest: " << blobs
.size() << std::endl
;
170 } while (c
.dc
.disk_size
== 0);
175 blob
->index
.seekg(-sizeof(struct eblob_disk_control
), std::ios_base::cur
);
177 eblob_convert_disk_control(&c
.dc
);
182 std::cout
<< "Completed all blobs" << std::endl
;
187 std::sort(ctl
.begin(), ctl
.end(), em_compare());
191 struct em_ctl c
= ctl
[0];
192 c
.blob
->index
.seekg(sizeof(struct eblob_disk_control
), std::ios_base::cur
);
195 std::cout
<< c
.blob
->path_
<< ": " << eblob_dump_control(&c
.dc
, position
, 1, 0) << std::endl
;
198 if (c
.dc
.flags
& BLOB_DISK_CTL_REMOVE
) {
203 c
.blob
->data
.seekg(c
.dc
.position
, std::ios::beg
);
204 c
.blob
->data
.read((char *)&ddc
, sizeof(struct eblob_disk_control
));
205 eblob_convert_disk_control(&ddc
);
207 if (c
.blob
->data
.gcount() != sizeof(struct eblob_disk_control
))
208 throw std::runtime_error("Data read failed");
210 if (ddc
.flags
& BLOB_DISK_CTL_REMOVE
) {
215 size_t size
= ddc
.disk_size
;
217 ddc
.position
= position
;
220 std::cout
<< "out: " << eblob_dump_control(&ddc
, position
, 1, 0) << std::endl
;
223 if (size
> sizeof(struct eblob_disk_control
)) {
224 eblob_convert_disk_control(&ddc
);
226 data_out
.write((char *)&ddc
, sizeof(struct eblob_disk_control
));
227 copy_data(c
.blob
->data
, data_out
, size
- sizeof(struct eblob_disk_control
));
229 index_out
.write((char *)&ddc
, sizeof(struct eblob_disk_control
));
237 } catch (const std::exception
&e
) {
238 std::cerr
<< e
.what() << std::endl
;
241 std::cout
<< "Total records: " << total
<< std::endl
;
242 std::cout
<< "Written records: " << written
<< std::endl
;
243 std::cout
<< "Removed records: " << removed
<< std::endl
;
244 std::cout
<< "Broken records: " << broken
<< std::endl
;