fix indentation, typo, improve logging
[oweals/gnunet.git] / src / datastore / gnunet-datastore.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2010, 2013 GNUnet e.V.
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
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      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18      Boston, MA 02110-1301, USA.
19 */
20
21 /**
22  * @file datastore/gnunet-datastore.c
23  * @brief tool to manipulate datastores
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_datastore_service.h"
29
30
31 /**
32  * Name of the second configuration file.
33  */
34 static char *alternative_cfg;
35
36 /**
37  * Global return value.
38  */
39 static int ret;
40
41 /**
42  * Our offset on 'get'.
43  */
44 static uint64_t offset;
45
46 /**
47  * First UID ever returned.
48  */
49 static uint64_t first_uid;
50
51 /**
52  * Configuration for the source database.
53  */
54 static struct GNUNET_CONFIGURATION_Handle *scfg;
55
56 /**
57  * Handle for database source.
58  */
59 static struct GNUNET_DATASTORE_Handle *db_src;
60
61 /**
62  * Handle for database destination.
63  */
64 static struct GNUNET_DATASTORE_Handle *db_dst;
65
66 /**
67  * Current operation.
68  */
69 static struct GNUNET_DATASTORE_QueueEntry *qe;
70
71
72 static void
73 do_shutdown (void *cls)
74 {
75   if (NULL != qe)
76     GNUNET_DATASTORE_cancel (qe);
77   GNUNET_DATASTORE_disconnect (db_src, GNUNET_NO);
78   GNUNET_DATASTORE_disconnect (db_dst, GNUNET_NO);
79   GNUNET_CONFIGURATION_destroy (scfg);
80 }
81
82
83 /**
84  * Perform next GET operation.
85  */
86 static void
87 do_get (void);
88
89
90 /**
91  * Continuation called to notify client about result of the
92  * operation.
93  *
94  * @param cls closure
95  * @param success GNUNET_SYSERR on failure (including timeout/queue drop)
96  *                GNUNET_NO if content was already there
97  *                GNUNET_YES (or other positive value) on success
98  * @param min_expiration minimum expiration time required for 0-priority content to be stored
99  *                by the datacache at this time, zero for unknown, forever if we have no
100  *                space for 0-priority content
101  * @param msg NULL on success, otherwise an error message
102  */
103 static void
104 do_finish (void *cls,
105            int32_t success,
106            struct GNUNET_TIME_Absolute min_expiration,
107            const char *msg)
108 {
109   qe = NULL;
110   if (GNUNET_SYSERR == success)
111   {
112     fprintf (stderr,
113              _("Failed to store item: %s, aborting\n"),
114              msg);
115     ret = 1;
116     GNUNET_SCHEDULER_shutdown ();
117     return;
118   }
119   do_get ();
120 }
121
122
123 /**
124  * Process a datum that was stored in the datastore.
125  *
126  * @param cls closure
127  * @param key key for the content
128  * @param size number of bytes in data
129  * @param data content stored
130  * @param type type of the content
131  * @param priority priority of the content
132  * @param anonymity anonymity-level for the content
133  * @param expiration expiration time for the content
134  * @param uid unique identifier for the datum;
135  *        maybe 0 if no unique identifier is available
136  */
137 static void
138 do_put (void *cls,
139         const struct GNUNET_HashCode *key,
140         size_t size,
141         const void *data,
142         enum GNUNET_BLOCK_Type type,
143         uint32_t priority,
144         uint32_t anonymity,
145         struct GNUNET_TIME_Absolute
146         expiration, uint64_t uid)
147 {
148   qe = NULL;
149   if ( (0 != offset) &&
150        (uid == first_uid) )
151   {
152     GNUNET_SCHEDULER_shutdown ();
153     return;
154   }
155   if (0 == offset)
156     first_uid = uid;
157   qe = GNUNET_DATASTORE_put (db_dst, 0,
158                              key, size, data, type,
159                              priority, anonymity,
160                              0 /* FIXME: replication is lost... */,
161                              expiration,
162                              0, 1,
163                              &do_finish, NULL);
164 }
165
166
167 /**
168  * Perform next GET operation.
169  */
170 static void
171 do_get ()
172 {
173   qe = GNUNET_DATASTORE_get_key (db_src,
174                                  offset,
175                                  NULL, GNUNET_BLOCK_TYPE_ANY,
176                                  0, 1,
177                                  &do_put, NULL);
178 }
179
180
181
182 /**
183  * Main function that will be run by the scheduler.
184  *
185  * @param cls closure
186  * @param args remaining command-line arguments
187  * @param cfgfile name of the configuration file used
188  * @param cfg configuration -- for destination datastore
189  */
190 static void
191 run (void *cls, char *const *args, const char *cfgfile,
192      const struct GNUNET_CONFIGURATION_Handle *cfg)
193 {
194   if (NULL == alternative_cfg)
195     return; /* nothing to be done */
196   if (0 == strcmp (cfgfile, alternative_cfg))
197   {
198     fprintf (stderr,
199              _("Cannot use the same configuration for source and destination\n"));
200     ret = 1;
201     return;
202   }
203   scfg = GNUNET_CONFIGURATION_create ();
204   if (GNUNET_OK !=
205       GNUNET_CONFIGURATION_load (scfg,
206                                  alternative_cfg))
207   {
208     GNUNET_CONFIGURATION_destroy (scfg);
209     ret = 1;
210     return;
211   }
212   db_src = GNUNET_DATASTORE_connect (scfg);
213   if (NULL == db_src)
214   {
215     GNUNET_CONFIGURATION_destroy (scfg);
216     ret = 1;
217     return;
218   }
219   db_dst = GNUNET_DATASTORE_connect (cfg);
220   if (NULL == db_dst)
221   {
222     GNUNET_DATASTORE_disconnect (db_src, GNUNET_NO);
223     GNUNET_CONFIGURATION_destroy (scfg);
224     ret = 1;
225     return;
226   }
227   GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL);
228   do_get ();
229 }
230
231
232 /**
233  * The main function to manipulate datastores.
234  *
235  * @param argc number of arguments from the command line
236  * @param argv command line arguments
237  * @return 0 ok, 1 on error
238  */
239 int
240 main (int argc, char *const *argv)
241 {
242   static const struct GNUNET_GETOPT_CommandLineOption options[] = {
243     { 's', "sourcecfg", "FILENAME",
244       gettext_noop ("specifies the configuration to use to access an alternative datastore; will merge that datastore into our current datastore"),
245       1, &GNUNET_GETOPT_set_filename, &alternative_cfg },
246     GNUNET_GETOPT_OPTION_END
247   };
248   if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
249     return 2;
250
251   if (GNUNET_OK !=
252       GNUNET_PROGRAM_run (argc, argv, "gnunet-datastore",
253                           gettext_noop ("Manipulate GNUnet datastore"),
254                           options, &run, NULL))
255     ret = 1;
256   GNUNET_free ((void*) argv);
257   return ret;
258 }
259
260 /* end of gnunet-datastore.c */