metaproxy  1.21.0
Public Member Functions | Public Attributes | List of all members
metaproxy_1::filter::Multi::Frontend Struct Reference
Collaboration diagram for metaproxy_1::filter::Multi::Frontend:
Collaboration graph

Public Member Functions

 Frontend (Rep *rep)
 
 ~Frontend ()
 
void multi_move (std::list< BackendPtr > &blist)
 
void init (Package &package, Z_GDU *gdu)
 
void close (Package &package)
 
void search (Package &package, Z_APDU *apdu)
 
void present (Package &package, Z_APDU *apdu)
 
void scan (Package &package, Z_APDU *apdu)
 
void relay_apdu (Package &package, Z_APDU *apdu)
 
void record_diagnostics (Z_Records *records, Z_DiagRecs *&z_diag, ODR odr, int &no_successful)
 

Public Attributes

bool m_is_multi
 
bool m_in_use
 
std::list< BackendPtrm_backend_list
 
std::map< std::string, Multi::FrontendSetm_sets
 
Repm_p
 

Detailed Description

Definition at line 95 of file filter_multi.cpp.

Constructor & Destructor Documentation

◆ Frontend()

mp::filter::Multi::Frontend::Frontend ( Rep rep)

Definition at line 165 of file filter_multi.cpp.

166 {
167  m_p = rep;
168  m_is_multi = false;
169 }

◆ ~Frontend()

mp::filter::Multi::Frontend::~Frontend ( )

Definition at line 171 of file filter_multi.cpp.

172 {
173 }

Member Function Documentation

◆ close()

void mp::filter::Multi::Frontend::close ( Package &  package)

Definition at line 250 of file filter_multi.cpp.

251 {
252  std::list<BackendPtr>::const_iterator bit;
253  for (bit = m_backend_list.begin(); bit != m_backend_list.end(); bit++)
254  {
255  BackendPtr b = *bit;
256 
257  b->m_package->copy_filter(package);
258  b->m_package->request() = (Z_GDU *) 0;
259  b->m_package->session().close();
260  b->m_package->move(b->m_route);
261  }
262 }
boost::shared_ptr< Backend > BackendPtr
std::list< BackendPtr > m_backend_list

◆ init()

void mp::filter::Multi::Frontend::init ( Package &  package,
Z_GDU *  gdu 
)

Definition at line 382 of file filter_multi.cpp.

383 {
384  Z_InitRequest *req = gdu->u.z3950->u.initRequest;
385 
386  std::list<std::string> targets;
387 
388  mp::util::get_vhost_otherinfo(req->otherInfo, targets);
389 
390  if (targets.size() < 1)
391  {
392  package.move();
393  return;
394  }
395 
396  std::list<std::string>::const_iterator t_it = targets.begin();
397  for (; t_it != targets.end(); t_it++)
398  {
399  Session s;
400  Backend *b = new Backend;
401  b->m_vhost = *t_it;
402 
403  std::list<Multi::Map>::const_iterator it =
404  m_p->m_route_patterns.begin();
405  while (it != m_p->m_route_patterns.end()) {
406  if (it->match(*t_it, &b->m_route, &b->m_auth))
407  break;
408  it++;
409  }
410  // b->m_route = m_p->m_target_route[*t_it];
411  // b->m_route unset
412  b->m_package = PackagePtr(new Package(s, package.origin()));
413 
414  m_backend_list.push_back(BackendPtr(b));
415  }
416  m_is_multi = true;
417 
418  // create init request
419  std::list<BackendPtr>::iterator bit;
420  for (bit = m_backend_list.begin(); bit != m_backend_list.end(); bit++)
421  {
422  mp::odr odr;
423  BackendPtr b = *bit;
424  Z_APDU *init_apdu = zget_APDU(odr, Z_APDU_initRequest);
425 
426  std::list<std::string>vhost_one;
427  vhost_one.push_back(b->m_vhost);
428  mp::util::set_vhost_otherinfo(&init_apdu->u.initRequest->otherInfo,
429  odr, vhost_one);
430 
431 
432  Z_InitRequest *breq = init_apdu->u.initRequest;
433 
434  if (b->m_auth.length())
435  {
436  breq->idAuthentication =
437  (Z_IdAuthentication *)
438  odr_malloc(odr, sizeof(*breq->idAuthentication));
439  breq->idAuthentication->which = Z_IdAuthentication_open;
440  breq->idAuthentication->u.open = odr_strdup(odr, b->m_auth.c_str());
441  }
442  else
443  breq->idAuthentication = req->idAuthentication;
444 
445  *breq->preferredMessageSize = *req->preferredMessageSize;
446  *breq->maximumRecordSize = *req->maximumRecordSize;
447 
448 
449  const char *peer_name = yaz_oi_get_string_oid(
450  &req->otherInfo, yaz_oid_userinfo_client_ip, 1, 0);
451  if (peer_name)
452  yaz_oi_set_string_oid(&breq->otherInfo, odr,
453  yaz_oid_userinfo_client_ip, 1, peer_name);
454 
455  ODR_MASK_SET(breq->options, Z_Options_search);
456  ODR_MASK_SET(breq->options, Z_Options_present);
457  ODR_MASK_SET(breq->options, Z_Options_namedResultSets);
458  ODR_MASK_SET(breq->options, Z_Options_scan);
459 
460  ODR_MASK_SET(breq->protocolVersion, Z_ProtocolVersion_1);
461  ODR_MASK_SET(breq->protocolVersion, Z_ProtocolVersion_2);
462  ODR_MASK_SET(breq->protocolVersion, Z_ProtocolVersion_3);
463 
464  b->m_package->request() = init_apdu;
465 
466  b->m_package->copy_filter(package);
467  }
469 
470  // create the frontend init response based on each backend init response
471  mp::odr odr;
472 
473  Z_APDU *f_apdu = odr.create_initResponse(gdu->u.z3950, 0, 0);
474  Z_InitResponse *f_resp = f_apdu->u.initResponse;
475 
476  ODR_MASK_SET(f_resp->options, Z_Options_search);
477  ODR_MASK_SET(f_resp->options, Z_Options_present);
478  ODR_MASK_SET(f_resp->options, Z_Options_namedResultSets);
479  ODR_MASK_SET(f_resp->options, Z_Options_scan);
480 
481  ODR_MASK_SET(f_resp->protocolVersion, Z_ProtocolVersion_1);
482  ODR_MASK_SET(f_resp->protocolVersion, Z_ProtocolVersion_2);
483  ODR_MASK_SET(f_resp->protocolVersion, Z_ProtocolVersion_3);
484 
485  int no_failed = 0;
486  int no_succeeded = 0;
487 
488  Odr_int preferredMessageSize = *req->preferredMessageSize;
489  Odr_int maximumRecordSize = *req->maximumRecordSize;
490  for (bit = m_backend_list.begin(); bit != m_backend_list.end(); )
491  {
492  PackagePtr p = (*bit)->m_package;
493 
494  if (p->session().is_closed())
495  {
496  // failed. Remove from list and increment number of failed
497  no_failed++;
498  bit = m_backend_list.erase(bit);
499  continue;
500  }
501  Z_GDU *gdu = p->response().get();
502  if (gdu && gdu->which == Z_GDU_Z3950 && gdu->u.z3950->which ==
503  Z_APDU_initResponse)
504  {
505  int i;
506  Z_APDU *b_apdu = gdu->u.z3950;
507  Z_InitResponse *b_resp = b_apdu->u.initResponse;
508 
509  // common options for all backends
510  for (i = 0; i <= Z_Options_stringSchema; i++)
511  {
512  if (!ODR_MASK_GET(b_resp->options, i))
513  ODR_MASK_CLEAR(f_resp->options, i);
514  }
515  // common protocol version
516  for (i = 0; i <= Z_ProtocolVersion_3; i++)
517  if (!ODR_MASK_GET(b_resp->protocolVersion, i))
518  ODR_MASK_CLEAR(f_resp->protocolVersion, i);
519  if (*b_resp->result)
520  {
521  no_succeeded++;
522  if (preferredMessageSize > *b_resp->preferredMessageSize)
523  preferredMessageSize = *b_resp->preferredMessageSize;
524  if (maximumRecordSize > *b_resp->maximumRecordSize)
525  maximumRecordSize = *b_resp->maximumRecordSize;
526  }
527  else
528  {
529  if (!f_resp->userInformationField
530  && b_resp->userInformationField)
531  f_resp->userInformationField = b_resp->userInformationField;
532  no_failed++;
533  }
534  }
535  else
536  no_failed++;
537  bit++;
538  }
539  *f_resp->preferredMessageSize = preferredMessageSize;
540  *f_resp->maximumRecordSize = maximumRecordSize;
541 
542  if (m_p->m_hide_unavailable)
543  {
544  if (no_succeeded == 0)
545  {
546  *f_resp->result = 0;
547  package.session().close();
548  }
549  }
550  else
551  {
552  if (no_failed)
553  {
554  *f_resp->result = 0;
555  package.session().close();
556  }
557  }
558  package.response() = f_apdu;
559 }
std::list< Multi::Map > m_route_patterns
boost::shared_ptr< Package > PackagePtr
void multi_move(std::list< BackendPtr > &blist)

References metaproxy_1::filter::Multi::Backend::m_auth, metaproxy_1::filter::Multi::Backend::m_package, metaproxy_1::filter::Multi::Backend::m_route, and metaproxy_1::filter::Multi::Backend::m_vhost.

◆ multi_move()

void mp::filter::Multi::Frontend::multi_move ( std::list< BackendPtr > &  blist)

Definition at line 264 of file filter_multi.cpp.

265 {
266  std::list<BackendPtr>::const_iterator bit;
267  boost::thread_group g;
268  for (bit = blist.begin(); bit != blist.end(); bit++)
269  {
270  g.add_thread(new boost::thread(**bit));
271  }
272  g.join_all();
273 }

◆ present()

void mp::filter::Multi::Frontend::present ( Package &  package,
Z_APDU *  apdu 
)

Definition at line 762 of file filter_multi.cpp.

763 {
764  // create present request
765  Z_PresentRequest *req = apdu_req->u.presentRequest;
766 
767  Sets_it it;
768  it = m_sets.find(std::string(req->resultSetId));
769  if (it == m_sets.end())
770  {
771  mp::odr odr;
772  Z_APDU *apdu =
773  odr.create_presentResponse(
774  apdu_req,
775  YAZ_BIB1_SPECIFIED_RESULT_SET_DOES_NOT_EXIST,
776  req->resultSetId);
777  package.response() = apdu;
778  return;
779  }
780  std::list<Multi::FrontendSet::PresentJob> jobs;
781  int start = *req->resultSetStartPoint;
782  int number = *req->numberOfRecordsRequested;
783 
784  if (m_p->m_merge_type == round_robin)
785  it->second.round_robin(start, number, jobs);
786  else if (m_p->m_merge_type == serve_order)
787  it->second.serve_order(start, number, jobs);
788 
789  if (0)
790  {
791  std::list<Multi::FrontendSet::PresentJob>::const_iterator jit;
792  for (jit = jobs.begin(); jit != jobs.end(); jit++)
793  {
794  yaz_log(YLOG_DEBUG, "job pos=%d", jit->m_pos);
795  }
796  }
797 
798  std::list<BackendPtr> present_backend_list;
799 
800  std::list<BackendSet>::const_iterator bsit;
801  bsit = it->second.m_backend_sets.begin();
802  for (; bsit != it->second.m_backend_sets.end(); bsit++)
803  {
804  int start = -1;
805  int end = -1;
806  {
807  std::list<Multi::FrontendSet::PresentJob>::const_iterator jit;
808  for (jit = jobs.begin(); jit != jobs.end(); jit++)
809  {
810  if (jit->m_backend == bsit->m_backend)
811  {
812  if (start == -1 || jit->m_pos < start)
813  start = jit->m_pos;
814  if (end == -1 || jit->m_pos > end)
815  end = jit->m_pos;
816  }
817  }
818  }
819  if (start != -1)
820  {
821  std::list<Multi::FrontendSet::PresentJob>::iterator jit;
822  for (jit = jobs.begin(); jit != jobs.end(); jit++)
823  {
824  if (jit->m_backend == bsit->m_backend)
825  {
826  if (jit->m_pos >= start && jit->m_pos <= end)
827  jit->m_start = start;
828  }
829  }
830 
831  PackagePtr p = bsit->m_backend->m_package;
832 
833  *req->resultSetStartPoint = start;
834  *req->numberOfRecordsRequested = end - start + 1;
835 
836  p->request() = apdu_req;
837  p->copy_filter(package);
838 
839  present_backend_list.push_back(bsit->m_backend);
840  }
841  }
842  multi_move(present_backend_list);
843 
844  // look at each response
845  Z_DiagRecs *z_diag = 0;
846  int no_successful = 0;
847  mp::odr odr;
848  PackagePtr close_p;
849 
850  std::list<BackendPtr>::const_iterator pbit = present_backend_list.begin();
851  for (; pbit != present_backend_list.end(); pbit++)
852  {
853  PackagePtr p = (*pbit)->m_package;
854 
855  // save closing package for at least one target
856  if (p->session().is_closed())
857  close_p = p;
858 
859  Z_GDU *gdu = p->response().get();
860  if (gdu && gdu->which == Z_GDU_Z3950 && gdu->u.z3950->which ==
861  Z_APDU_presentResponse)
862  {
863  Z_APDU *b_apdu = gdu->u.z3950;
864  Z_PresentResponse *b_resp = b_apdu->u.presentResponse;
865 
866  record_diagnostics(b_resp->records, z_diag, odr, no_successful);
867  }
868  }
869 
870  Z_APDU *f_apdu = odr.create_presentResponse(apdu_req, 0, 0);
871  Z_PresentResponse *f_resp = f_apdu->u.presentResponse;
872 
873  if (close_p && (no_successful == 0 || !m_p->m_hide_errors))
874  {
875  package.session().close();
876  package.response() = close_p->response();
877  return;
878  }
879  if (z_diag && (no_successful == 0 || !m_p->m_hide_errors))
880  {
881  f_resp->records = (Z_Records *)
882  odr_malloc(odr, sizeof(*f_resp->records));
883  if (z_diag->num_diagRecs > 1)
884  {
885  f_resp->records->which = Z_Records_multipleNSD;
886  f_resp->records->u.multipleNonSurDiagnostics = z_diag;
887  }
888  else
889  {
890  f_resp->records->which = Z_Records_NSD;
891  f_resp->records->u.nonSurrogateDiagnostic =
892  z_diag->diagRecs[0]->u.defaultFormat;
893  }
894  }
895  else if (number < 0 || (size_t) number > jobs.size())
896  {
897  f_apdu =
898  odr.create_presentResponse(
899  apdu_req,
900  YAZ_BIB1_PRESENT_REQUEST_OUT_OF_RANGE,
901  0);
902  }
903  else
904  {
905  f_resp->records = (Z_Records *) odr_malloc(odr, sizeof(Z_Records));
906  Z_Records * records = f_resp->records;
907  records->which = Z_Records_DBOSD;
908  records->u.databaseOrSurDiagnostics =
909  (Z_NamePlusRecordList *)
910  odr_malloc(odr, sizeof(Z_NamePlusRecordList));
911  Z_NamePlusRecordList *nprl = records->u.databaseOrSurDiagnostics;
912  nprl->num_records = jobs.size();
913  nprl->records = (Z_NamePlusRecord**)
914  odr_malloc(odr, sizeof(Z_NamePlusRecord *) * nprl->num_records);
915  int i = 0;
916  std::list<Multi::FrontendSet::PresentJob>::const_iterator jit;
917  for (jit = jobs.begin(); jit != jobs.end(); jit++)
918  {
919  PackagePtr p = jit->m_backend->m_package;
920 
921  Z_GDU *gdu = p->response().get();
922  Z_APDU *b_apdu = gdu->u.z3950;
923  int inside_pos = jit->m_pos - jit->m_start;
924  Z_Records *records = b_apdu->u.presentResponse->records;
925 
926  if (records && records->which == Z_Records_DBOSD
927  && inside_pos <
928  records->u.databaseOrSurDiagnostics->num_records)
929  {
930  nprl->records[i] = (Z_NamePlusRecord*)
931  odr_malloc(odr, sizeof(Z_NamePlusRecord));
932  *nprl->records[i] = *records->
933  u.databaseOrSurDiagnostics->records[inside_pos];
934  nprl->records[i]->databaseName =
935  odr_strdup(odr, jit->m_backend->m_vhost.c_str());
936  i++;
937  }
938  }
939  nprl->num_records = i; // usually same as jobs.size();
940  *f_resp->nextResultSetPosition = start + i;
941  *f_resp->numberOfRecordsReturned = i;
942  }
943  package.response() = f_apdu;
944 }
std::map< std::string, FrontendSet >::iterator Sets_it
void record_diagnostics(Z_Records *records, Z_DiagRecs *&z_diag, ODR odr, int &no_successful)
std::map< std::string, Multi::FrontendSet > m_sets

References metaproxy_1::filter::round_robin, and metaproxy_1::filter::serve_order.

◆ record_diagnostics()

void mp::filter::Multi::Frontend::record_diagnostics ( Z_Records *  records,
Z_DiagRecs *&  z_diag,
ODR  odr,
int &  no_successful 
)

Definition at line 561 of file filter_multi.cpp.

565 {
566  // see we get any errors (AKA diagnstics)
567  if (records)
568  {
569  if (records->which == Z_Records_NSD)
570  {
571  if (!z_diag)
572  {
573  z_diag = (Z_DiagRecs *)
574  odr_malloc(odr, sizeof(*z_diag));
575  z_diag->num_diagRecs = 0;
576  z_diag->diagRecs = (Z_DiagRec**)
577  odr_malloc(odr, sizeof(*z_diag->diagRecs));
578  }
579  else
580  {
581  Z_DiagRec **n = (Z_DiagRec **)
582  odr_malloc(odr,
583  (1 + z_diag->num_diagRecs) * sizeof(*n));
584  memcpy(n, z_diag->diagRecs, z_diag->num_diagRecs
585  * sizeof(*n));
586  z_diag->diagRecs = n;
587  }
588  Z_DiagRec *nr = (Z_DiagRec *) odr_malloc(odr, sizeof(*nr));
589  nr->which = Z_DiagRec_defaultFormat;
590  nr->u.defaultFormat =
591  records->u.nonSurrogateDiagnostic;
592  z_diag->diagRecs[z_diag->num_diagRecs++] = nr;
593  }
594  else if (records->which == Z_Records_multipleNSD)
595  {
596  Z_DiagRecs * dr =records->u.multipleNonSurDiagnostics;
597 
598  if (!z_diag)
599  {
600  z_diag = (Z_DiagRecs *) odr_malloc(odr, sizeof(*z_diag));
601  z_diag->num_diagRecs = 0;
602  z_diag->diagRecs = 0;
603  }
604  Z_DiagRec **n = (Z_DiagRec **)
605  odr_malloc(odr,
606  (dr->num_diagRecs + z_diag->num_diagRecs) *
607  sizeof(*n));
608  if (z_diag->num_diagRecs)
609  memcpy(n, z_diag->diagRecs, z_diag->num_diagRecs * sizeof(*n));
610  memcpy(n + z_diag->num_diagRecs,
611  dr->diagRecs, dr->num_diagRecs * sizeof(*n));
612  z_diag->diagRecs = n;
613  z_diag->num_diagRecs += dr->num_diagRecs;
614  }
615  else
616  no_successful++; // probably piggyback
617  }
618  else
619  no_successful++; // no records and no diagnostics
620 }

