📄 search.c
字号:
/* This file is part of GNUnet. (C) 2001, 2002, 2003, 2004, 2006, 2008 Christian Grothoff (and other contributing authors) GNUnet is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNUnet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNUnet; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.*//** * @file applications/fs/fsui/search.c * @brief Helper functions for searching. FSUI search performs the * filtering of duplicate results as well as adding boolean search * (ANDing and ORing) and confirming if files are present in the * network. * @author Christian Grothoff */#include "platform.h"#include "gnunet_util.h"#include "gnunet_directories.h"#include "gnunet_protocols.h"#include "gnunet_fsui_lib.h"#include "gnunet_uritrack_lib.h"#include "gnunet_namespace_lib.h"#include "fsui.h"#define DEBUG_SEARCH GNUNET_NO/** * Pass the result to the client and note it as shown. */static voidprocessResult (struct GNUNET_FSUI_SearchList *ctx, struct SearchResultList *pos, int update){ GNUNET_FSUI_Event event; if (update) { event.type = GNUNET_FSUI_search_update; event.data.SearchUpdate.sc.pos = ctx; event.data.SearchUpdate.sc.cctx = ctx->cctx; event.data.SearchUpdate.fi = pos->fi; event.data.SearchUpdate.searchURI = ctx->uri; event.data.SearchUpdate.availability_rank = pos->probeSuccess - pos->probeFailure; event.data.SearchUpdate.availability_certainty = pos->probeSuccess + pos->probeFailure; event.data.SearchUpdate.applicability_rank = pos->matchingSearchCount; } else { event.type = GNUNET_FSUI_search_result; event.data.SearchResult.sc.pos = ctx; event.data.SearchResult.sc.cctx = ctx->cctx; event.data.SearchResult.fi = pos->fi; event.data.SearchResult.searchURI = ctx->uri; } ctx->ctx->ecb (ctx->ctx->ecbClosure, &event); if (! update) { GNUNET_URITRACK_add_state (ctx->ctx->ectx, ctx->ctx->cfg, pos->fi.uri, GNUNET_URITRACK_SEARCH_RESULT); }}/** * Process results found by ECRS. */intGNUNET_FSUI_search_progress_callback (const GNUNET_ECRS_FileInfo * fi, const GNUNET_HashCode * key, int isRoot, void *cls){ GNUNET_FSUI_SearchList *pos = cls; unsigned int i; struct GNUNET_GE_Context *ectx; struct SearchResultList *srl; struct SearchRecordList *rec; int update; GNUNET_HashCode nsid; ectx = pos->ctx->ectx; GNUNET_URITRACK_track (ectx, pos->ctx->cfg, fi); if (isRoot) { GNUNET_NS_namespace_set_root (ectx, pos->ctx->cfg, fi->uri); GNUNET_ECRS_uri_get_namespace_from_sks (fi->uri, &nsid); GNUNET_pseudonym_add (ectx, pos->ctx->cfg, &nsid, fi->meta); return GNUNET_OK; } srl = pos->resultsReceived; while (srl != NULL) { if (GNUNET_ECRS_uri_test_equal (fi->uri, srl->fi.uri)) { for (i = 0; i < srl->matchingSearchCount; i++) { if ((GNUNET_ECRS_uri_test_sks (pos->uri)) || (0 == memcmp (key, &srl->matchingSearches[i]->key, sizeof (GNUNET_HashCode)))) {#if DEBUG_SEARCH fprintf (stderr, "Received search result that I have seen before.\n");#endif return GNUNET_OK; /* seen before */ } } /* not seen before, find corresponding search! */ rec = pos->searches; while ((rec != NULL) && (0 != memcmp (key, &rec->key, sizeof (GNUNET_HashCode)))) rec = rec->next; if (rec == NULL) { GNUNET_GE_BREAK (NULL, 0); return GNUNET_OK; /* should have matching search */ } GNUNET_array_append (srl->matchingSearches, srl->matchingSearchCount, rec); if (rec->is_required) { if (srl->mandatoryMatchesRemaining > 0) srl->mandatoryMatchesRemaining--; else GNUNET_GE_BREAK (NULL, 0); update = 0;#if DEBUG_SEARCH fprintf (stderr, "Received mandatory search result\n");#endif } else { update = 1;#if DEBUG_SEARCH fprintf (stderr, "Received optional search result\n");#endif } if (srl->mandatoryMatchesRemaining == 0) {#if DEBUG_SEARCH fprintf (stderr, "Passing result to client\n");#endif processResult (pos, srl, update); } return GNUNET_OK; } srl = srl->next; } /* new result */ rec = pos->searches; while ((rec != NULL) && (!GNUNET_ECRS_uri_test_sks (pos->uri)) && (0 != memcmp (key, &rec->key, sizeof (GNUNET_HashCode)))) rec = rec->next; if (rec == NULL) { GNUNET_GE_BREAK (NULL, 0); return GNUNET_OK; /* should have matching search */ } srl = GNUNET_malloc (sizeof (struct SearchResultList)); memset (srl, 0, sizeof (struct SearchResultList)); GNUNET_array_append (srl->matchingSearches, srl->matchingSearchCount, rec); srl->fi.meta = GNUNET_meta_data_duplicate (fi->meta); srl->fi.uri = GNUNET_ECRS_uri_duplicate (fi->uri); srl->mandatoryMatchesRemaining = pos->mandatory_keyword_count; if (rec->is_required) { if (srl->mandatoryMatchesRemaining > 0) srl->mandatoryMatchesRemaining--; else GNUNET_GE_BREAK (NULL, 0);#if DEBUG_SEARCH fprintf (stderr, "Received new mandatory result\n");#endif } else {#if DEBUG_SEARCH fprintf (stderr, "Received new optional result\n");#endif } srl->next = pos->resultsReceived; pos->resultsReceived = srl; if (srl->mandatoryMatchesRemaining == 0) {#if DEBUG_SEARCH fprintf (stderr, "Passing new result to client\n");#endif processResult (pos, srl, 0); } return GNUNET_OK;}static intcount_mandatory_keywords (const char *keyword, int is_mandatory, void *closure){ struct GNUNET_FSUI_SearchList *pos = closure; if (is_mandatory) pos->mandatory_keyword_count++; return GNUNET_OK;}/** * This function is called on each keyword in the * search list. Start the corresponding ECRS search. * * @param closure our GNUNET_FSUI_SearchList. */static intcreate_ecrs_search (const char *keyword, int is_mandatory, void *closure){ struct GNUNET_FSUI_SearchList *pos = closure; struct SearchRecordList *srl;#if DEBUG_SEARCH fprintf (stderr, "Starting search for `%s' (%d)\n", keyword, is_mandatory);#endif srl = GNUNET_malloc (sizeof (struct SearchRecordList)); memset (srl, 0, sizeof (struct SearchRecordList)); srl->uri = GNUNET_ECRS_keyword_command_line_to_uri (pos->ctx->ectx, 1, &keyword); GNUNET_hash (keyword, strlen (keyword), &srl->key); srl->is_required = is_mandatory; srl->next = pos->searches; pos->searches = srl; srl->search = GNUNET_ECRS_search_start (pos->ctx->ectx, pos->ctx->cfg, pos->probe_context, srl->uri, pos->anonymityLevel, &GNUNET_FSUI_search_progress_callback, pos); if (srl->search == NULL) { GNUNET_ECRS_uri_destroy (srl->uri); pos->searches = srl->next; GNUNET_free (srl); pos->start_time = 0; /* flag to indicate error */ return GNUNET_SYSERR; } return GNUNET_OK;}/** * Start a search. */struct GNUNET_FSUI_SearchList *GNUNET_FSUI_search_start (struct GNUNET_FSUI_Context *ctx, unsigned int anonymityLevel, const struct GNUNET_ECRS_URI *uri){ GNUNET_FSUI_SearchList *pos; struct GNUNET_GE_Context *ectx; GNUNET_FSUI_Event event; struct SearchRecordList *srl; struct GNUNET_FS_SearchContext *pc; if (!(GNUNET_ECRS_uri_test_ksk (uri) || GNUNET_ECRS_uri_test_sks (uri))) { GNUNET_GE_BREAK (NULL, 0); return NULL; } pc = GNUNET_FS_create_search_context (ctx->ectx, ctx->cfg); if (pc == NULL) return NULL; ectx = ctx->ectx; pos = GNUNET_malloc (sizeof (GNUNET_FSUI_SearchList)); memset (pos, 0, sizeof (GNUNET_FSUI_SearchList)); pos->probe_context = pc; pos->state = GNUNET_FSUI_ACTIVE; pos->anonymityLevel = anonymityLevel; pos->ctx = ctx; pos->start_time = GNUNET_get_time (); pos->uri = GNUNET_ECRS_uri_duplicate (uri); event.type = GNUNET_FSUI_search_started;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -