+void yf::Frontend::search(Package &package, Z_APDU *apdu,
+ const std::map<std::string, Virt_db_map> &maps)
+{
+ Z_SearchRequest *req = apdu->u.searchRequest;
+ std::string vhost;
+ std::string database;
+ std::string resultSetId = req->resultSetName;
+ bool support_named_result_sets = false; // whether backend supports it
+ yp2::odr odr;
+
+ if (req->num_databaseNames != 1)
+ { // exactly one database must be specified
+ Z_APDU *apdu = zget_APDU(odr, Z_APDU_searchResponse);
+
+ Z_Records *rec = (Z_Records *) odr_malloc(odr, sizeof(Z_Records));
+ apdu->u.searchResponse->records = rec;
+ rec->which = Z_Records_NSD;
+ rec->u.nonSurrogateDiagnostic =
+ zget_DefaultDiagFormat(
+ odr, YAZ_BIB1_TOO_MANY_DATABASES_SPECIFIED, 0);
+ package.response() = apdu;
+
+ return;
+ }
+ database = req->databaseNames[0];
+ std::map<std::string, Virt_db_map>::const_iterator map_it;
+ map_it = maps.find(database);
+ if (map_it == maps.end())
+ { // no map for database: return diagnostic
+ Z_APDU *apdu = zget_APDU(odr, Z_APDU_searchResponse);
+
+ Z_Records *rec = (Z_Records *) odr_malloc(odr, sizeof(Z_Records));
+ apdu->u.searchResponse->records = rec;
+ rec->which = Z_Records_NSD;
+ rec->u.nonSurrogateDiagnostic =
+ zget_DefaultDiagFormat(
+ odr, YAZ_BIB1_DATABASE_DOES_NOT_EXIST, database.c_str());
+ package.response() = apdu;
+
+ return;
+ }
+ if (*req->replaceIndicator == 0)
+ {
+ Sets_it sets_it = m_sets.find(req->resultSetName);
+ if (sets_it != m_sets.end())
+ {
+ Z_APDU *apdu = zget_APDU(odr, Z_APDU_searchResponse);
+
+ Z_Records *rec = (Z_Records *) odr_malloc(odr, sizeof(Z_Records));
+ apdu->u.searchResponse->records = rec;
+ rec->which = Z_Records_NSD;
+ rec->u.nonSurrogateDiagnostic =
+ zget_DefaultDiagFormat(
+ odr,
+ YAZ_BIB1_RESULT_SET_EXISTS_AND_REPLACE_INDICATOR_OFF,
+ 0);
+ package.response() = apdu;
+
+ return;
+ }
+ }
+ m_sets.erase(req->resultSetName);
+ vhost = map_it->second.m_vhost;
+ // we might look for an existing session with same vhost
+ Session id;
+ const char *vhost_cstr = vhost.c_str();
+ if (true)
+ { // sending init to backend
+ Package init_package(id, package.origin());
+ init_package.copy_filter(package);
+
+ Z_APDU *init_apdu = zget_APDU(odr, Z_APDU_initRequest);
+
+ yaz_oi_set_string_oidval(&init_apdu->u.initRequest->otherInfo, odr,
+ VAL_PROXY, 1, vhost_cstr);
+
+ init_package.request() = init_apdu;
+
+ init_package.move(); // sending init
+
+ if (init_package.session().is_closed())
+ {
+ Z_APDU *apdu = zget_APDU(odr, Z_APDU_searchResponse);
+
+ Z_Records *rec = (Z_Records *) odr_malloc(odr, sizeof(Z_Records));
+ apdu->u.searchResponse->records = rec;
+ rec->which = Z_Records_NSD;
+ rec->u.nonSurrogateDiagnostic =
+ zget_DefaultDiagFormat(
+ odr, YAZ_BIB1_DATABASE_UNAVAILABLE, database.c_str());
+ package.response() = apdu;
+ }
+ Z_GDU *gdu = init_package.response().get();
+ // we hope to get an init response
+ if (gdu && gdu->which == Z_GDU_Z3950 && gdu->u.z3950->which ==
+ Z_APDU_initResponse)
+ {
+ if (ODR_MASK_GET(gdu->u.z3950->u.initResponse->options,
+ Z_Options_namedResultSets))
+ support_named_result_sets = true;
+ }
+ else
+ {
+ Z_APDU *apdu = zget_APDU(odr, Z_APDU_searchResponse);
+
+ Z_Records *rec = (Z_Records *) odr_malloc(odr, sizeof(Z_Records));
+ apdu->u.searchResponse->records = rec;
+ rec->which = Z_Records_NSD;
+ rec->u.nonSurrogateDiagnostic =
+ zget_DefaultDiagFormat(
+ odr, YAZ_BIB1_DATABASE_UNAVAILABLE, database.c_str());
+ package.response() = apdu;
+
+ return;
+ }
+ }
+ // sending search to backend
+ Package search_package(id, package.origin());
+
+ search_package.copy_filter(package);
+ const char *sep = strchr(vhost_cstr, '/');
+ if (sep)
+ req->databaseNames[0] = odr_strdup(odr, sep+1);
+
+ *req->replaceIndicator = 1;
+
+ std::string backend_resultSetId = "default";
+ req->resultSetName = odr_strdup(odr, backend_resultSetId.c_str());
+ search_package.request() = yazpp_1::GDU(apdu);
+
+ search_package.move();
+
+ if (search_package.session().is_closed())
+ {
+ Z_APDU *apdu = zget_APDU(odr, Z_APDU_searchResponse);
+
+ Z_Records *rec = (Z_Records *) odr_malloc(odr, sizeof(Z_Records));
+ apdu->u.searchResponse->records = rec;
+ rec->which = Z_Records_NSD;
+ rec->u.nonSurrogateDiagnostic =
+ zget_DefaultDiagFormat(
+ odr, YAZ_BIB1_DATABASE_UNAVAILABLE, database.c_str());
+ package.response() = apdu;
+
+ return;
+ }
+ package.response() = search_package.response();
+
+ m_sets[resultSetId] =
+ Virt_db_set(id, backend_resultSetId, vhost,
+ support_named_result_sets);
+}
+