◆ relay_apdu()

void mp::filter::Multi::Frontend::relay_apdu ( Package &  package,
Z_APDU *  apdu 
)

Definition at line 975 of file filter_multi.cpp.

976 {
977  std::list<BackendPtr>::const_iterator bit;
978  for (bit = m_backend_list.begin(); bit != m_backend_list.end(); bit++)
979  {
980  PackagePtr p = (*bit)->m_package;
981  mp::odr odr;
982 
983  p->request() = apdu_req;
984  p->copy_filter(package);
985  }
987  for (bit = m_backend_list.begin(); bit != m_backend_list.end(); bit++)
988  {
989  PackagePtr p = (*bit)->m_package;
990 
991  if (p->session().is_closed()) // if any backend closes, close frontend
992  package.session().close();
993 
994  package.response() = p->response();
995  }
996 }

◆ scan()

void mp::filter::Multi::Frontend::scan ( Package &  package,
Z_APDU *  apdu 
)

Definition at line 999 of file filter_multi.cpp.

1000 {
1001  Z_ScanRequest *req = apdu_req->u.scanRequest;
1002 
1003  std::list<BackendPtr>::const_iterator bit;
1004  for (bit = m_backend_list.begin(); bit != m_backend_list.end(); bit++)
1005  {
1006  PackagePtr p = (*bit)->m_package;
1007  yazpp_1::GDU gdu1(apdu_req);
1008  mp::odr odr;
1009  Z_ScanRequest *req1 = gdu1.get()->u.z3950->u.scanRequest;
1010 
1011  if (!mp::util::set_databases_from_zurl(odr, (*bit)->m_vhost,
1012  &req1->num_databaseNames,
1013  &req1->databaseNames))
1014  {
1015  req1->num_databaseNames = req->num_databaseNames;
1016  req1->databaseNames = req->databaseNames;
1017  }
1018  p->request() = gdu1;
1019  p->copy_filter(package);
1020  }
1022 
1023  ScanTermInfoList entries_before;
1024  ScanTermInfoList entries_after;
1025  int no_before = 0;
1026  int no_after = 0;
1027 
1028  for (bit = m_backend_list.begin(); bit != m_backend_list.end(); bit++)
1029  {
1030  PackagePtr p = (*bit)->m_package;
1031 
1032  if (p->session().is_closed()) // if any backend closes, close frontend
1033  package.session().close();
1034 
1035  Z_GDU *gdu = p->response().get();
1036  if (gdu && gdu->which == Z_GDU_Z3950 && gdu->u.z3950->which ==
1037  Z_APDU_scanResponse)
1038  {
1039  Z_ScanResponse *res = gdu->u.z3950->u.scanResponse;
1040 
1041  if (res->entries && res->entries->nonsurrogateDiagnostics)
1042  {
1043  // failure
1044  mp::odr odr;
1045  Z_APDU *f_apdu = odr.create_scanResponse(apdu_req, 1, 0);
1046  Z_ScanResponse *f_res = f_apdu->u.scanResponse;
1047 
1048  f_res->entries->nonsurrogateDiagnostics =
1049  res->entries->nonsurrogateDiagnostics;
1050  f_res->entries->num_nonsurrogateDiagnostics =
1051  res->entries->num_nonsurrogateDiagnostics;
1052 
1053  package.response() = f_apdu;
1054  return;
1055  }
1056 
1057  if (res->entries && res->entries->entries)
1058  {
1059  Z_Entry **entries = res->entries->entries;
1060  int num_entries = res->entries->num_entries;
1061  int position = 1;
1062  if (req->preferredPositionInResponse)
1063  position = *req->preferredPositionInResponse;
1064  if (res->positionOfTerm)
1065  position = *res->positionOfTerm;
1066 
1067  // before
1068  int i;
1069  for (i = 0; i<position-1 && i<num_entries; i++)
1070  {
1071  Z_Entry *ent = entries[i];
1072 
1073  if (ent->which == Z_Entry_termInfo)
1074  {
1075  ScanTermInfo my;
1076 
1077  Odr_int *occur = ent->u.termInfo->globalOccurrences;
1078  my.m_count = occur ? *occur : 0;
1079 
1080  if (ent->u.termInfo->term->which == Z_Term_general)
1081  {
1082  my.m_norm_term = std::string(
1083  (const char *)
1084  ent->u.termInfo->term->u.general->buf,
1085  ent->u.termInfo->term->u.general->len);
1086  }
1087  if (my.m_norm_term.length())
1088  {
1089  ScanTermInfoList::iterator it =
1090  entries_before.begin();
1091  while (it != entries_before.end() && my <*it)
1092  it++;
1093  if (it != entries_before.end() && my == *it)
1094  {
1095  it->m_count += my.m_count;
1096  }
1097  else
1098  {
1099  entries_before.insert(it, my);
1100  no_before++;
1101  }
1102  }
1103  }
1104  }
1105  // after
1106  if (position <= 0)
1107  i = 0;
1108  else
1109  i = position-1;
1110  for ( ; i<num_entries; i++)
1111  {
1112  Z_Entry *ent = entries[i];
1113 
1114  if (ent->which == Z_Entry_termInfo)
1115  {
1116  ScanTermInfo my;
1117 
1118  Odr_int *occur = ent->u.termInfo->globalOccurrences;
1119  my.m_count = occur ? *occur : 0;
1120 
1121  if (ent->u.termInfo->term->which == Z_Term_general)
1122  {
1123  my.m_norm_term = std::string(
1124  (const char *)
1125  ent->u.termInfo->term->u.general->buf,
1126  ent->u.termInfo->term->u.general->len);
1127  }
1128  if (my.m_norm_term.length())
1129  {
1130  ScanTermInfoList::iterator it =
1131  entries_after.begin();
1132  while (it != entries_after.end() && *it < my)
1133  it++;
1134  if (it != entries_after.end() && my == *it)
1135  {
1136  it->m_count += my.m_count;
1137  }
1138  else
1139  {
1140  entries_after.insert(it, my);
1141  no_after++;
1142  }
1143  }
1144  }
1145  }
1146 
1147  }
1148  }
1149  else
1150  {
1151  // if any target does not return scan response - return that
1152  package.response() = p->response();
1153  return;
1154  }
1155  }
1156 
1157  if (false)
1158  {
1159  std::cout << "BEFORE\n";
1160  ScanTermInfoList::iterator it = entries_before.begin();
1161  for(; it != entries_before.end(); it++)
1162  {
1163  std::cout << " " << it->m_norm_term << " " << it->m_count << "\n";
1164  }
1165 
1166  std::cout << "AFTER\n";
1167  it = entries_after.begin();
1168  for(; it != entries_after.end(); it++)
1169  {
1170  std::cout << " " << it->m_norm_term << " " << it->m_count << "\n";
1171  }
1172  }
1173 
1174  if (false)
1175  {
1176  mp::odr odr;
1177  Z_APDU *f_apdu = odr.create_scanResponse(apdu_req, 1, "not implemented");
1178  package.response() = f_apdu;
1179  }
1180  else
1181  {
1182  mp::odr odr;
1183  Z_APDU *f_apdu = odr.create_scanResponse(apdu_req, 0, 0);
1184  Z_ScanResponse *resp = f_apdu->u.scanResponse;
1185 
1186  int number_returned = *req->numberOfTermsRequested;
1187  int position_returned = *req->preferredPositionInResponse;
1188 
1189  resp->entries->num_entries = number_returned;
1190  resp->entries->entries = (Z_Entry**)
1191  odr_malloc(odr, sizeof(Z_Entry*) * number_returned);
1192  int i;
1193 
1194  int lbefore = entries_before.size();
1195  if (lbefore < position_returned-1)
1196  position_returned = lbefore+1;
1197 
1198  ScanTermInfoList::iterator it = entries_before.begin();
1199  for (i = 0; i<position_returned-1 && it != entries_before.end(); i++, it++)
1200  {
1201  resp->entries->entries[position_returned-2-i] = it->get_entry(odr);
1202  }
1203 
1204  it = entries_after.begin();
1205 
1206  if (position_returned <= 0)
1207  i = 0;
1208  else
1209  i = position_returned-1;
1210  for (; i<number_returned && it != entries_after.end(); i++, it++)
1211  {
1212  resp->entries->entries[i] = it->get_entry(odr);
1213  }
1214 
1215  number_returned = i;
1216 
1217  resp->positionOfTerm = odr_intdup(odr, position_returned);
1218  resp->numberOfEntriesReturned = odr_intdup(odr, number_returned);
1219  resp->entries->num_entries = number_returned;
1220 
1221  package.response() = f_apdu;
1222  }
1223 }
std::list< ScanTermInfo > ScanTermInfoList

