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/>.
18 SPDX-License-Identifier: AGPL3.0-or-later
22 * @file datastore/gnunet-datastore.c
23 * @brief tool to manipulate datastores
24 * @author Christian Grothoff
28 #include "gnunet_util_lib.h"
29 #include "gnunet_datastore_service.h"
31 GNUNET_NETWORK_STRUCT_BEGIN
36 * Number of bytes in the item (NBO).
38 uint32_t size GNUNET_PACKED;
41 * Type of the item (NBO) (actually an enum GNUNET_BLOCK_Type)
43 uint32_t type GNUNET_PACKED;
46 * Priority of the item (NBO).
48 uint32_t priority GNUNET_PACKED;
51 * Desired anonymity level (NBO).
53 uint32_t anonymity GNUNET_PACKED;
56 * Desired replication level (NBO).
58 uint32_t replication GNUNET_PACKED;
61 * Expiration time (NBO).
63 struct GNUNET_TIME_AbsoluteNBO expiration;
66 * Key under which the item can be found.
68 struct GNUNET_HashCode key;
70 GNUNET_NETWORK_STRUCT_END
74 * Length of our magic header.
76 static const size_t MAGIC_LEN = 16;
81 static const uint8_t MAGIC_BYTES[16] = "GNUNETDATASTORE1";
89 * Insert into the database.
96 static char *file_name;
101 static struct GNUNET_DISK_FileHandle *file_handle;
104 * Global return value.
109 * Handle for datastore.
111 static struct GNUNET_DATASTORE_Handle *datastore;
116 static struct GNUNET_DATASTORE_QueueEntry *qe;
121 static uint64_t record_count;
125 do_shutdown (void *cls)
128 GNUNET_DATASTORE_cancel (qe);
129 if (NULL != datastore)
130 GNUNET_DATASTORE_disconnect (datastore, GNUNET_NO);
131 if (NULL != file_handle)
132 GNUNET_DISK_file_close (file_handle);
137 * Begin dumping the database.
144 * Begin inserting into the database.
151 * Perform next GET operation.
154 do_get (const uint64_t next_uid);
158 * Process a datum that was stored in the datastore.
161 * @param key key for the content
162 * @param size number of bytes in data
163 * @param data content stored
164 * @param type type of the content
165 * @param priority priority of the content
166 * @param anonymity anonymity-level for the content
167 * @param replication replication-level for the content
168 * @param expiration expiration time for the content
169 * @param uid unique identifier for the datum;
170 * maybe 0 if no unique identifier is available
174 const struct GNUNET_HashCode *key,
177 enum GNUNET_BLOCK_Type type,
180 uint32_t replication,
181 struct GNUNET_TIME_Absolute expiration,
187 fprintf (stderr, _ ("Dumped %" PRIu64 " records\n"), record_count);
188 GNUNET_DISK_file_close (file_handle);
195 GNUNET_SCHEDULER_shutdown ();
200 struct DataRecord dr;
201 dr.size = htonl ((uint32_t) size);
202 dr.type = htonl (type);
203 dr.priority = htonl (priority);
204 dr.anonymity = htonl (anonymity);
205 dr.replication = htonl (replication);
206 dr.expiration = GNUNET_TIME_absolute_hton (expiration);
210 len = GNUNET_DISK_file_write (file_handle, &dr, sizeof(dr));
211 if (sizeof(dr) != len)
214 _ ("Short write to file: %zd bytes expecting %zd\n"),
218 GNUNET_SCHEDULER_shutdown ();
222 len = GNUNET_DISK_file_write (file_handle, data, size);
226 _ ("Short write to file: %zd bytes expecting %zd\n"),
230 GNUNET_SCHEDULER_shutdown ();
240 * Perform next GET operation.
243 do_get (const uint64_t next_uid)
245 GNUNET_assert (NULL == qe);
246 qe = GNUNET_DATASTORE_get_key (datastore,
250 GNUNET_BLOCK_TYPE_ANY,
251 0 /* queue_priority */,
252 1 /* max_queue_size */,
254 NULL /* proc_cls */);
257 fprintf (stderr, _ ("Error queueing datastore GET operation\n"));
259 GNUNET_SCHEDULER_shutdown ();
265 * Begin dumping the database.
272 if (NULL != file_name)
274 file_handle = GNUNET_DISK_file_open (file_name,
275 GNUNET_DISK_OPEN_WRITE
276 | GNUNET_DISK_OPEN_TRUNCATE
277 | GNUNET_DISK_OPEN_CREATE,
278 GNUNET_DISK_PERM_USER_READ
279 | GNUNET_DISK_PERM_USER_WRITE);
280 if (NULL == file_handle)
282 fprintf (stderr, _ ("Unable to open dump file: %s\n"), file_name);
284 GNUNET_SCHEDULER_shutdown ();
290 file_handle = GNUNET_DISK_get_handle_from_int_fd (STDOUT_FILENO);
292 GNUNET_DISK_file_write (file_handle, MAGIC_BYTES, MAGIC_LEN);
298 * Continuation called to notify client about result of the
302 * @param success GNUNET_SYSERR on failure (including timeout/queue drop)
303 * GNUNET_NO if content was already there
304 * GNUNET_YES (or other positive value) on success
305 * @param min_expiration minimum expiration time required for 0-priority content to be stored
306 * by the datacache at this time, zero for unknown, forever if we have no
307 * space for 0-priority content
308 * @param msg NULL on success, otherwise an error message
313 struct GNUNET_TIME_Absolute min_expiration,
317 if (GNUNET_SYSERR == success)
319 fprintf (stderr, _ ("Failed to store item: %s, aborting\n"), msg);
321 GNUNET_SCHEDULER_shutdown ();
325 struct DataRecord dr;
328 len = GNUNET_DISK_file_read (file_handle, &dr, sizeof(dr));
331 fprintf (stderr, _ ("Inserted %" PRIu64 " records\n"), record_count);
333 GNUNET_SCHEDULER_shutdown ();
336 else if (sizeof(dr) != len)
339 _ ("Short read from file: %zd bytes expecting %zd\n"),
343 GNUNET_SCHEDULER_shutdown ();
347 const size_t size = ntohl (dr.size);
349 len = GNUNET_DISK_file_read (file_handle, data, size);
353 _ ("Short read from file: %zd bytes expecting %zd\n"),
357 GNUNET_SCHEDULER_shutdown ();
362 qe = GNUNET_DATASTORE_put (datastore,
369 ntohl (dr.anonymity),
370 ntohl (dr.replication),
371 GNUNET_TIME_absolute_ntoh (dr.expiration),
378 fprintf (stderr, _ ("Error queueing datastore PUT operation\n"));
380 GNUNET_SCHEDULER_shutdown ();
386 * Begin inserting into the database.
393 if (NULL != file_name)
395 file_handle = GNUNET_DISK_file_open (file_name,
396 GNUNET_DISK_OPEN_READ,
397 GNUNET_DISK_PERM_NONE);
398 if (NULL == file_handle)
400 fprintf (stderr, _ ("Unable to open dump file: %s\n"), file_name);
402 GNUNET_SCHEDULER_shutdown ();
408 file_handle = GNUNET_DISK_get_handle_from_int_fd (STDIN_FILENO);
411 uint8_t buf[MAGIC_LEN];
414 len = GNUNET_DISK_file_read (file_handle, buf, MAGIC_LEN);
415 if ((len != MAGIC_LEN) || (0 != memcmp (buf, MAGIC_BYTES, MAGIC_LEN)))
417 fprintf (stderr, _ ("Input file is not of a supported format\n"));
420 put_cb (NULL, GNUNET_YES, GNUNET_TIME_UNIT_ZERO_ABS, NULL);
425 * Main function that will be run by the scheduler.
428 * @param args remaining command-line arguments
429 * @param cfgfile name of the configuration file used
430 * @param cfg configuration
436 const struct GNUNET_CONFIGURATION_Handle *cfg)
438 GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
439 datastore = GNUNET_DATASTORE_connect (cfg);
440 if (NULL == datastore)
442 fprintf (stderr, _ ("Failed connecting to the datastore.\n"));
444 GNUNET_SCHEDULER_shutdown ();
454 _ ("Please choose at least one operation: %s, %s\n"),
458 GNUNET_SCHEDULER_shutdown ();
464 * The main function to manipulate datastores.
466 * @param argc number of arguments from the command line
467 * @param argv command line arguments
468 * @return 0 ok, 1 on error
471 main (int argc, char *const *argv)
473 struct GNUNET_GETOPT_CommandLineOption options[] =
474 { GNUNET_GETOPT_option_flag ('d',
477 "Dump all records from the datastore"),
479 GNUNET_GETOPT_option_flag ('i',
482 "Insert records into the datastore"),
484 GNUNET_GETOPT_option_filename ('f',
487 gettext_noop ("File to dump or insert"),
489 GNUNET_GETOPT_OPTION_END };
491 if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
495 GNUNET_PROGRAM_run (argc,
498 gettext_noop ("Manipulate GNUnet datastore"),
503 GNUNET_free ((void *) argv);
508 /* end of gnunet-datastore.c */