add first sketch of gns benchmarking tool
[oweals/gnunet.git] / src / pq / pq_result_helper.c
1  /*
2   This file is part of GNUnet
3   Copyright (C) 2014, 2015, 2016 GNUnet e.V.
4
5   GNUnet is free software; you can redistribute it and/or modify it under the
6   terms of the GNU General Public License as published by the Free Software
7   Foundation; either version 3, or (at your option) any later version.
8
9   GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY
10   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11   A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
12
13   You should have received a copy of the GNU General Public License along with
14   GNUnet; see the file COPYING.  If not, If not, see <http://www.gnu.org/licenses/>
15 */
16 /**
17  * @file pq/pq_result_helper.c
18  * @brief functions to extract result values
19  * @author Christian Grothoff
20  */
21 #include "platform.h"
22 #include "gnunet_util_lib.h"
23 #include "gnunet_pq_lib.h"
24
25
26 /**
27  * Function called to clean up memory allocated
28  * by a #GNUNET_PQ_ResultConverter.
29  *
30  * @param cls closure
31  * @param rd result data to clean up
32  */
33 static void
34 clean_varsize_blob (void *cls,
35                     void *rd)
36 {
37   void **dst = rd;
38
39   if (NULL != *dst)
40   {
41     GNUNET_free (*dst);
42     *dst = NULL;
43   }
44 }
45
46
47 /**
48  * Extract data from a Postgres database @a result at row @a row.
49  *
50  * @param cls closure
51  * @param result where to extract data from
52  * @param int row to extract data from
53  * @param fname name (or prefix) of the fields to extract from
54  * @param[in,out] dst_size where to store size of result, may be NULL
55  * @param[out] dst where to store the result
56  * @return
57  *   #GNUNET_YES if all results could be extracted
58  *   #GNUNET_SYSERR if a result was invalid (non-existing field)
59  */
60 static int
61 extract_varsize_blob (void *cls,
62                       PGresult *result,
63                       int row,
64                       const char *fname,
65                       size_t *dst_size,
66                       void *dst)
67 {
68   size_t len;
69   const char *res;
70   void *idst;
71   int fnum;
72
73   *dst_size = 0;
74   *((void **) dst) = NULL;
75
76   fnum = PQfnumber (result,
77                     fname);
78   if (fnum < 0)
79   {
80     GNUNET_break (0);
81     return GNUNET_SYSERR;
82   }
83   if (PQgetisnull (result,
84                    row,
85                    fnum))
86   {
87     /* Let's allow this for varsize */
88     return GNUNET_OK;
89   }
90   /* if a field is null, continue but
91    * remember that we now return a different result */
92   len = PQgetlength (result,
93                      row,
94                      fnum);
95   res = PQgetvalue (result,
96                     row,
97                     fnum);
98   GNUNET_assert (NULL != res);
99   *dst_size = len;
100   idst = GNUNET_malloc (len);
101   *((void **) dst) = idst;
102   GNUNET_memcpy (idst,
103                  res,
104                  len);
105   return GNUNET_OK;
106 }
107
108
109 /**
110  * Variable-size result expected.
111  *
112  * @param name name of the field in the table
113  * @param[out] dst where to store the result, allocated
114  * @param[out] sptr where to store the size of @a dst
115  * @return array entry for the result specification to use
116  */
117 struct GNUNET_PQ_ResultSpec
118 GNUNET_PQ_result_spec_variable_size (const char *name,
119                                      void **dst,
120                                      size_t *sptr)
121 {
122   struct GNUNET_PQ_ResultSpec res =
123     { &extract_varsize_blob,
124       &clean_varsize_blob, NULL,
125       (void *) (dst), 0, name, sptr };
126   return res;
127 }
128
129
130 /**
131  * Extract data from a Postgres database @a result at row @a row.
132  *
133  * @param cls closure
134  * @param result where to extract data from
135  * @param int row to extract data from
136  * @param fname name (or prefix) of the fields to extract from
137  * @param[in] dst_size desired size, never NULL
138  * @param[out] dst where to store the result
139  * @return
140  *   #GNUNET_YES if all results could be extracted
141  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
142  */
143 static int
144 extract_fixed_blob (void *cls,
145                     PGresult *result,
146                     int row,
147                     const char *fname,
148                     size_t *dst_size,
149                     void *dst)
150 {
151   size_t len;
152   const char *res;
153   int fnum;
154
155   fnum = PQfnumber (result,
156                     fname);
157   if (fnum < 0)
158   {
159     GNUNET_break (0);
160     return GNUNET_SYSERR;
161   }
162   if (PQgetisnull (result,
163                    row,
164                    fnum))
165   {
166     GNUNET_break (0);
167     return GNUNET_SYSERR;
168   }
169
170   /* if a field is null, continue but
171    * remember that we now return a different result */
172   len = PQgetlength (result,
173                      row,
174                      fnum);
175   if (*dst_size != len)
176   {
177     GNUNET_break (0);
178     return GNUNET_SYSERR;
179   }
180   res = PQgetvalue (result,
181                     row,
182                     fnum);
183   GNUNET_assert (NULL != res);
184   GNUNET_memcpy (dst,
185                  res,
186                  len);
187   return GNUNET_OK;
188 }
189
190
191 /**
192  * Fixed-size result expected.
193  *
194  * @param name name of the field in the table
195  * @param[out] dst where to store the result
196  * @param dst_size number of bytes in @a dst
197  * @return array entry for the result specification to use
198  */
199 struct GNUNET_PQ_ResultSpec
200 GNUNET_PQ_result_spec_fixed_size (const char *name,
201                                   void *dst,
202                                   size_t dst_size)
203 {
204   struct GNUNET_PQ_ResultSpec res =
205     { &extract_fixed_blob,
206       NULL, NULL,
207       (dst), dst_size, name, NULL };
208   return res;
209 }
210
211
212 /**
213  * Extract data from a Postgres database @a result at row @a row.
214  *
215  * @param cls closure
216  * @param result where to extract data from
217  * @param int row to extract data from
218  * @param fname name (or prefix) of the fields to extract from
219  * @param[in,out] dst_size where to store size of result, may be NULL
220  * @param[out] dst where to store the result
221  * @return
222  *   #GNUNET_YES if all results could be extracted
223  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
224  */
225 static int
226 extract_rsa_public_key (void *cls,
227                         PGresult *result,
228                         int row,
229                         const char *fname,
230                         size_t *dst_size,
231                         void *dst)
232 {
233   struct GNUNET_CRYPTO_RsaPublicKey **pk = dst;
234   size_t len;
235   const char *res;
236   int fnum;
237
238   *pk = NULL;
239   fnum = PQfnumber (result,
240                     fname);
241   if (fnum < 0)
242   {
243     GNUNET_break (0);
244     return GNUNET_SYSERR;
245   }
246   if (PQgetisnull (result,
247                    row,
248                    fnum))
249   {
250     GNUNET_break (0);
251     return GNUNET_SYSERR;
252   }
253   /* if a field is null, continue but
254    * remember that we now return a different result */
255   len = PQgetlength (result,
256                      row,
257                      fnum);
258   res = PQgetvalue (result,
259                     row,
260                     fnum);
261   *pk = GNUNET_CRYPTO_rsa_public_key_decode (res,
262                                              len);
263   if (NULL == *pk)
264   {
265     GNUNET_break (0);
266     return GNUNET_SYSERR;
267   }
268   return GNUNET_OK;
269 }
270
271
272 /**
273  * Function called to clean up memory allocated
274  * by a #GNUNET_PQ_ResultConverter.
275  *
276  * @param cls closure
277  * @param rd result data to clean up
278  */
279 static void
280 clean_rsa_public_key (void *cls,
281                       void *rd)
282 {
283   struct GNUNET_CRYPTO_RsaPublicKey **pk = rd;
284
285   if (NULL != *pk)
286   {
287     GNUNET_CRYPTO_rsa_public_key_free (*pk);
288     *pk = NULL;
289   }
290 }
291
292
293 /**
294  * RSA public key expected.
295  *
296  * @param name name of the field in the table
297  * @param[out] rsa where to store the result
298  * @return array entry for the result specification to use
299  */
300 struct GNUNET_PQ_ResultSpec
301 GNUNET_PQ_result_spec_rsa_public_key (const char *name,
302                                       struct GNUNET_CRYPTO_RsaPublicKey **rsa)
303 {
304   struct GNUNET_PQ_ResultSpec res =
305     { &extract_rsa_public_key,
306       &clean_rsa_public_key,
307       NULL,
308       (void *) rsa, 0, name, NULL };
309   return res;
310 }
311
312
313 /**
314  * Extract data from a Postgres database @a result at row @a row.
315  *
316  * @param cls closure
317  * @param result where to extract data from
318  * @param int row to extract data from
319  * @param fname name (or prefix) of the fields to extract from
320  * @param[in,out] dst_size where to store size of result, may be NULL
321  * @param[out] dst where to store the result
322  * @return
323  *   #GNUNET_YES if all results could be extracted
324  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
325  */
326 static int
327 extract_rsa_signature (void *cls,
328                        PGresult *result,
329                        int row,
330                        const char *fname,
331                        size_t *dst_size,
332                        void *dst)
333 {
334   struct GNUNET_CRYPTO_RsaSignature **sig = dst;
335   size_t len;
336   const char *res;
337   int fnum;
338
339   *sig = NULL;
340   fnum = PQfnumber (result,
341                     fname);
342   if (fnum < 0)
343   {
344     GNUNET_break (0);
345     return GNUNET_SYSERR;
346   }
347   if (PQgetisnull (result,
348                    row,
349                    fnum))
350   {
351     GNUNET_break (0);
352     return GNUNET_SYSERR;
353   }
354   /* if a field is null, continue but
355    * remember that we now return a different result */
356   len = PQgetlength (result,
357                      row,
358                      fnum);
359   res = PQgetvalue (result,
360                     row,
361                     fnum);
362   *sig = GNUNET_CRYPTO_rsa_signature_decode (res,
363                                              len);
364   if (NULL == *sig)
365   {
366     GNUNET_break (0);
367     return GNUNET_SYSERR;
368   }
369   return GNUNET_OK;
370 }
371
372
373 /**
374  * Function called to clean up memory allocated
375  * by a #GNUNET_PQ_ResultConverter.
376  *
377  * @param cls closure
378  * @param rd result data to clean up
379  */
380 static void
381 clean_rsa_signature (void *cls,
382                      void *rd)
383 {
384   struct GNUNET_CRYPTO_RsaSignature **sig = rd;
385
386   if (NULL != *sig)
387   {
388     GNUNET_CRYPTO_rsa_signature_free (*sig);
389     *sig = NULL;
390   }
391 }
392
393
394 /**
395  * RSA signature expected.
396  *
397  * @param name name of the field in the table
398  * @param[out] sig where to store the result;
399  * @return array entry for the result specification to use
400  */
401 struct GNUNET_PQ_ResultSpec
402 GNUNET_PQ_result_spec_rsa_signature (const char *name,
403                                     struct GNUNET_CRYPTO_RsaSignature **sig)
404 {
405   struct GNUNET_PQ_ResultSpec res =
406     { &extract_rsa_signature,
407       &clean_rsa_signature,
408       NULL,
409       (void *) sig, 0, (name), NULL };
410   return res;
411 }
412
413
414 /**
415  * Extract data from a Postgres database @a result at row @a row.
416  *
417  * @param cls closure
418  * @param result where to extract data from
419  * @param int row to extract data from
420  * @param fname name (or prefix) of the fields to extract from
421  * @param[in,out] dst_size where to store size of result, may be NULL
422  * @param[out] dst where to store the result
423  * @return
424  *   #GNUNET_YES if all results could be extracted
425  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
426  */
427 static int
428 extract_string (void *cls,
429                 PGresult *result,
430                 int row,
431                 const char *fname,
432                 size_t *dst_size,
433                 void *dst)
434 {
435   char **str = dst;
436   size_t len;
437   const char *res;
438   int fnum;
439
440   *str = NULL;
441   fnum = PQfnumber (result,
442                     fname);
443   if (fnum < 0)
444   {
445     GNUNET_break (0);
446     return GNUNET_SYSERR;
447   }
448   if (PQgetisnull (result,
449                    row,
450                    fnum))
451   {
452     GNUNET_break (0);
453     return GNUNET_SYSERR;
454   }
455   /* if a field is null, continue but
456    * remember that we now return a different result */
457   len = PQgetlength (result,
458                      row,
459                      fnum);
460   res = PQgetvalue (result,
461                     row,
462                     fnum);
463   *str = GNUNET_strndup (res,
464                          len);
465   if (NULL == *str)
466   {
467     GNUNET_break (0);
468     return GNUNET_SYSERR;
469   }
470   return GNUNET_OK;
471 }
472
473
474 /**
475  * Function called to clean up memory allocated
476  * by a #GNUNET_PQ_ResultConverter.
477  *
478  * @param cls closure
479  * @param rd result data to clean up
480  */
481 static void
482 clean_string (void *cls,
483               void *rd)
484 {
485   char **str = rd;
486
487   if (NULL != *str)
488   {
489     GNUNET_free (*str);
490     *str = NULL;
491   }
492 }
493
494
495 /**
496  * 0-terminated string expected.
497  *
498  * @param name name of the field in the table
499  * @param[out] dst where to store the result, allocated
500  * @return array entry for the result specification to use
501  */
502 struct GNUNET_PQ_ResultSpec
503 GNUNET_PQ_result_spec_string (const char *name,
504                               char **dst)
505 {
506   struct GNUNET_PQ_ResultSpec res =
507     { &extract_string,
508       &clean_string,
509       NULL,
510       (void *) dst, 0, (name), NULL };
511   return res;
512 }
513
514
515 /**
516  * Absolute time expected.
517  *
518  * @param name name of the field in the table
519  * @param[out] at where to store the result
520  * @return array entry for the result specification to use
521  */
522 struct GNUNET_PQ_ResultSpec
523 GNUNET_PQ_result_spec_absolute_time (const char *name,
524                                      struct GNUNET_TIME_Absolute *at)
525 {
526   return GNUNET_PQ_result_spec_uint64 (name,
527                                        &at->abs_value_us);
528 }
529
530
531 /**
532  * Absolute time in network byte order expected.
533  *
534  * @param name name of the field in the table
535  * @param[out] at where to store the result
536  * @return array entry for the result specification to use
537  */
538 struct GNUNET_PQ_ResultSpec
539 GNUNET_PQ_result_spec_absolute_time_nbo (const char *name,
540                                          struct GNUNET_TIME_AbsoluteNBO *at)
541 {
542   struct GNUNET_PQ_ResultSpec res =
543     GNUNET_PQ_result_spec_auto_from_type(name, &at->abs_value_us__);
544   return res;
545 }
546
547
548 /**
549  * Extract data from a Postgres database @a result at row @a row.
550  *
551  * @param cls closure
552  * @param result where to extract data from
553  * @param int row to extract data from
554  * @param fname name (or prefix) of the fields to extract from
555  * @param[in,out] dst_size where to store size of result, may be NULL
556  * @param[out] dst where to store the result
557  * @return
558  *   #GNUNET_YES if all results could be extracted
559  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
560  */
561 static int
562 extract_uint16 (void *cls,
563                 PGresult *result,
564                 int row,
565                 const char *fname,
566                 size_t *dst_size,
567                 void *dst)
568 {
569   uint16_t *udst = dst;
570   const uint16_t *res;
571   int fnum;
572
573   fnum = PQfnumber (result,
574                     fname);
575   if (fnum < 0)
576   {
577     GNUNET_break (0);
578     return GNUNET_SYSERR;
579   }
580   if (PQgetisnull (result,
581                    row,
582                    fnum))
583   {
584     GNUNET_break (0);
585     return GNUNET_SYSERR;
586   }
587   GNUNET_assert (NULL != dst);
588   if (sizeof (uint16_t) != *dst_size)
589   {
590     GNUNET_break (0);
591     return GNUNET_SYSERR;
592   }
593   if (sizeof (uint16_t) !=
594       PQgetlength (result,
595                    row,
596                    fnum))
597   {
598     GNUNET_break (0);
599     return GNUNET_SYSERR;
600   }
601   res = (uint16_t *) PQgetvalue (result,
602                                  row,
603                                  fnum);
604   *udst = ntohs (*res);
605   return GNUNET_OK;
606 }
607
608
609 /**
610  * uint16_t expected.
611  *
612  * @param name name of the field in the table
613  * @param[out] u16 where to store the result
614  * @return array entry for the result specification to use
615  */
616 struct GNUNET_PQ_ResultSpec
617 GNUNET_PQ_result_spec_uint16 (const char *name,
618                               uint16_t *u16)
619 {
620   struct GNUNET_PQ_ResultSpec res =
621     { &extract_uint16,
622       NULL,
623       NULL,
624       (void *) u16, sizeof (*u16), (name), NULL };
625   return res;
626 }
627
628
629 /**
630  * Extract data from a Postgres database @a result at row @a row.
631  *
632  * @param cls closure
633  * @param result where to extract data from
634  * @param int row to extract data from
635  * @param fname name (or prefix) of the fields to extract from
636  * @param[in,out] dst_size where to store size of result, may be NULL
637  * @param[out] dst where to store the result
638  * @return
639  *   #GNUNET_YES if all results could be extracted
640  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
641  */
642 static int
643 extract_uint32 (void *cls,
644                 PGresult *result,
645                 int row,
646                 const char *fname,
647                 size_t *dst_size,
648                 void *dst)
649 {
650   uint32_t *udst = dst;
651   const uint32_t *res;
652   int fnum;
653
654   fnum = PQfnumber (result,
655                     fname);
656   if (fnum < 0)
657   {
658     GNUNET_break (0);
659     return GNUNET_SYSERR;
660   }
661   if (PQgetisnull (result,
662                    row,
663                    fnum))
664   {
665     GNUNET_break (0);
666     return GNUNET_SYSERR;
667   }
668   GNUNET_assert (NULL != dst);
669   if (sizeof (uint32_t) != *dst_size)
670   {
671     GNUNET_break (0);
672     return GNUNET_SYSERR;
673   }
674   if (sizeof (uint32_t) !=
675       PQgetlength (result,
676                    row,
677                    fnum))
678   {
679     GNUNET_break (0);
680     return GNUNET_SYSERR;
681   }
682   res = (uint32_t *) PQgetvalue (result,
683                                  row,
684                                  fnum);
685   *udst = ntohl (*res);
686   return GNUNET_OK;
687 }
688
689
690 /**
691  * uint32_t expected.
692  *
693  * @param name name of the field in the table
694  * @param[out] u32 where to store the result
695  * @return array entry for the result specification to use
696  */
697 struct GNUNET_PQ_ResultSpec
698 GNUNET_PQ_result_spec_uint32 (const char *name,
699                               uint32_t *u32)
700 {
701   struct GNUNET_PQ_ResultSpec res =
702     { &extract_uint32,
703       NULL,
704       NULL,
705       (void *) u32, sizeof (*u32), (name), NULL };
706   return res;
707 }
708
709
710 /**
711  * Extract data from a Postgres database @a result at row @a row.
712  *
713  * @param cls closure
714  * @param result where to extract data from
715  * @param int row to extract data from
716  * @param fname name (or prefix) of the fields to extract from
717  * @param[in,out] dst_size where to store size of result, may be NULL
718  * @param[out] dst where to store the result
719  * @return
720  *   #GNUNET_YES if all results could be extracted
721  *   #GNUNET_SYSERR if a result was invalid (non-existing field or NULL)
722  */
723 static int
724 extract_uint64 (void *cls,
725                 PGresult *result,
726                 int row,
727                 const char *fname,
728                 size_t *dst_size,
729                 void *dst)
730 {
731   uint64_t *udst = dst;
732   const uint64_t *res;
733   int fnum;
734
735   fnum = PQfnumber (result,
736                     fname);
737   if (fnum < 0)
738   {
739     GNUNET_break (0);
740     return GNUNET_SYSERR;
741   }
742   if (PQgetisnull (result,
743                    row,
744                    fnum))
745   {
746     GNUNET_break (0);
747     return GNUNET_SYSERR;
748   }
749   GNUNET_assert (NULL != dst);
750   if (sizeof (uint64_t) != *dst_size)
751   {
752     GNUNET_break (0);
753     return GNUNET_SYSERR;
754   }
755   if (sizeof (uint64_t) !=
756       PQgetlength (result,
757                    row,
758                    fnum))
759   {
760     GNUNET_break (0);
761     return GNUNET_SYSERR;
762   }
763   res = (uint64_t *) PQgetvalue (result,
764                                  row,
765                                  fnum);
766   *udst = GNUNET_ntohll (*res);
767   return GNUNET_OK;
768 }
769
770
771 /**
772  * uint64_t expected.
773  *
774  * @param name name of the field in the table
775  * @param[out] u64 where to store the result
776  * @return array entry for the result specification to use
777  */
778 struct GNUNET_PQ_ResultSpec
779 GNUNET_PQ_result_spec_uint64 (const char *name,
780                               uint64_t *u64)
781 {
782   struct GNUNET_PQ_ResultSpec res =
783     { &extract_uint64,
784       NULL,
785       NULL,
786       (void *) u64, sizeof (*u64), (name), NULL };
787   return res;
788 }
789
790
791 /* end of pq_result_helper.c */