diff options
author | Martin Schanzenbach <schanzen@gnunet.org> | 2022-10-03 13:23:35 +0900 |
---|---|---|
committer | Martin Schanzenbach <schanzen@gnunet.org> | 2022-10-03 13:23:35 +0900 |
commit | e891aa916c09b3e79c02f7c486f3e1a1c015769a (patch) | |
tree | e0e3eb9c1828b8652c91bc9bb624395ebe256544 | |
parent | 4611664be0ba79ec7029a74cf961f28f2a658241 (diff) | |
download | gnunet-e891aa916c09b3e79c02f7c486f3e1a1c015769a.tar.gz gnunet-e891aa916c09b3e79c02f7c486f3e1a1c015769a.zip |
NAMESTORE: Bulk store API and fix for delayed store activities
New API: GNUNET_NAMESTORE_records_store2 which allows the caller
to pass an array of records in order to facilitate bulk import of zone
data.
Further, the transactional API requires that monitors and namecache
updates are delayed until transactions are actually commited.
-rw-r--r-- | src/include/gnunet_namestore_service.h | 37 | ||||
-rw-r--r-- | src/namestore/gnunet-service-namestore.c | 294 | ||||
-rw-r--r-- | src/namestore/namestore.conf.in | 6 | ||||
-rw-r--r-- | src/namestore/namestore.h | 43 | ||||
-rw-r--r-- | src/namestore/namestore_api.c | 105 | ||||
-rw-r--r-- | src/namestore/perf_namestore_api_postgres.conf | 1 | ||||
-rw-r--r-- | src/namestore/perf_namestore_api_sqlite.conf | 1 | ||||
-rw-r--r-- | src/namestore/plugin_namestore_sqlite.c | 1 | ||||
-rw-r--r-- | src/namestore/plugin_rest_namestore.c | 108 | ||||
-rw-r--r-- | src/namestore/test_plugin_namestore_postgres.conf | 1 | ||||
-rw-r--r-- | src/namestore/test_plugin_namestore_sqlite.conf | 1 |
11 files changed, 440 insertions, 158 deletions
diff --git a/src/include/gnunet_namestore_service.h b/src/include/gnunet_namestore_service.h index dc6aeaa69..b795494af 100644 --- a/src/include/gnunet_namestore_service.h +++ b/src/include/gnunet_namestore_service.h | |||
@@ -148,6 +148,43 @@ GNUNET_NAMESTORE_records_store (struct GNUNET_NAMESTORE_Handle *h, | |||
148 | void *cont_cls); | 148 | void *cont_cls); |
149 | 149 | ||
150 | /** | 150 | /** |
151 | * Store one or more record sets in the namestore. If any item is already present, | ||
152 | * it is replaced with the new record. Use an empty array to | ||
153 | * remove all records under the given name. | ||
154 | * | ||
155 | * The continuation is called after the records have been stored in the | ||
156 | * database. They may not yet have been commited. Monitors may be notified | ||
157 | * asynchronously (basically with a buffer when commited). | ||
158 | * However, if any monitor is consistently too slow to | ||
159 | * keep up with the changes, calling @a cont will be delayed until the | ||
160 | * monitors do keep up. | ||
161 | * Uncommited store requests within a transaction (GNUNET_NAMESTORE_transaction_begin) | ||
162 | * cause @a cont to be called immediately before the commit and before | ||
163 | * notification of monitors. | ||
164 | * | ||
165 | * @param h handle to the namestore | ||
166 | * @param pkey private key of the zone | ||
167 | * @param rd_set_count the number of record sets | ||
168 | * @param a_label an array of size @a rd_set_count of names for each record set | ||
169 | * @param a_rd_count an array of size @a rd_set_count containing the number of records in the corresponding 'rd' array | ||
170 | * @param a_rd an array of size @a rd_set_count of arrays of records with data to store | ||
171 | * @param cont continuation to call when done | ||
172 | * @param cont_cls closure for @a cont | ||
173 | * @return handle to abort the request | ||
174 | */ | ||
175 | |||
176 | struct GNUNET_NAMESTORE_QueueEntry * | ||
177 | GNUNET_NAMESTORE_records_store2 ( | ||
178 | struct GNUNET_NAMESTORE_Handle *h, | ||
179 | const struct GNUNET_IDENTITY_PrivateKey *pkey, | ||
180 | unsigned int rd_set_count, | ||
181 | const char **a_label, | ||
182 | unsigned int *a_rd_count, | ||
183 | const struct GNUNET_GNSRECORD_Data **a_rd, | ||
184 | GNUNET_NAMESTORE_ContinuationWithStatus cont, | ||
185 | void *cont_cls); | ||
186 | |||
187 | /** | ||
151 | * Store an item in the namestore. If the item is already present, | 188 | * Store an item in the namestore. If the item is already present, |
152 | * it is replaced with the new record. Use an empty array to | 189 | * it is replaced with the new record. Use an empty array to |
153 | * remove all records under the given name. | 190 | * remove all records under the given name. |
diff --git a/src/namestore/gnunet-service-namestore.c b/src/namestore/gnunet-service-namestore.c index b860d7a3c..ada2acb16 100644 --- a/src/namestore/gnunet-service-namestore.c +++ b/src/namestore/gnunet-service-namestore.c | |||
@@ -147,6 +147,11 @@ struct NamestoreClient | |||
147 | char *db_lib_name; | 147 | char *db_lib_name; |
148 | 148 | ||
149 | /** | 149 | /** |
150 | * GNUNET_YES if this nc has begun a transaction which is uncommited. | ||
151 | */ | ||
152 | int in_transaction; | ||
153 | |||
154 | /** | ||
150 | * Message queue for transmission to @e client | 155 | * Message queue for transmission to @e client |
151 | */ | 156 | */ |
152 | struct GNUNET_MQ_Handle *mq; | 157 | struct GNUNET_MQ_Handle *mq; |
@@ -308,10 +313,26 @@ struct StoreActivity | |||
308 | struct NamestoreClient *nc; | 313 | struct NamestoreClient *nc; |
309 | 314 | ||
310 | /** | 315 | /** |
311 | * Copy of the original store message (as data fields in @e rd will | 316 | * The request ID |
317 | */ | ||
318 | uint32_t rid; | ||
319 | |||
320 | /** | ||
321 | * Wheather or not this store action is already commited. | ||
322 | * The store activity will not be processed unless this field is GNUNET_YES | ||
323 | */ | ||
324 | int uncommited; | ||
325 | |||
326 | /** | ||
327 | * The zone private key | ||
328 | */ | ||
329 | struct GNUNET_IDENTITY_PrivateKey private_key; | ||
330 | |||
331 | /** | ||
332 | * Copy of the original record set (as data fields in @e rd will | ||
312 | * point into it!). | 333 | * point into it!). |
313 | */ | 334 | */ |
314 | const struct RecordStoreMessage *rsm; | 335 | const struct RecordSet *rs; |
315 | 336 | ||
316 | /** | 337 | /** |
317 | * Next zone monitor that still needs to be notified about this PUT. | 338 | * Next zone monitor that still needs to be notified about this PUT. |
@@ -879,7 +900,7 @@ send_lookup_response (struct NamestoreClient *nc, | |||
879 | * @param rid client's request ID | 900 | * @param rid client's request ID |
880 | */ | 901 | */ |
881 | static void | 902 | static void |
882 | send_store_response (struct NamestoreClient *nc, int res, const char*emsg, | 903 | send_store_response (struct NamestoreClient *nc, int res, const char *emsg, |
883 | uint32_t rid) | 904 | uint32_t rid) |
884 | { | 905 | { |
885 | struct GNUNET_MQ_Envelope *env; | 906 | struct GNUNET_MQ_Envelope *env; |
@@ -1105,7 +1126,7 @@ warn_monitor_slow (void *cls) | |||
1105 | static void | 1126 | static void |
1106 | continue_store_activity (struct StoreActivity *sa) | 1127 | continue_store_activity (struct StoreActivity *sa) |
1107 | { | 1128 | { |
1108 | const struct RecordStoreMessage *rp_msg = sa->rsm; | 1129 | const struct RecordSet *rd_set = sa->rs; |
1109 | unsigned int rd_count; | 1130 | unsigned int rd_count; |
1110 | size_t name_len; | 1131 | size_t name_len; |
1111 | size_t rd_ser_len; | 1132 | size_t rd_ser_len; |
@@ -1113,11 +1134,20 @@ continue_store_activity (struct StoreActivity *sa) | |||
1113 | const char *name_tmp; | 1134 | const char *name_tmp; |
1114 | const char *rd_ser; | 1135 | const char *rd_ser; |
1115 | 1136 | ||
1116 | rid = ntohl (rp_msg->gns_header.r_id); | 1137 | // If we are in a transaction, do not notify monitors or update |
1117 | name_len = ntohs (rp_msg->name_len); | 1138 | // cached. This will be done when we are commiting. |
1118 | rd_count = ntohs (rp_msg->rd_count); | 1139 | if (GNUNET_YES == sa->uncommited) |
1119 | rd_ser_len = ntohs (rp_msg->rd_len); | 1140 | { |
1120 | name_tmp = (const char *) &rp_msg[1]; | 1141 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1142 | "Transaction not yet committed, delaying monitor and cache updates\n"); | ||
1143 | send_store_response (sa->nc, GNUNET_YES, NULL, sa->rid); | ||
1144 | GNUNET_SERVICE_client_continue (sa->nc->client); | ||
1145 | return; | ||
1146 | } | ||
1147 | name_len = ntohs (rd_set->name_len); | ||
1148 | rd_count = ntohs (rd_set->rd_count); | ||
1149 | rd_ser_len = ntohs (rd_set->rd_len); | ||
1150 | name_tmp = (const char *) &rd_set[1]; | ||
1121 | rd_ser = &name_tmp[name_len]; | 1151 | rd_ser = &name_tmp[name_len]; |
1122 | { | 1152 | { |
1123 | struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)]; | 1153 | struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)]; |
@@ -1129,7 +1159,7 @@ continue_store_activity (struct StoreActivity *sa) | |||
1129 | 1159 | ||
1130 | for (struct ZoneMonitor *zm = sa->zm_pos; NULL != zm; zm = sa->zm_pos) | 1160 | for (struct ZoneMonitor *zm = sa->zm_pos; NULL != zm; zm = sa->zm_pos) |
1131 | { | 1161 | { |
1132 | if ((0 != GNUNET_memcmp (&rp_msg->private_key, &zm->zone)) && | 1162 | if ((0 != GNUNET_memcmp (&sa->private_key, &zm->zone)) && |
1133 | (0 != GNUNET_memcmp (&zm->zone, &zero))) | 1163 | (0 != GNUNET_memcmp (&zm->zone, &zero))) |
1134 | { | 1164 | { |
1135 | sa->zm_pos = zm->next; /* not interesting to this monitor */ | 1165 | sa->zm_pos = zm->next; /* not interesting to this monitor */ |
@@ -1153,7 +1183,7 @@ continue_store_activity (struct StoreActivity *sa) | |||
1153 | zm->limit--; | 1183 | zm->limit--; |
1154 | send_lookup_response_with_filter (zm->nc, | 1184 | send_lookup_response_with_filter (zm->nc, |
1155 | 0, | 1185 | 0, |
1156 | &rp_msg->private_key, | 1186 | &sa->private_key, |
1157 | sa->conv_name, | 1187 | sa->conv_name, |
1158 | rd_count, | 1188 | rd_count, |
1159 | rd, | 1189 | rd, |
@@ -1163,8 +1193,8 @@ continue_store_activity (struct StoreActivity *sa) | |||
1163 | /* great, done with the monitors, unpack (again) for refresh_block operation */ | 1193 | /* great, done with the monitors, unpack (again) for refresh_block operation */ |
1164 | refresh_block (sa->nc, | 1194 | refresh_block (sa->nc, |
1165 | NULL, | 1195 | NULL, |
1166 | rid, | 1196 | sa->rid, |
1167 | &rp_msg->private_key, | 1197 | &sa->private_key, |
1168 | sa->conv_name, | 1198 | sa->conv_name, |
1169 | rd_count, | 1199 | rd_count, |
1170 | rd); | 1200 | rd); |
@@ -1240,7 +1270,8 @@ client_disconnect_cb (void *cls, | |||
1240 | for (cop = cop_head; NULL != cop; cop = cop->next) | 1270 | for (cop = cop_head; NULL != cop; cop = cop->next) |
1241 | if (nc == cop->nc) | 1271 | if (nc == cop->nc) |
1242 | cop->nc = NULL; | 1272 | cop->nc = NULL; |
1243 | GNUNET_break (NULL == GNUNET_PLUGIN_unload (nc->db_lib_name, nc->GSN_database)); | 1273 | GNUNET_break (NULL == GNUNET_PLUGIN_unload (nc->db_lib_name, |
1274 | nc->GSN_database)); | ||
1244 | GNUNET_free (nc->db_lib_name); | 1275 | GNUNET_free (nc->db_lib_name); |
1245 | GNUNET_free (nc); | 1276 | GNUNET_free (nc); |
1246 | } | 1277 | } |
@@ -1549,29 +1580,16 @@ handle_record_lookup (void *cls, const struct LabelLookupMessage *ll_msg) | |||
1549 | static int | 1580 | static int |
1550 | check_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | 1581 | check_record_store (void *cls, const struct RecordStoreMessage *rp_msg) |
1551 | { | 1582 | { |
1552 | size_t name_len; | ||
1553 | size_t msg_size; | 1583 | size_t msg_size; |
1554 | size_t msg_size_exp; | 1584 | size_t min_size_exp; |
1555 | size_t rd_ser_len; | 1585 | size_t rd_set_count; |
1556 | const char *name_tmp; | ||
1557 | 1586 | ||
1558 | (void) cls; | 1587 | (void) cls; |
1559 | name_len = ntohs (rp_msg->name_len); | ||
1560 | msg_size = ntohs (rp_msg->gns_header.header.size); | 1588 | msg_size = ntohs (rp_msg->gns_header.header.size); |
1561 | rd_ser_len = ntohs (rp_msg->rd_len); | 1589 | rd_set_count = ntohs (rp_msg->rd_set_count); |
1562 | msg_size_exp = sizeof(struct RecordStoreMessage) + name_len + rd_ser_len; | 1590 | min_size_exp = sizeof(struct RecordStoreMessage) + sizeof (struct RecordSet) |
1563 | if (msg_size != msg_size_exp) | 1591 | * rd_set_count; |
1564 | { | 1592 | if (msg_size < min_size_exp) |
1565 | GNUNET_break (0); | ||
1566 | return GNUNET_SYSERR; | ||
1567 | } | ||
1568 | if ((0 == name_len) || (name_len > MAX_NAME_LEN)) | ||
1569 | { | ||
1570 | GNUNET_break (0); | ||
1571 | return GNUNET_SYSERR; | ||
1572 | } | ||
1573 | name_tmp = (const char *) &rp_msg[1]; | ||
1574 | if ('\0' != name_tmp[name_len - 1]) | ||
1575 | { | 1593 | { |
1576 | GNUNET_break (0); | 1594 | GNUNET_break (0); |
1577 | return GNUNET_SYSERR; | 1595 | return GNUNET_SYSERR; |
@@ -1620,77 +1638,61 @@ get_block_exp_existing (void *cls, | |||
1620 | } | 1638 | } |
1621 | } | 1639 | } |
1622 | 1640 | ||
1623 | 1641 | static enum GNUNET_GenericReturnValue | |
1624 | /** | 1642 | store_record_set (struct NamestoreClient *nc, |
1625 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message | 1643 | const struct GNUNET_IDENTITY_PrivateKey *private_key, |
1626 | * | 1644 | const struct RecordSet *rd_set, |
1627 | * @param cls client sending the message | 1645 | char **conv_name, |
1628 | * @param rp_msg message of type `struct RecordStoreMessage` | 1646 | ssize_t *len, |
1629 | */ | 1647 | char **emsg) |
1630 | static void | ||
1631 | handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | ||
1632 | { | 1648 | { |
1633 | struct NamestoreClient *nc = cls; | ||
1634 | size_t name_len; | 1649 | size_t name_len; |
1635 | size_t rd_ser_len; | 1650 | size_t rd_ser_len; |
1636 | uint32_t rid; | ||
1637 | const char *name_tmp; | 1651 | const char *name_tmp; |
1638 | char *conv_name; | ||
1639 | const char *rd_ser; | 1652 | const char *rd_ser; |
1640 | unsigned int rd_count; | 1653 | unsigned int rd_count; |
1641 | int res; | 1654 | int res; |
1642 | struct StoreActivity *sa; | ||
1643 | struct GNUNET_TIME_Absolute existing_block_exp; | 1655 | struct GNUNET_TIME_Absolute existing_block_exp; |
1644 | struct GNUNET_TIME_Absolute new_block_exp; | 1656 | struct GNUNET_TIME_Absolute new_block_exp; |
1645 | 1657 | *len = sizeof (struct RecordSet); | |
1646 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1658 | |
1647 | "Received NAMESTORE_RECORD_STORE message\n"); | 1659 | name_len = ntohs (rd_set->name_len); |
1648 | existing_block_exp = GNUNET_TIME_UNIT_ZERO_ABS; | 1660 | *len += name_len; |
1649 | new_block_exp = GNUNET_TIME_UNIT_ZERO_ABS; | 1661 | rd_count = ntohs (rd_set->rd_count); |
1650 | rid = ntohl (rp_msg->gns_header.r_id); | 1662 | rd_ser_len = ntohs (rd_set->rd_len); |
1651 | name_len = ntohs (rp_msg->name_len); | 1663 | *len += rd_ser_len; |
1652 | rd_count = ntohs (rp_msg->rd_count); | 1664 | name_tmp = (const char *) &rd_set[1]; |
1653 | rd_ser_len = ntohs (rp_msg->rd_len); | ||
1654 | name_tmp = (const char *) &rp_msg[1]; | ||
1655 | rd_ser = &name_tmp[name_len]; | 1665 | rd_ser = &name_tmp[name_len]; |
1656 | { | 1666 | { |
1657 | struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)]; | 1667 | struct GNUNET_GNSRECORD_Data rd[GNUNET_NZL (rd_count)]; |
1658 | char *emsg; | ||
1659 | 1668 | ||
1660 | /* Extracting and converting private key */ | 1669 | /* Extracting and converting private key */ |
1661 | conv_name = GNUNET_GNSRECORD_string_normalize (name_tmp); | 1670 | *conv_name = GNUNET_GNSRECORD_string_normalize (name_tmp); |
1662 | if (NULL == conv_name) | 1671 | if (NULL == *conv_name) |
1663 | { | 1672 | { |
1664 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 1673 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
1665 | "Error normalizing name `%s'\n", | 1674 | "Error normalizing name `%s'\n", |
1666 | name_tmp); | 1675 | name_tmp); |
1667 | send_store_response (nc, GNUNET_SYSERR, _ ("Error normalizing name."), | 1676 | *emsg = GNUNET_strdup (_ ("Error normalizing name.")); |
1668 | rid); | 1677 | return GNUNET_SYSERR; |
1669 | GNUNET_SERVICE_client_continue (nc->client); | ||
1670 | return; | ||
1671 | } | 1678 | } |
1672 | 1679 | ||
1673 | /* Check name for validity */ | 1680 | /* Check name for validity */ |
1674 | if (GNUNET_OK != GNUNET_GNSRECORD_label_check (conv_name, &emsg)) | 1681 | if (GNUNET_OK != GNUNET_GNSRECORD_label_check (*conv_name, emsg)) |
1675 | { | 1682 | { |
1676 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 1683 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, |
1677 | "Label invalid: `%s'\n", | 1684 | "Label invalid: `%s'\n", |
1678 | emsg); | 1685 | *emsg); |
1679 | send_store_response (nc, GNUNET_SYSERR, emsg, rid); | 1686 | GNUNET_free (*conv_name); |
1680 | GNUNET_free (emsg); | 1687 | return -1; |
1681 | GNUNET_free (conv_name); | ||
1682 | GNUNET_SERVICE_client_continue (nc->client); | ||
1683 | return; | ||
1684 | } | 1688 | } |
1685 | 1689 | ||
1686 | if (GNUNET_OK != | 1690 | if (GNUNET_OK != |
1687 | GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, rd)) | 1691 | GNUNET_GNSRECORD_records_deserialize (rd_ser_len, rd_ser, rd_count, rd)) |
1688 | { | 1692 | { |
1689 | send_store_response (nc, GNUNET_SYSERR, | 1693 | *emsg = GNUNET_strdup (_ ("Error deserializing records.")); |
1690 | _ ("Error deserializing records."), rid); | 1694 | GNUNET_free (*conv_name); |
1691 | GNUNET_free (conv_name); | 1695 | return GNUNET_SYSERR; |
1692 | GNUNET_SERVICE_client_continue (nc->client); | ||
1693 | return; | ||
1694 | } | 1696 | } |
1695 | 1697 | ||
1696 | GNUNET_STATISTICS_update (statistics, | 1698 | GNUNET_STATISTICS_update (statistics, |
@@ -1700,10 +1702,10 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | |||
1700 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1702 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1701 | "Creating %u records for name `%s'\n", | 1703 | "Creating %u records for name `%s'\n", |
1702 | (unsigned int) rd_count, | 1704 | (unsigned int) rd_count, |
1703 | conv_name); | 1705 | *conv_name); |
1704 | if ((GNUNET_NO == nc->GSN_database->lookup_records (nc->GSN_database->cls, | 1706 | if ((GNUNET_NO == nc->GSN_database->lookup_records (nc->GSN_database->cls, |
1705 | &rp_msg->private_key, | 1707 | private_key, |
1706 | conv_name, | 1708 | *conv_name, |
1707 | &get_block_exp_existing, | 1709 | &get_block_exp_existing, |
1708 | &existing_block_exp)) && | 1710 | &existing_block_exp)) && |
1709 | (rd_count == 0)) | 1711 | (rd_count == 0)) |
@@ -1711,7 +1713,7 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | |||
1711 | /* This name does not exist, so cannot be removed */ | 1713 | /* This name does not exist, so cannot be removed */ |
1712 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | 1714 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, |
1713 | "Name `%s' does not exist, no deletion required\n", | 1715 | "Name `%s' does not exist, no deletion required\n", |
1714 | conv_name); | 1716 | *conv_name); |
1715 | res = GNUNET_NO; | 1717 | res = GNUNET_NO; |
1716 | } | 1718 | } |
1717 | else | 1719 | else |
@@ -1728,7 +1730,6 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | |||
1728 | struct GNUNET_GNSRECORD_Data rd_nf[GNUNET_NZL (rd_count) + 1]; | 1730 | struct GNUNET_GNSRECORD_Data rd_nf[GNUNET_NZL (rd_count) + 1]; |
1729 | unsigned int rd_clean_off; | 1731 | unsigned int rd_clean_off; |
1730 | unsigned int rd_nf_count; | 1732 | unsigned int rd_nf_count; |
1731 | char *emsg; | ||
1732 | int have_nick; | 1733 | int have_nick; |
1733 | 1734 | ||
1734 | rd_clean_off = 0; | 1735 | rd_clean_off = 0; |
@@ -1737,35 +1738,34 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | |||
1737 | { | 1738 | { |
1738 | rd_clean[rd_clean_off] = rd[i]; | 1739 | rd_clean[rd_clean_off] = rd[i]; |
1739 | 1740 | ||
1740 | if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) || | 1741 | if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, *conv_name)) || |
1741 | (GNUNET_GNSRECORD_TYPE_NICK != rd[i].record_type)) | 1742 | (GNUNET_GNSRECORD_TYPE_NICK != rd[i].record_type)) |
1742 | rd_clean_off++; | 1743 | rd_clean_off++; |
1743 | 1744 | ||
1744 | if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) && | 1745 | if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, *conv_name)) && |
1745 | (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type)) | 1746 | (GNUNET_GNSRECORD_TYPE_NICK == rd[i].record_type)) |
1746 | { | 1747 | { |
1747 | cache_nick (&rp_msg->private_key, &rd[i]); | 1748 | // FIXME: In case this is an uncommited transaction, |
1749 | // we should not do this here. Can we do this in the store activity? | ||
1750 | cache_nick (private_key, &rd[i]); | ||
1748 | have_nick = GNUNET_YES; | 1751 | have_nick = GNUNET_YES; |
1749 | } | 1752 | } |
1750 | } | 1753 | } |
1751 | if (GNUNET_OK != | 1754 | if (GNUNET_OK != |
1752 | GNUNET_GNSRECORD_normalize_record_set (conv_name, | 1755 | GNUNET_GNSRECORD_normalize_record_set (*conv_name, |
1753 | rd_clean, | 1756 | rd_clean, |
1754 | rd_clean_off, | 1757 | rd_clean_off, |
1755 | rd_nf, | 1758 | rd_nf, |
1756 | &rd_nf_count, | 1759 | &rd_nf_count, |
1757 | &new_block_exp, | 1760 | &new_block_exp, |
1758 | GNUNET_GNSRECORD_FILTER_NONE, | 1761 | GNUNET_GNSRECORD_FILTER_NONE, |
1759 | &emsg)) | 1762 | emsg)) |
1760 | { | 1763 | { |
1761 | send_store_response (nc, GNUNET_SYSERR, emsg, rid); | 1764 | GNUNET_free (*conv_name); |
1762 | GNUNET_free (emsg); | 1765 | return GNUNET_SYSERR; |
1763 | GNUNET_SERVICE_client_continue (nc->client); | ||
1764 | GNUNET_free (conv_name); | ||
1765 | return; | ||
1766 | } | 1766 | } |
1767 | /* | 1767 | /* |
1768 | * If existing_block_exp is 0, then there was not record set | 1768 | * If existing_block_exp is 0, then there was no record set |
1769 | * and no tombstone. | 1769 | * and no tombstone. |
1770 | * Otherwise, if the existing block expiration is after the | 1770 | * Otherwise, if the existing block expiration is after the |
1771 | * new block expiration would be, we need to add a tombstone | 1771 | * new block expiration would be, we need to add a tombstone |
@@ -1781,36 +1781,91 @@ handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | |||
1781 | rd_nf[rd_nf_count].flags = GNUNET_GNSRECORD_RF_PRIVATE; | 1781 | rd_nf[rd_nf_count].flags = GNUNET_GNSRECORD_RF_PRIVATE; |
1782 | rd_nf_count++; | 1782 | rd_nf_count++; |
1783 | } | 1783 | } |
1784 | if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, conv_name)) && | 1784 | if ((0 == strcmp (GNUNET_GNS_EMPTY_LABEL_AT, *conv_name)) && |
1785 | (GNUNET_NO == have_nick)) | 1785 | (GNUNET_NO == have_nick)) |
1786 | { | 1786 | { |
1787 | /* remove nick record from cache, in case we have one there */ | 1787 | /* remove nick record from cache, in case we have one there */ |
1788 | cache_nick (&rp_msg->private_key, NULL); | 1788 | // FIXME: In case this is an uncommited transaction, |
1789 | // we should not do this here. Can we do this in the store activity? | ||
1790 | cache_nick (private_key, NULL); | ||
1789 | } | 1791 | } |
1790 | res = nc->GSN_database->store_records (nc->GSN_database->cls, | 1792 | res = nc->GSN_database->store_records (nc->GSN_database->cls, |
1791 | &rp_msg->private_key, | 1793 | private_key, |
1792 | conv_name, | 1794 | *conv_name, |
1793 | rd_nf_count, | 1795 | rd_nf_count, |
1794 | rd_nf); | 1796 | rd_nf); |
1795 | } | 1797 | } |
1796 | 1798 | ||
1797 | if (GNUNET_OK != res) | 1799 | if (GNUNET_SYSERR == res) |
1798 | { | 1800 | { |
1799 | /* store not successful, no need to tell monitors */ | 1801 | /* store not successful, no need to tell monitors */ |
1800 | send_store_response (nc, res, _ ("Store failed"), rid); | 1802 | *emsg = GNUNET_strdup (_ ("Store failed")); |
1803 | GNUNET_free (*conv_name); | ||
1804 | return GNUNET_SYSERR; | ||
1805 | } | ||
1806 | } | ||
1807 | return res; | ||
1808 | } | ||
1809 | |||
1810 | /** | ||
1811 | * Handles a #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE message | ||
1812 | * | ||
1813 | * @param cls client sending the message | ||
1814 | * @param rp_msg message of type `struct RecordStoreMessage` | ||
1815 | */ | ||
1816 | static void | ||
1817 | handle_record_store (void *cls, const struct RecordStoreMessage *rp_msg) | ||
1818 | { | ||
1819 | struct NamestoreClient *nc = cls; | ||
1820 | size_t name_len; | ||
1821 | size_t rd_ser_len; | ||
1822 | uint32_t rid; | ||
1823 | uint16_t rd_set_count; | ||
1824 | const char *name_tmp; | ||
1825 | char *conv_name; | ||
1826 | char *emsg = NULL; | ||
1827 | const char *buf; | ||
1828 | const char *rd_ser; | ||
1829 | unsigned int rd_count; | ||
1830 | ssize_t read; | ||
1831 | struct StoreActivity *sa; | ||
1832 | struct RecordSet *rs; | ||
1833 | struct GNUNET_TIME_Absolute existing_block_exp; | ||
1834 | struct GNUNET_TIME_Absolute new_block_exp; | ||
1835 | enum GNUNET_GenericReturnValue res; | ||
1836 | |||
1837 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1838 | "Received NAMESTORE_RECORD_STORE message\n"); | ||
1839 | existing_block_exp = GNUNET_TIME_UNIT_ZERO_ABS; | ||
1840 | new_block_exp = GNUNET_TIME_UNIT_ZERO_ABS; | ||
1841 | rid = ntohl (rp_msg->gns_header.r_id); | ||
1842 | rd_set_count = ntohs (rp_msg->rd_set_count); | ||
1843 | buf = (const char *) &rp_msg[1]; | ||
1844 | for (int i = 0; i < rd_set_count; i++) | ||
1845 | { | ||
1846 | rs = (struct RecordSet *) buf; | ||
1847 | res = store_record_set (nc, &rp_msg->private_key, | ||
1848 | rs, &conv_name, &read, &emsg); | ||
1849 | if (GNUNET_OK != res) | ||
1850 | { | ||
1851 | send_store_response (nc, res, emsg, | ||
1852 | rid); | ||
1853 | GNUNET_free (emsg); | ||
1801 | GNUNET_SERVICE_client_continue (nc->client); | 1854 | GNUNET_SERVICE_client_continue (nc->client); |
1802 | GNUNET_free (conv_name); | ||
1803 | return; | 1855 | return; |
1804 | } | 1856 | } |
1805 | sa = GNUNET_malloc (sizeof(struct StoreActivity) | 1857 | sa = GNUNET_malloc (sizeof(struct StoreActivity) + read); |
1806 | + ntohs (rp_msg->gns_header.header.size)); | ||
1807 | GNUNET_CONTAINER_DLL_insert (sa_head, sa_tail, sa); | 1858 | GNUNET_CONTAINER_DLL_insert (sa_head, sa_tail, sa); |
1808 | sa->nc = nc; | 1859 | sa->nc = nc; |
1809 | sa->rsm = (const struct RecordStoreMessage *) &sa[1]; | 1860 | sa->rs = (const struct RecordSet *) &sa[1]; |
1810 | GNUNET_memcpy (&sa[1], rp_msg, ntohs (rp_msg->gns_header.header.size)); | 1861 | GNUNET_memcpy (&sa[1], rs, read); |
1862 | sa->rid = rid; | ||
1863 | sa->private_key = rp_msg->private_key; | ||
1811 | sa->zm_pos = monitor_head; | 1864 | sa->zm_pos = monitor_head; |
1812 | sa->conv_name = conv_name; | 1865 | sa->conv_name = conv_name; |
1866 | sa->uncommited = nc->in_transaction; | ||
1813 | continue_store_activity (sa); | 1867 | continue_store_activity (sa); |
1868 | buf += read; | ||
1814 | } | 1869 | } |
1815 | } | 1870 | } |
1816 | 1871 | ||
@@ -1826,6 +1881,8 @@ handle_tx_control (void *cls, const struct TxControlMessage *tx_msg) | |||
1826 | struct NamestoreClient *nc = cls; | 1881 | struct NamestoreClient *nc = cls; |
1827 | struct TxControlResultMessage *txr_msg; | 1882 | struct TxControlResultMessage *txr_msg; |
1828 | struct GNUNET_MQ_Envelope *env; | 1883 | struct GNUNET_MQ_Envelope *env; |
1884 | struct StoreActivity *sa = sa_head; | ||
1885 | struct StoreActivity *sn; | ||
1829 | enum GNUNET_GenericReturnValue ret; | 1886 | enum GNUNET_GenericReturnValue ret; |
1830 | char *emsg = NULL; | 1887 | char *emsg = NULL; |
1831 | char *err_tmp; | 1888 | char *err_tmp; |
@@ -1836,14 +1893,47 @@ handle_tx_control (void *cls, const struct TxControlMessage *tx_msg) | |||
1836 | case GNUNET_NAMESTORE_TX_BEGIN: | 1893 | case GNUNET_NAMESTORE_TX_BEGIN: |
1837 | ret = nc->GSN_database->transaction_begin (nc->GSN_database->cls, | 1894 | ret = nc->GSN_database->transaction_begin (nc->GSN_database->cls, |
1838 | &emsg); | 1895 | &emsg); |
1896 | nc->in_transaction = GNUNET_YES; | ||
1839 | break; | 1897 | break; |
1840 | case GNUNET_NAMESTORE_TX_COMMIT: | 1898 | case GNUNET_NAMESTORE_TX_COMMIT: |
1841 | ret = nc->GSN_database->transaction_commit (nc->GSN_database->cls, | 1899 | ret = nc->GSN_database->transaction_commit (nc->GSN_database->cls, |
1842 | &emsg); | 1900 | &emsg); |
1901 | if (GNUNET_SYSERR != ret) | ||
1902 | { | ||
1903 | nc->in_transaction = GNUNET_NO; | ||
1904 | while (NULL != sa) | ||
1905 | { | ||
1906 | if ((nc != sa->nc) || | ||
1907 | (GNUNET_NO == sa->uncommited)) | ||
1908 | { | ||
1909 | sa = sa->next; | ||
1910 | continue; | ||
1911 | } | ||
1912 | sa->uncommited = GNUNET_NO; | ||
1913 | continue_store_activity (sa); | ||
1914 | sa = sa->next; | ||
1915 | } | ||
1916 | } | ||
1843 | break; | 1917 | break; |
1844 | case GNUNET_NAMESTORE_TX_ROLLBACK: | 1918 | case GNUNET_NAMESTORE_TX_ROLLBACK: |
1845 | ret = nc->GSN_database->transaction_rollback (nc->GSN_database->cls, | 1919 | ret = nc->GSN_database->transaction_rollback (nc->GSN_database->cls, |
1846 | &emsg); | 1920 | &emsg); |
1921 | if (GNUNET_SYSERR != ret) | ||
1922 | { | ||
1923 | nc->in_transaction = GNUNET_NO; | ||
1924 | while (NULL != sa) | ||
1925 | { | ||
1926 | if ((nc != sa->nc) || | ||
1927 | (GNUNET_NO == sa->uncommited)) | ||
1928 | { | ||
1929 | sa = sa->next; | ||
1930 | continue; | ||
1931 | } | ||
1932 | sn = sa->next; | ||
1933 | free_store_activity (sa); | ||
1934 | sa = sn; | ||
1935 | } | ||
1936 | } | ||
1847 | break; | 1937 | break; |
1848 | default: | 1938 | default: |
1849 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 1939 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
diff --git a/src/namestore/namestore.conf.in b/src/namestore/namestore.conf.in index a9c928c66..fe7d4002c 100644 --- a/src/namestore/namestore.conf.in +++ b/src/namestore/namestore.conf.in | |||
@@ -21,12 +21,9 @@ CACHE_KEYS = YES | |||
21 | 21 | ||
22 | 22 | ||
23 | [namestore-sqlite] | 23 | [namestore-sqlite] |
24 | INIT_ON_CONNECT = YES | ||
24 | FILENAME = $GNUNET_DATA_HOME/namestore/sqlite.db | 25 | FILENAME = $GNUNET_DATA_HOME/namestore/sqlite.db |
25 | 26 | ||
26 | [namestore-heap] | ||
27 | FILENAME = $GNUNET_DATA_HOME/namestore/heap.db | ||
28 | |||
29 | |||
30 | [namestore-postgres] | 27 | [namestore-postgres] |
31 | # How to connect to the database | 28 | # How to connect to the database |
32 | CONFIG = postgres:///gnunet | 29 | CONFIG = postgres:///gnunet |
@@ -34,6 +31,7 @@ CONFIG = postgres:///gnunet | |||
34 | TEMPORARY_TABLE = NO | 31 | TEMPORARY_TABLE = NO |
35 | # Use asynchronous commit (SET synchronous_commit TO OFF). | 32 | # Use asynchronous commit (SET synchronous_commit TO OFF). |
36 | ASYNC_COMMIT = NO | 33 | ASYNC_COMMIT = NO |
34 | INIT_ON_CONNECT = YES | ||
37 | 35 | ||
38 | [uri] | 36 | [uri] |
39 | gns = gnunet-namestore -e 1a -u | 37 | gns = gnunet-namestore -e 1a -u |
diff --git a/src/namestore/namestore.h b/src/namestore/namestore.h index ad02ffb48..d7b6fd13e 100644 --- a/src/namestore/namestore.h +++ b/src/namestore/namestore.h | |||
@@ -51,23 +51,9 @@ struct GNUNET_NAMESTORE_Header | |||
51 | uint32_t r_id GNUNET_PACKED; | 51 | uint32_t r_id GNUNET_PACKED; |
52 | }; | 52 | }; |
53 | 53 | ||
54 | 54 | struct RecordSet | |
55 | /** | ||
56 | * Store a record to the namestore (as authority). | ||
57 | */ | ||
58 | struct RecordStoreMessage | ||
59 | { | 55 | { |
60 | /** | 56 | /** |
61 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE | ||
62 | */ | ||
63 | struct GNUNET_NAMESTORE_Header gns_header; | ||
64 | |||
65 | /** | ||
66 | * Expiration time | ||
67 | */ | ||
68 | struct GNUNET_TIME_AbsoluteNBO expire; | ||
69 | |||
70 | /** | ||
71 | * Name length | 57 | * Name length |
72 | */ | 58 | */ |
73 | uint16_t name_len GNUNET_PACKED; | 59 | uint16_t name_len GNUNET_PACKED; |
@@ -87,14 +73,35 @@ struct RecordStoreMessage | |||
87 | */ | 73 | */ |
88 | uint16_t reserved GNUNET_PACKED; | 74 | uint16_t reserved GNUNET_PACKED; |
89 | 75 | ||
76 | |||
77 | /* followed by: | ||
78 | * name with length name_len | ||
79 | * serialized record data with rd_count records | ||
80 | */ | ||
81 | }; | ||
82 | |||
83 | /** | ||
84 | * Store a record to the namestore (as authority). | ||
85 | */ | ||
86 | struct RecordStoreMessage | ||
87 | { | ||
88 | /** | ||
89 | * Type will be #GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE | ||
90 | */ | ||
91 | struct GNUNET_NAMESTORE_Header gns_header; | ||
92 | |||
90 | /** | 93 | /** |
91 | * The private key of the authority. | 94 | * The private key of the authority. |
92 | */ | 95 | */ |
93 | struct GNUNET_IDENTITY_PrivateKey private_key; | 96 | struct GNUNET_IDENTITY_PrivateKey private_key; |
94 | 97 | ||
95 | /* followed by: | 98 | /** |
96 | * name with length name_len | 99 | * Number of record sets |
97 | * serialized record data with rd_count records | 100 | */ |
101 | uint16_t rd_set_count; | ||
102 | |||
103 | /** | ||
104 | * Followed by rd_set_count RecordSets | ||
98 | */ | 105 | */ |
99 | }; | 106 | }; |
100 | 107 | ||
diff --git a/src/namestore/namestore_api.c b/src/namestore/namestore_api.c index 51ee25acf..f9ed2b620 100644 --- a/src/namestore/namestore_api.c +++ b/src/namestore/namestore_api.c | |||
@@ -1095,32 +1095,60 @@ GNUNET_NAMESTORE_records_store ( | |||
1095 | GNUNET_NAMESTORE_ContinuationWithStatus cont, | 1095 | GNUNET_NAMESTORE_ContinuationWithStatus cont, |
1096 | void *cont_cls) | 1096 | void *cont_cls) |
1097 | { | 1097 | { |
1098 | return GNUNET_NAMESTORE_records_store2 (h, pkey, 1, &label, &rd_count, &rd, | ||
1099 | cont, cont_cls); | ||
1100 | } | ||
1101 | |||
1102 | struct GNUNET_NAMESTORE_QueueEntry * | ||
1103 | GNUNET_NAMESTORE_records_store2 ( | ||
1104 | struct GNUNET_NAMESTORE_Handle *h, | ||
1105 | const struct GNUNET_IDENTITY_PrivateKey *pkey, | ||
1106 | unsigned int rd_set_count, | ||
1107 | const char **a_label, | ||
1108 | unsigned int *a_rd_count, | ||
1109 | const struct GNUNET_GNSRECORD_Data **a_rd, | ||
1110 | GNUNET_NAMESTORE_ContinuationWithStatus cont, | ||
1111 | void *cont_cls) | ||
1112 | { | ||
1098 | struct GNUNET_NAMESTORE_QueueEntry *qe; | 1113 | struct GNUNET_NAMESTORE_QueueEntry *qe; |
1099 | struct GNUNET_MQ_Envelope *env; | 1114 | struct GNUNET_MQ_Envelope *env; |
1115 | const char *label; | ||
1116 | unsigned int rd_count; | ||
1117 | const struct GNUNET_GNSRECORD_Data *rd; | ||
1100 | char *name_tmp; | 1118 | char *name_tmp; |
1101 | char *rd_ser; | 1119 | char *rd_ser; |
1102 | ssize_t rd_ser_len; | 1120 | ssize_t rd_ser_len[rd_set_count]; |
1103 | size_t name_len; | 1121 | size_t name_len; |
1104 | uint32_t rid; | 1122 | uint32_t rid; |
1105 | struct RecordStoreMessage *msg; | 1123 | struct RecordStoreMessage *msg; |
1124 | struct RecordSet *rd_set; | ||
1106 | ssize_t sret; | 1125 | ssize_t sret; |
1126 | int i; | ||
1127 | size_t rd_set_len = 0; | ||
1107 | 1128 | ||
1108 | name_len = strlen (label) + 1; | 1129 | for (i = 0; i < rd_set_count; i++) |
1109 | if (name_len > MAX_NAME_LEN) | ||
1110 | { | 1130 | { |
1111 | GNUNET_break (0); | 1131 | label = a_label[i]; |
1112 | return NULL; | 1132 | rd_count = a_rd_count[i]; |
1113 | } | 1133 | rd = a_rd[i]; |
1114 | rd_ser_len = GNUNET_GNSRECORD_records_get_size (rd_count, rd); | 1134 | name_len = strlen (label) + 1; |
1115 | if (rd_ser_len < 0) | 1135 | if (name_len > MAX_NAME_LEN) |
1116 | { | 1136 | { |
1117 | GNUNET_break (0); | 1137 | GNUNET_break (0); |
1118 | return NULL; | 1138 | return NULL; |
1119 | } | 1139 | } |
1120 | if (rd_ser_len > UINT16_MAX) | 1140 | rd_ser_len[i] = GNUNET_GNSRECORD_records_get_size (rd_count, rd); |
1121 | { | 1141 | if (rd_ser_len[i] < 0) |
1122 | GNUNET_break (0); | 1142 | { |
1123 | return NULL; | 1143 | GNUNET_break (0); |
1144 | return NULL; | ||
1145 | } | ||
1146 | if (rd_ser_len[i] > UINT16_MAX) | ||
1147 | { | ||
1148 | GNUNET_break (0); | ||
1149 | return NULL; | ||
1150 | } | ||
1151 | rd_set_len = sizeof (struct RecordSet) + name_len + rd_ser_len[i]; | ||
1124 | } | 1152 | } |
1125 | rid = get_op_id (h); | 1153 | rid = get_op_id (h); |
1126 | qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry); | 1154 | qe = GNUNET_new (struct GNUNET_NAMESTORE_QueueEntry); |
@@ -1132,30 +1160,38 @@ GNUNET_NAMESTORE_records_store ( | |||
1132 | 1160 | ||
1133 | /* setup msg */ | 1161 | /* setup msg */ |
1134 | env = GNUNET_MQ_msg_extra (msg, | 1162 | env = GNUNET_MQ_msg_extra (msg, |
1135 | name_len + rd_ser_len, | 1163 | rd_set_len, |
1136 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE); | 1164 | GNUNET_MESSAGE_TYPE_NAMESTORE_RECORD_STORE); |
1137 | msg->gns_header.r_id = htonl (rid); | 1165 | msg->gns_header.r_id = htonl (rid); |
1138 | msg->name_len = htons (name_len); | 1166 | msg->rd_set_count = htons (rd_set_count); |
1139 | msg->rd_count = htons (rd_count); | ||
1140 | msg->rd_len = htons (rd_ser_len); | ||
1141 | msg->reserved = ntohs (0); | ||
1142 | msg->private_key = *pkey; | 1167 | msg->private_key = *pkey; |
1143 | 1168 | rd_set = (struct RecordSet*) &msg[1]; | |
1144 | name_tmp = (char *) &msg[1]; | 1169 | for (int i = 0; i < rd_set_count; i++) |
1145 | GNUNET_memcpy (name_tmp, label, name_len); | ||
1146 | rd_ser = &name_tmp[name_len]; | ||
1147 | sret = GNUNET_GNSRECORD_records_serialize (rd_count, rd, rd_ser_len, rd_ser); | ||
1148 | if ((0 > sret) || (sret != rd_ser_len)) | ||
1149 | { | 1170 | { |
1150 | GNUNET_break (0); | 1171 | label = a_label[i]; |
1151 | GNUNET_free (env); | 1172 | rd = a_rd[i]; |
1152 | return NULL; | 1173 | name_len = strlen (label) + 1; |
1174 | rd_set->name_len = htons (name_len); | ||
1175 | rd_set->rd_count = htons (a_rd_count[i]); | ||
1176 | rd_set->rd_len = htons (rd_ser_len[i]); | ||
1177 | rd_set->reserved = ntohs (0); | ||
1178 | name_tmp = (char *) &rd_set[1]; | ||
1179 | GNUNET_memcpy (name_tmp, label, name_len); | ||
1180 | rd_ser = &name_tmp[name_len]; | ||
1181 | sret = GNUNET_GNSRECORD_records_serialize (a_rd_count[i], rd, rd_ser_len[i], | ||
1182 | rd_ser); | ||
1183 | if ((0 > sret) || (sret != rd_ser_len[i])) | ||
1184 | { | ||
1185 | GNUNET_break (0); | ||
1186 | GNUNET_free (env); | ||
1187 | return NULL; | ||
1188 | } | ||
1189 | // Point to next RecordSet | ||
1190 | rd_set = (struct RecordSet*) &name_tmp[name_len + rd_ser_len[i]]; | ||
1153 | } | 1191 | } |
1154 | GNUNET_assert (rd_ser_len == sret); | ||
1155 | LOG (GNUNET_ERROR_TYPE_DEBUG, | 1192 | LOG (GNUNET_ERROR_TYPE_DEBUG, |
1156 | "Sending NAMESTORE_RECORD_STORE message for name `%s' with %u records\n", | 1193 | "Sending NAMESTORE_RECORD_STORE message for name %u record sets\n", |
1157 | label, | 1194 | rd_set_count); |
1158 | rd_count); | ||
1159 | qe->timeout_task = | 1195 | qe->timeout_task = |
1160 | GNUNET_SCHEDULER_add_delayed (NAMESTORE_DELAY_TOLERANCE, &warn_delay, qe); | 1196 | GNUNET_SCHEDULER_add_delayed (NAMESTORE_DELAY_TOLERANCE, &warn_delay, qe); |
1161 | if (NULL == h->mq) | 1197 | if (NULL == h->mq) |
@@ -1171,6 +1207,7 @@ GNUNET_NAMESTORE_records_store ( | |||
1171 | return qe; | 1207 | return qe; |
1172 | } | 1208 | } |
1173 | 1209 | ||
1210 | |||
1174 | static struct GNUNET_NAMESTORE_QueueEntry * | 1211 | static struct GNUNET_NAMESTORE_QueueEntry * |
1175 | records_lookup ( | 1212 | records_lookup ( |
1176 | struct GNUNET_NAMESTORE_Handle *h, | 1213 | struct GNUNET_NAMESTORE_Handle *h, |
diff --git a/src/namestore/perf_namestore_api_postgres.conf b/src/namestore/perf_namestore_api_postgres.conf index 52d0ecdd5..12fc24d4b 100644 --- a/src/namestore/perf_namestore_api_postgres.conf +++ b/src/namestore/perf_namestore_api_postgres.conf | |||
@@ -9,3 +9,4 @@ DISABLE = YES | |||
9 | [namestore-postgres] | 9 | [namestore-postgres] |
10 | CONFIG = connect_timeout=10 dbname=gnunetcheck | 10 | CONFIG = connect_timeout=10 dbname=gnunetcheck |
11 | TEMPORARY_TABLE = YES | 11 | TEMPORARY_TABLE = YES |
12 | INIT_ON_CONNECT = YES | ||
diff --git a/src/namestore/perf_namestore_api_sqlite.conf b/src/namestore/perf_namestore_api_sqlite.conf index de0fa3f1f..55c3dc812 100644 --- a/src/namestore/perf_namestore_api_sqlite.conf +++ b/src/namestore/perf_namestore_api_sqlite.conf | |||
@@ -5,3 +5,4 @@ DISABLE = YES | |||
5 | 5 | ||
6 | [namestore-sqlite] | 6 | [namestore-sqlite] |
7 | FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db | 7 | FILENAME = $GNUNET_TEST_HOME/namestore/sqlite_test.db |
8 | INIT_ON_CONNECT = YES | ||
diff --git a/src/namestore/plugin_namestore_sqlite.c b/src/namestore/plugin_namestore_sqlite.c index f1097ad0a..35fd340ab 100644 --- a/src/namestore/plugin_namestore_sqlite.c +++ b/src/namestore/plugin_namestore_sqlite.c | |||
@@ -871,6 +871,7 @@ database_connect (struct Plugin *plugin) | |||
871 | GNUNET_free (sqlite_filename); | 871 | GNUNET_free (sqlite_filename); |
872 | return GNUNET_SYSERR; | 872 | return GNUNET_SYSERR; |
873 | } | 873 | } |
874 | GNUNET_free (sqlite_filename); | ||
874 | GNUNET_break (SQLITE_OK == | 875 | GNUNET_break (SQLITE_OK == |
875 | sqlite3_busy_timeout (plugin->dbh, | 876 | sqlite3_busy_timeout (plugin->dbh, |
876 | BUSY_TIMEOUT_MS)); | 877 | BUSY_TIMEOUT_MS)); |
diff --git a/src/namestore/plugin_rest_namestore.c b/src/namestore/plugin_rest_namestore.c index 0475960eb..b9c32e087 100644 --- a/src/namestore/plugin_rest_namestore.c +++ b/src/namestore/plugin_rest_namestore.c | |||
@@ -721,6 +721,114 @@ ns_lookup_cb (void *cls, | |||
721 | } | 721 | } |
722 | } | 722 | } |
723 | 723 | ||
724 | /** | ||
725 | * Handle namestore POST import | ||
726 | * | ||
727 | * @param con_handle the connection handle | ||
728 | * @param url the url | ||
729 | * @param cls the RequestHandle | ||
730 | */ | ||
731 | /*void | ||
732 | namestore_import (struct GNUNET_REST_RequestHandle *con_handle, | ||
733 | const char *url, | ||
734 | void *cls) | ||
735 | { | ||
736 | struct RequestHandle *handle = cls; | ||
737 | struct EgoEntry *ego_entry; | ||
738 | struct GNUNET_GNSRECORD_Data *rd_import; | ||
739 | char *egoname; | ||
740 | json_t *data_js; | ||
741 | json_error_t err; | ||
742 | |||
743 | char term_data[handle->rest_handle->data_size + 1]; | ||
744 | |||
745 | if (0 >= handle->rest_handle->data_size) | ||
746 | { | ||
747 | handle->response_code = MHD_HTTP_BAD_REQUEST; | ||
748 | handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_NO_DATA); | ||
749 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
750 | return; | ||
751 | } | ||
752 | term_data[handle->rest_handle->data_size] = '\0'; | ||
753 | GNUNET_memcpy (term_data, | ||
754 | handle->rest_handle->data, | ||
755 | handle->rest_handle->data_size); | ||
756 | data_js = json_loads (term_data, JSON_DECODE_ANY, &err); | ||
757 | if (NULL == data_js) | ||
758 | { | ||
759 | GNUNET_asprintf (&handle->emsg, "Error parsing data: %s", err.text); | ||
760 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
761 | return; | ||
762 | } | ||
763 | if (!json_is_array (data_js)) | ||
764 | { | ||
765 | handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_INVALID_DATA); | ||
766 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
767 | json_decref (data_js); | ||
768 | return; | ||
769 | } | ||
770 | size_t num_records = json_array_size (data_js); | ||
771 | rd_import = GNUNET_malloc (sizeof (*rd_import) * json_array_size (data_js)); | ||
772 | for (int i = 0; i < num_records) | ||
773 | struct GNUNET_JSON_Specification gnsspec[] = | ||
774 | { GNUNET_GNSRECORD_JSON_spec_gnsrecord (&handle->rd, &handle->rd_count, | ||
775 | &handle->record_name), | ||
776 | GNUNET_JSON_spec_end () }; | ||
777 | if (GNUNET_OK != GNUNET_JSON_parse (data_js, gnsspec, NULL, NULL)) | ||
778 | { | ||
779 | handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_INVALID_DATA); | ||
780 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
781 | json_decref (data_js); | ||
782 | return; | ||
783 | } | ||
784 | GNUNET_JSON_parse_free (gnsspec); | ||
785 | if (0 >= strlen (handle->record_name)) | ||
786 | { | ||
787 | handle->response_code = MHD_HTTP_BAD_REQUEST; | ||
788 | handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_INVALID_DATA); | ||
789 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
790 | json_decref (data_js); | ||
791 | return; | ||
792 | } | ||
793 | json_decref (data_js); | ||
794 | |||
795 | egoname = NULL; | ||
796 | ego_entry = NULL; | ||
797 | |||
798 | // set zone to name if given | ||
799 | if (strlen (GNUNET_REST_API_NS_NAMESTORE) + 1 >= strlen (handle->url)) | ||
800 | { | ||
801 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
802 | handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND); | ||
803 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
804 | return; | ||
805 | } | ||
806 | egoname = &handle->url[strlen (GNUNET_REST_API_NS_NAMESTORE) + 1]; | ||
807 | ego_entry = get_egoentry_namestore (handle, egoname); | ||
808 | |||
809 | if (NULL == ego_entry) | ||
810 | { | ||
811 | handle->response_code = MHD_HTTP_NOT_FOUND; | ||
812 | handle->emsg = GNUNET_strdup (GNUNET_REST_IDENTITY_NOT_FOUND); | ||
813 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
814 | return; | ||
815 | } | ||
816 | handle->zone_pkey = GNUNET_IDENTITY_ego_get_private_key (ego_entry->ego); | ||
817 | handle->ns_qe = GNUNET_NAMESTORE_records_lookup (ns_handle, | ||
818 | handle->zone_pkey, | ||
819 | handle->record_name, | ||
820 | &ns_lookup_error_cb, | ||
821 | handle, | ||
822 | &ns_lookup_cb, | ||
823 | handle); | ||
824 | if (NULL == handle->ns_qe) | ||
825 | { | ||
826 | handle->emsg = GNUNET_strdup (GNUNET_REST_NAMESTORE_FAILED); | ||
827 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
828 | return; | ||
829 | } | ||
830 | } | ||
831 | */ | ||
724 | 832 | ||
725 | /** | 833 | /** |
726 | * Handle namestore POST/PUT request | 834 | * Handle namestore POST/PUT request |
diff --git a/src/namestore/test_plugin_namestore_postgres.conf b/src/namestore/test_plugin_namestore_postgres.conf index 2ce8a7792..3b5cb8699 100644 --- a/src/namestore/test_plugin_namestore_postgres.conf +++ b/src/namestore/test_plugin_namestore_postgres.conf | |||
@@ -1,3 +1,4 @@ | |||
1 | [namestore-postgres] | 1 | [namestore-postgres] |
2 | CONFIG = connect_timeout=10 dbname=gnunetcheck | 2 | CONFIG = connect_timeout=10 dbname=gnunetcheck |
3 | INIT_ON_CONNECT = YES | ||
3 | TEMPORARY_TABLE = YES | 4 | TEMPORARY_TABLE = YES |
diff --git a/src/namestore/test_plugin_namestore_sqlite.conf b/src/namestore/test_plugin_namestore_sqlite.conf index 24eecd286..365198db2 100644 --- a/src/namestore/test_plugin_namestore_sqlite.conf +++ b/src/namestore/test_plugin_namestore_sqlite.conf | |||
@@ -1,2 +1,3 @@ | |||
1 | [namestore-sqlite] | 1 | [namestore-sqlite] |
2 | FILENAME = $GNUNET_TMP/gnunet-test-plugin-namestore-sqlite/sqlite.db | 2 | FILENAME = $GNUNET_TMP/gnunet-test-plugin-namestore-sqlite/sqlite.db |
3 | INIT_ON_CONNECT = YES | ||