2 This file is part of GNUnet.
3 Copyright (C) 2010, 2013 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU Affero General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
15 You should have received a copy of the GNU Affero General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * @file datastore/gnunet-datastore.c
21 * @brief tool to manipulate datastores
22 * @author Christian Grothoff
26 #include "gnunet_util_lib.h"
27 #include "gnunet_datastore_service.h"
29 GNUNET_NETWORK_STRUCT_BEGIN
34 * Number of bytes in the item (NBO).
36 uint32_t size GNUNET_PACKED;
39 * Type of the item (NBO) (actually an enum GNUNET_BLOCK_Type)
41 uint32_t type GNUNET_PACKED;
44 * Priority of the item (NBO).
46 uint32_t priority GNUNET_PACKED;
49 * Desired anonymity level (NBO).
51 uint32_t anonymity GNUNET_PACKED;
54 * Desired replication level (NBO).
56 uint32_t replication GNUNET_PACKED;
59 * Expiration time (NBO).
61 struct GNUNET_TIME_AbsoluteNBO expiration;
64 * Key under which the item can be found.
66 struct GNUNET_HashCode key;
69 GNUNET_NETWORK_STRUCT_END
73 * Length of our magic header.
75 static const size_t MAGIC_LEN = 16;
80 static const uint8_t MAGIC_BYTES[16] = "GNUNETDATASTORE1";
88 * Insert into the database.
95 static char *file_name;
100 static struct GNUNET_DISK_FileHandle *file_handle;
103 * Global return value.
108 * Handle for datastore.
110 static struct GNUNET_DATASTORE_Handle *datastore;
115 static struct GNUNET_DATASTORE_QueueEntry *qe;
120 static uint64_t record_count;
124 do_shutdown (void *cls)
127 GNUNET_DATASTORE_cancel (qe);
128 if (NULL != datastore)
129 GNUNET_DATASTORE_disconnect (datastore, GNUNET_NO);
130 if (NULL != file_handle)
131 GNUNET_DISK_file_close (file_handle);
136 * Begin dumping the database.
143 * Begin inserting into the database.
150 * Perform next GET operation.
153 do_get (const uint64_t next_uid);
157 * Process a datum that was stored in the datastore.
160 * @param key key for the content
161 * @param size number of bytes in data
162 * @param data content stored
163 * @param type type of the content
164 * @param priority priority of the content
165 * @param anonymity anonymity-level for the content
166 * @param replication replication-level for the content
167 * @param expiration expiration time for the content
168 * @param uid unique identifier for the datum;
169 * maybe 0 if no unique identifier is available
173 const struct GNUNET_HashCode *key,
176 enum GNUNET_BLOCK_Type type,
179 uint32_t replication,
180 struct GNUNET_TIME_Absolute expiration,
187 _("Dumped %" PRIu64 " records\n"),
189 GNUNET_DISK_file_close (file_handle);
196 GNUNET_SCHEDULER_shutdown ();
201 struct DataRecord dr;
202 dr.size = htonl ((uint32_t) size);
203 dr.type = htonl (type);
204 dr.priority = htonl (priority);
205 dr.anonymity = htonl (anonymity);
206 dr.replication = htonl (replication);
207 dr.expiration = GNUNET_TIME_absolute_hton (expiration);
211 len = GNUNET_DISK_file_write (file_handle, &dr, sizeof (dr));
212 if (sizeof (dr) != len)
215 _("Short write to file: %zd bytes expecting %zd\n"),
219 GNUNET_SCHEDULER_shutdown ();
223 len = GNUNET_DISK_file_write (file_handle, data, size);
227 _("Short write to file: %zd bytes expecting %zd\n"),
231 GNUNET_SCHEDULER_shutdown ();
241 * Perform next GET operation.
244 do_get (const uint64_t next_uid)
246 GNUNET_assert (NULL == qe);
247 qe = GNUNET_DATASTORE_get_key (datastore,
251 GNUNET_BLOCK_TYPE_ANY,
252 0 /* queue_priority */,
253 1 /* max_queue_size */,
255 NULL /* proc_cls */);
259 _("Error queueing datastore GET operation\n"));
261 GNUNET_SCHEDULER_shutdown ();
267 * Begin dumping the database.
274 if (NULL != file_name)
276 file_handle = GNUNET_DISK_file_open (file_name,
277 GNUNET_DISK_OPEN_WRITE |
278 GNUNET_DISK_OPEN_TRUNCATE |
279 GNUNET_DISK_OPEN_CREATE,
280 GNUNET_DISK_PERM_USER_READ |
281 GNUNET_DISK_PERM_USER_WRITE);
282 if (NULL == file_handle)
285 _("Unable to open dump file: %s\n"),
288 GNUNET_SCHEDULER_shutdown ();
294 file_handle = GNUNET_DISK_get_handle_from_int_fd (STDOUT_FILENO);
296 GNUNET_DISK_file_write (file_handle, MAGIC_BYTES, MAGIC_LEN);
302 * Continuation called to notify client about result of the
306 * @param success GNUNET_SYSERR on failure (including timeout/queue drop)
307 * GNUNET_NO if content was already there
308 * GNUNET_YES (or other positive value) on success
309 * @param min_expiration minimum expiration time required for 0-priority content to be stored
310 * by the datacache at this time, zero for unknown, forever if we have no
311 * space for 0-priority content
312 * @param msg NULL on success, otherwise an error message
317 struct GNUNET_TIME_Absolute min_expiration,
321 if (GNUNET_SYSERR == success)
324 _("Failed to store item: %s, aborting\n"),
327 GNUNET_SCHEDULER_shutdown ();
331 struct DataRecord dr;
334 len = GNUNET_DISK_file_read (file_handle, &dr, sizeof (dr));
338 _("Inserted %" PRIu64 " records\n"),
341 GNUNET_SCHEDULER_shutdown ();
344 else if (sizeof (dr) != len)
347 _("Short read from file: %zd bytes expecting %zd\n"),
351 GNUNET_SCHEDULER_shutdown ();
355 const size_t size = ntohl (dr.size);
357 len = GNUNET_DISK_file_read (file_handle, data, size);
361 _("Short read from file: %zd bytes expecting %zd\n"),
365 GNUNET_SCHEDULER_shutdown ();
370 qe = GNUNET_DATASTORE_put (datastore,
377 ntohl (dr.anonymity),
378 ntohl (dr.replication),
379 GNUNET_TIME_absolute_ntoh (dr.expiration),
387 _("Error queueing datastore PUT operation\n"));
389 GNUNET_SCHEDULER_shutdown ();
395 * Begin inserting into the database.
402 if (NULL != file_name)
404 file_handle = GNUNET_DISK_file_open (file_name,
405 GNUNET_DISK_OPEN_READ,
406 GNUNET_DISK_PERM_NONE);
407 if (NULL == file_handle)
410 _("Unable to open dump file: %s\n"),
413 GNUNET_SCHEDULER_shutdown ();
419 file_handle = GNUNET_DISK_get_handle_from_int_fd (STDIN_FILENO);
422 uint8_t buf[MAGIC_LEN];
425 len = GNUNET_DISK_file_read (file_handle, buf, MAGIC_LEN);
426 if (len != MAGIC_LEN ||
427 0 != memcmp (buf, MAGIC_BYTES, MAGIC_LEN))
430 _("Input file is not of a supported format\n"));
433 put_cb (NULL, GNUNET_YES, GNUNET_TIME_UNIT_ZERO_ABS, NULL);
438 * Main function that will be run by the scheduler.
441 * @param args remaining command-line arguments
442 * @param cfgfile name of the configuration file used
443 * @param cfg configuration
449 const struct GNUNET_CONFIGURATION_Handle *cfg)
451 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
452 datastore = GNUNET_DATASTORE_connect (cfg);
453 if (NULL == datastore)
456 _("Failed connecting to the datastore.\n"));
458 GNUNET_SCHEDULER_shutdown ();
468 _("Please choose at least one operation: %s, %s\n"),
472 GNUNET_SCHEDULER_shutdown ();
478 * The main function to manipulate datastores.
480 * @param argc number of arguments from the command line
481 * @param argv command line arguments
482 * @return 0 ok, 1 on error
488 struct GNUNET_GETOPT_CommandLineOption options[] = {
489 GNUNET_GETOPT_option_flag ('d',
491 gettext_noop ("Dump all records from the datastore"),
493 GNUNET_GETOPT_option_flag ('i',
495 gettext_noop ("Insert records into the datastore"),
497 GNUNET_GETOPT_option_filename ('f',
500 gettext_noop ("File to dump or insert"),
502 GNUNET_GETOPT_OPTION_END
504 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
508 GNUNET_PROGRAM_run (argc, argv, "gnunet-datastore",
509 gettext_noop ("Manipulate GNUnet datastore"),
510 options, &run, NULL))
512 GNUNET_free ((void*) argv);
516 /* end of gnunet-datastore.c */