gnunet-service-fs_indexing.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  1. /*
  2. This file is part of GNUnet.
  3. (C) 2009, 2010 Christian Grothoff (and other contributing authors)
  4. GNUnet is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published
  6. by the Free Software Foundation; either version 3, or (at your
  7. option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNUnet; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  15. Boston, MA 02111-1307, USA.
  16. */
  17. /**
  18. * @file fs/gnunet-service-fs_indexing.c
  19. * @brief program that provides indexing functions of the file-sharing service
  20. * @author Christian Grothoff
  21. */
  22. #include "platform.h"
  23. #include <float.h>
  24. #include "gnunet_core_service.h"
  25. #include "gnunet_datastore_service.h"
  26. #include "gnunet_peer_lib.h"
  27. #include "gnunet_protocols.h"
  28. #include "gnunet_signatures.h"
  29. #include "gnunet_util_lib.h"
  30. #include "gnunet-service-fs.h"
  31. #include "gnunet-service-fs_indexing.h"
  32. #include "fs.h"
  33. /**
  34. * In-memory information about indexed files (also available
  35. * on-disk).
  36. */
  37. struct IndexInfo
  38. {
  39. /**
  40. * This is a linked list.
  41. */
  42. struct IndexInfo *next;
  43. /**
  44. * Name of the indexed file. Memory allocated
  45. * at the end of this struct (do not free).
  46. */
  47. const char *filename;
  48. /**
  49. * Context for transmitting confirmation to client,
  50. * NULL if we've done this already.
  51. */
  52. struct GNUNET_SERVER_TransmitContext *tc;
  53. /**
  54. * Context for hashing of the file.
  55. */
  56. struct GNUNET_CRYPTO_FileHashContext *fhc;
  57. /**
  58. * Hash of the contents of the file.
  59. */
  60. GNUNET_HashCode file_id;
  61. };
  62. /**
  63. * Linked list of indexed files.
  64. */
  65. static struct IndexInfo *indexed_files;
  66. /**
  67. * Maps hash over content of indexed files to the respective filename.
  68. * The filenames are pointers into the indexed_files linked list and
  69. * do not need to be freed.
  70. */
  71. static struct GNUNET_CONTAINER_MultiHashMap *ifm;
  72. /**
  73. * Our configuration.
  74. */
  75. static const struct GNUNET_CONFIGURATION_Handle *cfg;
  76. /**
  77. * Datastore handle. Created and destroyed by code in
  78. * gnunet-service-fs (this is an alias).
  79. */
  80. static struct GNUNET_DATASTORE_Handle *dsh;
  81. /**
  82. * Write the current index information list to disk.
  83. */
  84. static void
  85. write_index_list ()
  86. {
  87. struct GNUNET_BIO_WriteHandle *wh;
  88. char *fn;
  89. struct IndexInfo *pos;
  90. if (GNUNET_OK !=
  91. GNUNET_CONFIGURATION_get_value_filename (cfg,
  92. "FS",
  93. "INDEXDB",
  94. &fn))
  95. {
  96. GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
  97. _("Configuration option `%s' in section `%s' missing.\n"),
  98. "INDEXDB",
  99. "FS");
  100. return;
  101. }
  102. wh = GNUNET_BIO_write_open (fn);
  103. if (NULL == wh)
  104. {
  105. GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
  106. _("Could not open `%s'.\n"),
  107. fn);
  108. GNUNET_free (fn);
  109. return;
  110. }
  111. pos = indexed_files;
  112. while (pos != NULL)
  113. {
  114. if ( (GNUNET_OK !=
  115. GNUNET_BIO_write (wh,
  116. &pos->file_id,
  117. sizeof (GNUNET_HashCode))) ||
  118. (GNUNET_OK !=
  119. GNUNET_BIO_write_string (wh,
  120. pos->filename)) )
  121. break;
  122. pos = pos->next;
  123. }
  124. if (GNUNET_OK !=
  125. GNUNET_BIO_write_close (wh))
  126. {
  127. GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
  128. _("Error writing `%s'.\n"),
  129. fn);
  130. GNUNET_free (fn);
  131. return;
  132. }
  133. GNUNET_free (fn);
  134. }
  135. /**
  136. * Read index information from disk.
  137. */
  138. static void
  139. read_index_list ()
  140. {
  141. struct GNUNET_BIO_ReadHandle *rh;
  142. char *fn;
  143. struct IndexInfo *pos;
  144. char *fname;
  145. GNUNET_HashCode hc;
  146. size_t slen;
  147. char *emsg;
  148. if (GNUNET_OK !=
  149. GNUNET_CONFIGURATION_get_value_filename (cfg,
  150. "FS",
  151. "INDEXDB",
  152. &fn))
  153. {
  154. GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
  155. _("Configuration option `%s' in section `%s' missing.\n"),
  156. "INDEXDB",
  157. "FS");
  158. return;
  159. }
  160. if (GNUNET_NO == GNUNET_DISK_file_test (fn))
  161. {
  162. /* no index info yet */
  163. GNUNET_free (fn);
  164. return;
  165. }
  166. rh = GNUNET_BIO_read_open (fn);
  167. if (NULL == rh)
  168. {
  169. GNUNET_log (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
  170. _("Could not open `%s'.\n"),
  171. fn);
  172. GNUNET_free (fn);
  173. return;
  174. }
  175. while ( (GNUNET_OK ==
  176. GNUNET_BIO_read (rh,
  177. "Hash of indexed file",
  178. &hc,
  179. sizeof (GNUNET_HashCode))) &&
  180. (GNUNET_OK ==
  181. GNUNET_BIO_read_string (rh,
  182. "Name of indexed file",
  183. &fname,
  184. 1024 * 16)) &&
  185. (fname != NULL) )
  186. {
  187. slen = strlen (fname) + 1;
  188. pos = GNUNET_malloc (sizeof (struct IndexInfo) + slen);
  189. pos->file_id = hc;
  190. pos->filename = (const char *) &pos[1];
  191. memcpy (&pos[1], fname, slen);
  192. if (GNUNET_SYSERR ==
  193. GNUNET_CONTAINER_multihashmap_put (ifm,
  194. &hc,
  195. (void*) pos->filename,
  196. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
  197. {
  198. GNUNET_free (pos);
  199. }
  200. else
  201. {
  202. pos->next = indexed_files;
  203. indexed_files = pos;
  204. }
  205. GNUNET_free (fname);
  206. }
  207. if (GNUNET_OK !=
  208. GNUNET_BIO_read_close (rh, &emsg))
  209. GNUNET_free (emsg);
  210. GNUNET_free (fn);
  211. }
  212. /**
  213. * We've validated the hash of the file we're about to index. Signal
  214. * success to the client and update our internal data structures.
  215. *
  216. * @param ii the index info entry for the request
  217. */
  218. static void
  219. signal_index_ok (struct IndexInfo *ii)
  220. {
  221. if (GNUNET_SYSERR ==
  222. GNUNET_CONTAINER_multihashmap_put (ifm,
  223. &ii->file_id,
  224. (void*) ii->filename,
  225. GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY))
  226. {
  227. GNUNET_log (GNUNET_ERROR_TYPE_INFO,
  228. _("Index request received for file `%s' is already indexed as `%s'. Permitting anyway.\n"),
  229. ii->filename,
  230. (const char*) GNUNET_CONTAINER_multihashmap_get (ifm,
  231. &ii->file_id));
  232. GNUNET_SERVER_transmit_context_append_data (ii->tc,
  233. NULL, 0,
  234. GNUNET_MESSAGE_TYPE_FS_INDEX_START_OK);
  235. GNUNET_SERVER_transmit_context_run (ii->tc,
  236. GNUNET_TIME_UNIT_MINUTES);
  237. GNUNET_free (ii);
  238. return;
  239. }
  240. ii->next = indexed_files;
  241. indexed_files = ii;
  242. write_index_list ();
  243. GNUNET_SERVER_transmit_context_append_data (ii->tc,
  244. NULL, 0,
  245. GNUNET_MESSAGE_TYPE_FS_INDEX_START_OK);
  246. GNUNET_SERVER_transmit_context_run (ii->tc,
  247. GNUNET_TIME_UNIT_MINUTES);
  248. ii->tc = NULL;
  249. }
  250. /**
  251. * Function called once the hash computation over an
  252. * indexed file has completed.
  253. *
  254. * @param cls closure, our publishing context
  255. * @param res resulting hash, NULL on error
  256. */
  257. static void
  258. hash_for_index_val (void *cls,
  259. const GNUNET_HashCode *
  260. res)
  261. {
  262. struct IndexInfo *ii = cls;
  263. ii->fhc = NULL;
  264. if ( (res == NULL) ||
  265. (0 != memcmp (res,
  266. &ii->file_id,
  267. sizeof(GNUNET_HashCode))) )
  268. {
  269. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  270. _("Hash mismatch trying to index file `%s' which has hash `%s'\n"),
  271. ii->filename,
  272. GNUNET_h2s (res));
  273. #if DEBUG_FS
  274. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  275. "Wanted `%s'\n",
  276. GNUNET_h2s (&ii->file_id));
  277. #endif
  278. GNUNET_SERVER_transmit_context_append_data (ii->tc,
  279. NULL, 0,
  280. GNUNET_MESSAGE_TYPE_FS_INDEX_START_FAILED);
  281. GNUNET_SERVER_transmit_context_run (ii->tc,
  282. GNUNET_TIME_UNIT_MINUTES);
  283. GNUNET_free (ii);
  284. return;
  285. }
  286. signal_index_ok (ii);
  287. }
  288. /**
  289. * Handle INDEX_START-message.
  290. *
  291. * @param cls closure
  292. * @param client identification of the client
  293. * @param message the actual message
  294. */
  295. void
  296. GNUNET_FS_handle_index_start (void *cls,
  297. struct GNUNET_SERVER_Client *client,
  298. const struct GNUNET_MessageHeader *message)
  299. {
  300. const struct IndexStartMessage *ism;
  301. char *fn;
  302. uint16_t msize;
  303. struct IndexInfo *ii;
  304. size_t slen;
  305. uint64_t dev;
  306. uint64_t ino;
  307. uint64_t mydev;
  308. uint64_t myino;
  309. msize = ntohs(message->size);
  310. if ( (msize <= sizeof (struct IndexStartMessage)) ||
  311. ( ((const char *)message)[msize-1] != '\0') )
  312. {
  313. GNUNET_break (0);
  314. GNUNET_SERVER_receive_done (client,
  315. GNUNET_SYSERR);
  316. return;
  317. }
  318. ism = (const struct IndexStartMessage*) message;
  319. if (0 != ism->reserved)
  320. {
  321. GNUNET_break (0);
  322. GNUNET_SERVER_receive_done (client,
  323. GNUNET_SYSERR);
  324. return;
  325. }
  326. fn = GNUNET_STRINGS_filename_expand ((const char*) &ism[1]);
  327. if (fn == NULL)
  328. {
  329. GNUNET_SERVER_receive_done (client,
  330. GNUNET_SYSERR);
  331. return;
  332. }
  333. dev = GNUNET_ntohll (ism->device);
  334. ino = GNUNET_ntohll (ism->inode);
  335. ism = (const struct IndexStartMessage*) message;
  336. slen = strlen (fn) + 1;
  337. ii = GNUNET_malloc (sizeof (struct IndexInfo) + slen);
  338. ii->filename = (const char*) &ii[1];
  339. memcpy (&ii[1], fn, slen);
  340. ii->file_id = ism->file_id;
  341. #if DEBUG_FS
  342. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  343. "Received `%s' message for file `%s'\n",
  344. "START_INDEX",
  345. ii->filename);
  346. #endif
  347. ii->tc = GNUNET_SERVER_transmit_context_create (client);
  348. mydev = 0;
  349. myino = 0;
  350. if ( ( (dev != 0) ||
  351. (ino != 0) ) &&
  352. (GNUNET_OK == GNUNET_DISK_file_get_identifiers (fn,
  353. &mydev,
  354. &myino)) &&
  355. ( (dev == mydev) &&
  356. (ino == myino) ) )
  357. {
  358. /* fast validation OK! */
  359. signal_index_ok (ii);
  360. GNUNET_free (fn);
  361. return;
  362. }
  363. #if DEBUG_FS
  364. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  365. "Mismatch in file identifiers (%llu != %llu or %u != %u), need to hash.\n",
  366. (unsigned long long) ino,
  367. (unsigned long long) myino,
  368. (unsigned int) dev,
  369. (unsigned int) mydev);
  370. #endif
  371. /* slow validation, need to hash full file (again) */
  372. ii->fhc = GNUNET_CRYPTO_hash_file (GNUNET_SCHEDULER_PRIORITY_IDLE,
  373. fn,
  374. HASHING_BLOCKSIZE,
  375. &hash_for_index_val,
  376. ii);
  377. if (ii->fhc == NULL)
  378. hash_for_index_val (ii, NULL);
  379. GNUNET_free (fn);
  380. }
  381. /**
  382. * Handle INDEX_LIST_GET-message.
  383. *
  384. * @param cls closure
  385. * @param client identification of the client
  386. * @param message the actual message
  387. */
  388. void
  389. GNUNET_FS_handle_index_list_get (void *cls,
  390. struct GNUNET_SERVER_Client *client,
  391. const struct GNUNET_MessageHeader *message)
  392. {
  393. struct GNUNET_SERVER_TransmitContext *tc;
  394. struct IndexInfoMessage *iim;
  395. char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1];
  396. size_t slen;
  397. const char *fn;
  398. struct IndexInfo *pos;
  399. tc = GNUNET_SERVER_transmit_context_create (client);
  400. iim = (struct IndexInfoMessage*) buf;
  401. pos = indexed_files;
  402. while (NULL != pos)
  403. {
  404. fn = pos->filename;
  405. slen = strlen (fn) + 1;
  406. if (slen + sizeof (struct IndexInfoMessage) >= GNUNET_SERVER_MAX_MESSAGE_SIZE)
  407. {
  408. GNUNET_break (0);
  409. break;
  410. }
  411. iim->header.type = htons (GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_ENTRY);
  412. iim->header.size = htons (slen + sizeof (struct IndexInfoMessage));
  413. iim->reserved = 0;
  414. iim->file_id = pos->file_id;
  415. memcpy (&iim[1], fn, slen);
  416. GNUNET_SERVER_transmit_context_append_message (tc,
  417. &iim->header);
  418. pos = pos->next;
  419. }
  420. GNUNET_SERVER_transmit_context_append_data (tc,
  421. NULL, 0,
  422. GNUNET_MESSAGE_TYPE_FS_INDEX_LIST_END);
  423. GNUNET_SERVER_transmit_context_run (tc,
  424. GNUNET_TIME_UNIT_MINUTES);
  425. }
  426. /**
  427. * Handle UNINDEX-message.
  428. *
  429. * @param cls closure
  430. * @param client identification of the client
  431. * @param message the actual message
  432. */
  433. void
  434. GNUNET_FS_handle_unindex (void *cls,
  435. struct GNUNET_SERVER_Client *client,
  436. const struct GNUNET_MessageHeader *message)
  437. {
  438. const struct UnindexMessage *um;
  439. struct IndexInfo *pos;
  440. struct IndexInfo *prev;
  441. struct IndexInfo *next;
  442. struct GNUNET_SERVER_TransmitContext *tc;
  443. int found;
  444. um = (const struct UnindexMessage*) message;
  445. if (0 != um->reserved)
  446. {
  447. GNUNET_break (0);
  448. GNUNET_SERVER_receive_done (client,
  449. GNUNET_SYSERR);
  450. return;
  451. }
  452. found = GNUNET_NO;
  453. prev = NULL;
  454. pos = indexed_files;
  455. while (NULL != pos)
  456. {
  457. next = pos->next;
  458. if (0 == memcmp (&pos->file_id,
  459. &um->file_id,
  460. sizeof (GNUNET_HashCode)))
  461. {
  462. if (prev == NULL)
  463. indexed_files = next;
  464. else
  465. prev->next = next;
  466. GNUNET_break (GNUNET_OK ==
  467. GNUNET_CONTAINER_multihashmap_remove (ifm,
  468. &pos->file_id,
  469. (void*) pos->filename));
  470. GNUNET_free (pos);
  471. found = GNUNET_YES;
  472. }
  473. else
  474. {
  475. prev = pos;
  476. }
  477. pos = next;
  478. }
  479. #if DEBUG_FS
  480. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  481. "Client requested unindexing of file `%s': %s\n",
  482. GNUNET_h2s (&um->file_id),
  483. found ? "found" : "not found");
  484. #endif
  485. if (GNUNET_YES == found)
  486. write_index_list ();
  487. tc = GNUNET_SERVER_transmit_context_create (client);
  488. GNUNET_SERVER_transmit_context_append_data (tc,
  489. NULL, 0,
  490. GNUNET_MESSAGE_TYPE_FS_UNINDEX_OK);
  491. GNUNET_SERVER_transmit_context_run (tc,
  492. GNUNET_TIME_UNIT_MINUTES);
  493. }
  494. /**
  495. * Continuation called from datastore's remove
  496. * function.
  497. *
  498. * @param cls unused
  499. * @param success did the deletion work?
  500. * @param msg error message
  501. */
  502. static void
  503. remove_cont (void *cls,
  504. int success,
  505. const char *msg)
  506. {
  507. if (GNUNET_OK != success)
  508. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  509. _("Failed to delete bogus block: %s\n"),
  510. msg);
  511. }
  512. /**
  513. * We've received an on-demand encoded block from the datastore.
  514. * Attempt to do on-demand encoding and (if successful), call the
  515. * continuation with the resulting block. On error, clean up and ask
  516. * the datastore for more results.
  517. *
  518. * @param key key for the content
  519. * @param size number of bytes in data
  520. * @param data content stored
  521. * @param type type of the content
  522. * @param priority priority of the content
  523. * @param anonymity anonymity-level for the content
  524. * @param expiration expiration time for the content
  525. * @param uid unique identifier for the datum;
  526. * maybe 0 if no unique identifier is available
  527. * @param cont function to call with the actual block (at most once, on success)
  528. * @param cont_cls closure for cont
  529. * @return GNUNET_OK on success
  530. */
  531. int
  532. GNUNET_FS_handle_on_demand_block (const GNUNET_HashCode * key,
  533. uint32_t size,
  534. const void *data,
  535. enum GNUNET_BLOCK_Type type,
  536. uint32_t priority,
  537. uint32_t anonymity,
  538. struct GNUNET_TIME_Absolute
  539. expiration, uint64_t uid,
  540. GNUNET_DATASTORE_DatumProcessor cont,
  541. void *cont_cls)
  542. {
  543. const struct OnDemandBlock *odb;
  544. GNUNET_HashCode nkey;
  545. struct GNUNET_CRYPTO_AesSessionKey skey;
  546. struct GNUNET_CRYPTO_AesInitializationVector iv;
  547. GNUNET_HashCode query;
  548. ssize_t nsize;
  549. char ndata[DBLOCK_SIZE];
  550. char edata[DBLOCK_SIZE];
  551. const char *fn;
  552. struct GNUNET_DISK_FileHandle *fh;
  553. uint64_t off;
  554. if (size != sizeof (struct OnDemandBlock))
  555. {
  556. GNUNET_break (0);
  557. GNUNET_DATASTORE_remove (dsh,
  558. key,
  559. size,
  560. data,
  561. -1, -1,
  562. GNUNET_TIME_UNIT_FOREVER_REL,
  563. &remove_cont,
  564. NULL);
  565. return GNUNET_SYSERR;
  566. }
  567. odb = (const struct OnDemandBlock*) data;
  568. off = GNUNET_ntohll (odb->offset);
  569. fn = (const char*) GNUNET_CONTAINER_multihashmap_get (ifm,
  570. &odb->file_id);
  571. fh = NULL;
  572. if ( (NULL == fn) ||
  573. (NULL == (fh = GNUNET_DISK_file_open (fn,
  574. GNUNET_DISK_OPEN_READ,
  575. GNUNET_DISK_PERM_NONE))) ||
  576. (off !=
  577. GNUNET_DISK_file_seek (fh,
  578. off,
  579. GNUNET_DISK_SEEK_SET)) ||
  580. (-1 ==
  581. (nsize = GNUNET_DISK_file_read (fh,
  582. ndata,
  583. sizeof (ndata)))) )
  584. {
  585. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  586. _("Could not access indexed file `%s' (%s) at offset %llu: %s\n"),
  587. GNUNET_h2s (&odb->file_id),
  588. fn,
  589. (unsigned long long) off,
  590. (fn == NULL) ? _("not indexed") : STRERROR (errno));
  591. if (fh != NULL)
  592. GNUNET_DISK_file_close (fh);
  593. GNUNET_DATASTORE_remove (dsh,
  594. key,
  595. size,
  596. data,
  597. -1, -1,
  598. GNUNET_TIME_UNIT_FOREVER_REL,
  599. &remove_cont,
  600. NULL);
  601. return GNUNET_SYSERR;
  602. }
  603. GNUNET_DISK_file_close (fh);
  604. GNUNET_CRYPTO_hash (ndata,
  605. nsize,
  606. &nkey);
  607. GNUNET_CRYPTO_hash_to_aes_key (&nkey, &skey, &iv);
  608. GNUNET_CRYPTO_aes_encrypt (ndata,
  609. nsize,
  610. &skey,
  611. &iv,
  612. edata);
  613. GNUNET_CRYPTO_hash (edata,
  614. nsize,
  615. &query);
  616. if (0 != memcmp (&query,
  617. key,
  618. sizeof (GNUNET_HashCode)))
  619. {
  620. GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
  621. _("Indexed file `%s' changed at offset %llu\n"),
  622. fn,
  623. (unsigned long long) off);
  624. GNUNET_DATASTORE_remove (dsh,
  625. key,
  626. size,
  627. data,
  628. -1, -1,
  629. GNUNET_TIME_UNIT_FOREVER_REL,
  630. &remove_cont,
  631. NULL);
  632. return GNUNET_SYSERR;
  633. }
  634. #if DEBUG_FS
  635. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  636. "On-demand encoded block for query `%s'\n",
  637. GNUNET_h2s (key));
  638. #endif
  639. cont (cont_cls,
  640. key,
  641. nsize,
  642. edata,
  643. GNUNET_BLOCK_TYPE_FS_DBLOCK,
  644. priority,
  645. anonymity,
  646. expiration,
  647. uid);
  648. return GNUNET_OK;
  649. }
  650. /**
  651. * Shutdown the module.
  652. */
  653. void
  654. GNUNET_FS_indexing_done ()
  655. {
  656. struct IndexInfo *pos;
  657. GNUNET_CONTAINER_multihashmap_destroy (ifm);
  658. ifm = NULL;
  659. while (NULL != (pos = indexed_files))
  660. {
  661. indexed_files = pos->next;
  662. if (pos->fhc != NULL)
  663. GNUNET_CRYPTO_hash_file_cancel (pos->fhc);
  664. GNUNET_free (pos);
  665. }
  666. cfg = NULL;
  667. }
  668. /**
  669. * Initialize the indexing submodule.
  670. *
  671. * @param c configuration to use
  672. * @param d datastore to use
  673. */
  674. int
  675. GNUNET_FS_indexing_init (const struct GNUNET_CONFIGURATION_Handle *c,
  676. struct GNUNET_DATASTORE_Handle *d)
  677. {
  678. cfg = c;
  679. dsh = d;
  680. ifm = GNUNET_CONTAINER_multihashmap_create (128);
  681. read_index_list ();
  682. return GNUNET_OK;
  683. }
  684. /* end of gnunet-service-fs_indexing.c */