References metaproxy_1::filter::Multi::ScanTermInfo::m_count, and metaproxy_1::filter::Multi::ScanTermInfo::m_norm_term.

◆ search()

void mp::filter::Multi::Frontend::search ( Package &  package,
Z_APDU *  apdu 
)

Definition at line 622 of file filter_multi.cpp.

623 {
624  // create search request
625  Z_SearchRequest *req = apdu_req->u.searchRequest;
626 
627  std::list<BackendPtr>::const_iterator bit;
628  for (bit = m_backend_list.begin(); bit != m_backend_list.end(); bit++)
629  {
630  PackagePtr p = (*bit)->m_package;
631  yazpp_1::GDU gdu1(apdu_req);
632  mp::odr odr;
633  Z_SearchRequest *req1 = gdu1.get()->u.z3950->u.searchRequest;
634 
635  // they are altered now - to disable piggyback
636  *req1->smallSetUpperBound = 0;
637  *req1->largeSetLowerBound = 1;
638  *req1->mediumSetPresentNumber = 0;
639 
640  if (!mp::util::set_databases_from_zurl(odr, (*bit)->m_vhost,
641  &req1->num_databaseNames,
642  &req1->databaseNames))
643  {
644  req1->num_databaseNames = req->num_databaseNames;
645  req1->databaseNames = req->databaseNames;
646  }
647  p->request() = gdu1;
648  p->copy_filter(package);
649  }
651 
652  // look at each response
653  FrontendSet resultSet(std::string(req->resultSetName));
654 
655  mp::odr odr;
656  Odr_int result_set_size = 0;
657  Z_DiagRecs *z_diag = 0;
658  int no_successful = 0;
659  PackagePtr close_p;
660 
661  for (bit = m_backend_list.begin(); bit != m_backend_list.end(); bit++)
662  {
663  PackagePtr p = (*bit)->m_package;
664 
665  // save closing package for at least one target
666  if (p->session().is_closed())
667  close_p = p;
668 
669  Z_GDU *gdu = p->response().get();
670  if (gdu && gdu->which == Z_GDU_Z3950 && gdu->u.z3950->which ==
671  Z_APDU_searchResponse)
672  {
673  Z_APDU *b_apdu = gdu->u.z3950;
674  Z_SearchResponse *b_resp = b_apdu->u.searchResponse;
675 
676  record_diagnostics(b_resp->records, z_diag, odr, no_successful);
677 
678  BackendSet backendSet;
679  backendSet.m_backend = *bit;
680  backendSet.m_count = *b_resp->resultCount;
681  result_set_size += *b_resp->resultCount;
682  resultSet.m_backend_sets.push_back(backendSet);
683  }
684  }
685 
686  Z_APDU *f_apdu = odr.create_searchResponse(apdu_req, 0, 0);
687  Z_SearchResponse *f_resp = f_apdu->u.searchResponse;
688 
689  yaz_log(YLOG_DEBUG, "no_successful=%d is_closed=%s hide_errors=%s",
690  no_successful,
691  close_p ? "true" : "false",
692  m_p->m_hide_errors ? "true" : "false");
693  *f_resp->resultCount = result_set_size;
694  if (close_p && (no_successful == 0 || !m_p->m_hide_unavailable))
695  {
696  package.session().close();
697  package.response() = close_p->response();
698  return;
699  }
700  if (z_diag && (no_successful == 0 || !m_p->m_hide_errors))
701  {
702  f_resp->records = (Z_Records *)
703  odr_malloc(odr, sizeof(*f_resp->records));
704  if (z_diag->num_diagRecs > 1)
705  {
706  f_resp->records->which = Z_Records_multipleNSD;
707  f_resp->records->u.multipleNonSurDiagnostics = z_diag;
708  }
709  else
710  {
711  f_resp->records->which = Z_Records_NSD;
712  f_resp->records->u.nonSurrogateDiagnostic =
713  z_diag->diagRecs[0]->u.defaultFormat;
714  }
715  }
716  // assume OK
717  m_sets[resultSet.m_setname] = resultSet;
718 
719  Odr_int number;
720  mp::util::piggyback(*req->smallSetUpperBound,
721  *req->largeSetLowerBound,
722  *req->mediumSetPresentNumber,
723  0, 0,
725  number, 0);
726  Package pp(package.session(), package.origin());
727  if (z_diag == 0 && number > 0)
728  {
729  pp.copy_filter(package);
730  Z_APDU *p_apdu = zget_APDU(odr, Z_APDU_presentRequest);
731  Z_PresentRequest *p_req = p_apdu->u.presentRequest;
732  p_req->preferredRecordSyntax = req->preferredRecordSyntax;
733  p_req->resultSetId = req->resultSetName;
734  *p_req->resultSetStartPoint = 1;
735  *p_req->numberOfRecordsRequested = number;
736  pp.request() = p_apdu;
737  present(pp, p_apdu);
738 
739  if (pp.session().is_closed())
740  package.session().close();
741 
742  Z_GDU *gdu = pp.response().get();
743  if (gdu && gdu->which == Z_GDU_Z3950 && gdu->u.z3950->which ==
744  Z_APDU_presentResponse)
745  {
746  Z_PresentResponse *p_res = gdu->u.z3950->u.presentResponse;
747  f_resp->records = p_res->records;
748  *f_resp->numberOfRecordsReturned =
749  *p_res->numberOfRecordsReturned;
750  *f_resp->nextResultSetPosition =
751  *p_res->nextResultSetPosition;
752  }
753  else
754  {
755  package.response() = pp.response();
756  return;
757  }
758  }
759  package.response() = f_apdu; // in this scope because of p
760 }
static const int result_set_size
void present(Package &package, Z_APDU *apdu)

References metaproxy_1::filter::Multi::BackendSet::m_backend, metaproxy_1::filter::Multi::FrontendSet::m_backend_sets, metaproxy_1::filter::Multi::BackendSet::m_count, metaproxy_1::filter::Multi::FrontendSet::m_setname, and result_set_size.

Member Data Documentation

◆ m_backend_list

std::list<BackendPtr> metaproxy_1::filter::Multi::Frontend::m_backend_list

Definition at line 100 of file filter_multi.cpp.

◆ m_in_use

bool metaproxy_1::filter::Multi::Frontend::m_in_use

Definition at line 99 of file filter_multi.cpp.

◆ m_is_multi

bool metaproxy_1::filter::Multi::Frontend::m_is_multi

Definition at line 98 of file filter_multi.cpp.

◆ m_p

Rep* metaproxy_1::filter::Multi::Frontend::m_p

Definition at line 114 of file filter_multi.cpp.

◆ m_sets

std::map<std::string,Multi::FrontendSet> metaproxy_1::filter::Multi::Frontend::m_sets

Definition at line 101 of file filter_multi.cpp.


The documentation for this struct was generated from the following file: