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

Public Member Functions

 Frontend (Rep *rep)
 
 ~Frontend ()
 
void search (Package &package, Z_APDU *apdu)
 
void present (Package &package, Z_APDU *apdu)
 
void scan (Package &package, Z_APDU *apdu)
 
int result_set_ref (ODR o, const Databases &databases, Z_RPNStructure *s, std::string &rset)
 
void get_set (mp::Package &package, const Z_APDU *apdu_req, const Databases &databases, yazpp_1::Yaz_Z_Query &query, BackendInstancePtr &found_backend, BackendSetPtr &found_set)
 
void override_set (BackendInstancePtr &found_backend, std::string &result_set_id, const Databases &databases, bool out_of_sessions)
 

Public Attributes

bool m_is_virtual
 
bool m_in_use
 
Z_Options m_init_options
 
Repm_p
 
BackendClassPtr m_backend_class
 
FrontendSets m_frontend_sets
 

Detailed Description

Definition at line 166 of file filter_session_shared.cpp.

Constructor & Destructor Documentation

◆ Frontend()

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

◆ ~Frontend()

mp::filter::SessionShared::Frontend::~Frontend ( )

Definition at line 1440 of file filter_session_shared.cpp.

1441 {
1442 }

Member Function Documentation

◆ get_set()

void mp::filter::SessionShared::Frontend::get_set ( mp::Package &  package,
const Z_APDU *  apdu_req,
const Databases databases,
yazpp_1::Yaz_Z_Query &  query,
BackendInstancePtr found_backend,
BackendSetPtr found_set 
)

Definition at line 809 of file filter_session_shared.cpp.

815 {
816  bool session_restarted = false;
817  Z_OtherInformation *additionalSearchInfo = 0;
818 
819  if (apdu_req->which == Z_APDU_searchRequest)
820  additionalSearchInfo = apdu_req->u.searchRequest->additionalSearchInfo;
821 
822 restart:
823  std::string result_set_id;
824  bool out_of_sessions = false;
826  {
827  boost::mutex::scoped_lock lock(bc->m_mutex_backend_class);
828 
829  if ((int) bc->m_backend_list.size() >= m_p->m_session_max)
830  out_of_sessions = true;
831 
832  if (m_p->m_optimize_search)
833  {
834  // look at each backend and see if we have a similar search
835  BackendInstanceList::const_iterator it = bc->m_backend_list.begin();
836  while (it != bc->m_backend_list.end())
837  {
838  bool restart = false;
839  BackendSetList::const_iterator set_it = (*it)->m_sets.begin();
840  for (; set_it != (*it)->m_sets.end(); set_it++)
841  {
842  // for real present request we don't care
843  // if additionalSearchInfo matches: same records
844  if (mp::util::match((*set_it)->m_databases, databases)
845  && query.match(&(*set_it)->m_query)
846  && (apdu_req->which != Z_APDU_searchRequest ||
847  yaz_compare_z_OtherInformation(
848  additionalSearchInfo,
849  (*set_it)->additionalSearchInfoRequest)))
850  {
851  if ((*it)->m_in_use)
852  {
853  bc->m_cond_set_ready.wait(lock);
854  restart = true;
855  break;
856  }
857  else
858  {
859  found_set = *set_it;
860  found_backend = *it;
861  bc->use_backend(found_backend);
862  // found matching set. No need to search again
863  return;
864  }
865  }
866  }
867  if (restart)
868  it = bc->m_backend_list.begin();
869  else
870  it++;
871  }
872  }
873  override_set(found_backend, result_set_id, databases, out_of_sessions);
874  if (found_backend)
875  bc->use_backend(found_backend);
876  }
877  if (!found_backend)
878  {
879  int code;
880  std::string addinfo;
881  // create a new backend set (and new set) if we're not out of sessions
882  if (!out_of_sessions)
883  found_backend = bc->create_backend(package, code, addinfo);
884  if (!found_backend)
885  {
886  Z_APDU *f_apdu = 0;
887  mp::odr odr;
888 
889  if (out_of_sessions)
890  {
891  code = YAZ_BIB1_TEMPORARY_SYSTEM_ERROR;
892  addinfo = "session_shared: all sessions in use";
893  }
894  else
895  {
896  if (code == 0)
897  code = YAZ_BIB1_TEMPORARY_SYSTEM_ERROR;
898  if (addinfo.length() == 0)
899  addinfo = "session_shared: could not create backend";
900  }
901  if (apdu_req->which == Z_APDU_searchRequest)
902  {
903  f_apdu = odr.create_searchResponse(
904  apdu_req, YAZ_BIB1_TEMPORARY_SYSTEM_ERROR, addinfo.c_str());
905  }
906  else if (apdu_req->which == Z_APDU_presentRequest)
907  {
908  f_apdu = odr.create_presentResponse(
909  apdu_req, YAZ_BIB1_TEMPORARY_SYSTEM_ERROR, addinfo.c_str());
910  }
911  else
912  {
913  f_apdu = odr.create_close(
914  apdu_req, YAZ_BIB1_TEMPORARY_SYSTEM_ERROR, addinfo.c_str());
915  }
916  package.response() = f_apdu;
917  return;
918  }
919  if (bc->m_named_result_sets)
920  {
921  result_set_id = boost::io::str(
922  boost::format("%1%") % found_backend->m_result_set_sequence);
923  found_backend->m_result_set_sequence++;
924  }
925  else
926  result_set_id = "default";
927  }
928  found_backend->timestamp();
929 
930  // we must search ...
931  BackendSetPtr new_set(new BackendSet(result_set_id,
932  databases, query,
933  additionalSearchInfo));
934 
935  found_set = new_set;
936  found_set->timestamp();
937 
938  Z_Records *z_records = 0;
939 
940  Package search_package(found_backend->m_session, package.origin());
941  search_package.copy_filter(package);
942 
943  if (!new_set->search(package, search_package,
944  apdu_req, found_backend, &z_records))
945  {
946  bc->remove_backend(found_backend);
947  found_set.reset();
948  return; // search error
949  }
950 
951  if (z_records)
952  {
953  int condition = 0;
954  if (z_records->which == Z_Records_NSD)
955  {
956  condition =
957  get_diagnostic(z_records->u.nonSurrogateDiagnostic);
958  }
959  else if (z_records->which == Z_Records_multipleNSD)
960  {
961  if (z_records->u.multipleNonSurDiagnostics->num_diagRecs >= 1
962  &&
963 
964  z_records->u.multipleNonSurDiagnostics->diagRecs[0]->which ==
965  Z_DiagRec_defaultFormat)
966  {
967  condition = get_diagnostic(
968  z_records->u.multipleNonSurDiagnostics->diagRecs[0]->u.defaultFormat);
969 
970  }
971  }
972  if (m_p->m_restart && !session_restarted &&
973  condition == YAZ_BIB1_TEMPORARY_SYSTEM_ERROR)
974  {
975  package.log("session_shared", YLOG_LOG, "restart");
976  bc->remove_backend(found_backend);
977  session_restarted = true;
978  found_backend.reset();
979  goto restart;
980 
981  }
982 
983  if (condition)
984  {
985  mp::odr odr;
986  if (apdu_req->which == Z_APDU_searchRequest)
987  {
988  Z_APDU *f_apdu = odr.create_searchResponse(apdu_req,
989  0, 0);
990  Z_SearchResponse *f_resp = f_apdu->u.searchResponse;
991  *f_resp->searchStatus = Z_SearchResponse_none;
992  f_resp->records = z_records;
993  package.response() = f_apdu;
994  }
995  if (apdu_req->which == Z_APDU_presentRequest)
996  {
997  Z_APDU *f_apdu = odr.create_presentResponse(apdu_req,
998  0, 0);
999  Z_PresentResponse *f_resp = f_apdu->u.presentResponse;
1000  f_resp->records = z_records;
1001  package.response() = f_apdu;
1002  }
1003  bc->release_backend(found_backend);
1004  found_set.reset();
1005  return; // search error
1006  }
1007  }
1008  if (m_p->m_restart && !session_restarted && new_set->m_result_set_size < 0)
1009  {
1010  package.log("session_shared", YLOG_LOG, "restart");
1011  bc->remove_backend(found_backend);
1012  session_restarted = true;
1013  found_backend.reset();
1014  goto restart;
1015  }
1016  found_backend->m_sets.push_back(found_set);
1017 }
boost::shared_ptr< BackendSet > BackendSetPtr
boost::shared_ptr< BackendClass > BackendClassPtr
static int get_diagnostic(Z_DefaultDiagFormat *r)
void override_set(BackendInstancePtr &found_backend, std::string &result_set_id, const Databases &databases, bool out_of_sessions)

References get_diagnostic(), and metaproxy_1::filter::SessionShared::m_p.

Here is the call graph for this function:

◆ override_set()

void mp::filter::SessionShared::Frontend::override_set ( BackendInstancePtr found_backend,
std::string &  result_set_id,
const Databases databases,
bool  out_of_sessions 
)

Definition at line 755 of file filter_session_shared.cpp.

760 {
762  BackendInstanceList::const_iterator it = bc->m_backend_list.begin();
763  time_t now;
764  time(&now);
765 
766  size_t max_sets = bc->m_named_result_sets ? bc->m_backend_set_max : 1;
767  for (; it != bc->m_backend_list.end(); it++)
768  {
769  if (!(*it)->m_in_use)
770  {
771  BackendSetList::iterator set_it = (*it)->m_sets.begin();
772  for (; set_it != (*it)->m_sets.end(); set_it++)
773  {
774  bool same_databases = mp::util::match((*set_it)->m_databases,
775  databases);
776  if ((max_sets > 1 || same_databases)
777  &&
778  (out_of_sessions ||
779  now < (*set_it)->m_time_last_use ||
780  now - (*set_it)->m_time_last_use >= bc->m_backend_set_ttl))
781  {
782  found_backend = *it;
783  result_set_id = (*set_it)->m_result_set_id;
784  found_backend->m_sets.erase(set_it);
785  return;
786  }
787  }
788  }
789  }
790  for (it = bc->m_backend_list.begin(); it != bc->m_backend_list.end(); it++)
791  {
792  if (!(*it)->m_in_use && (*it)->m_sets.size() < max_sets)
793  {
794  found_backend = *it;
795  if (bc->m_named_result_sets)
796  {
797  result_set_id = boost::io::str(
798  boost::format("%1%") %
799  found_backend->m_result_set_sequence);
800  found_backend->m_result_set_sequence++;
801  }
802  else
803  result_set_id = "default";
804  return;
805  }
806  }
807 }

◆ present()

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

Definition at line 1142 of file filter_session_shared.cpp.

1144 {
1145  mp::odr odr;
1146  Z_PresentRequest *req = apdu_req->u.presentRequest;
1147 
1148  FrontendSets::iterator fset_it =
1149  m_frontend_sets.find(req->resultSetId);
1150 
1151  if (fset_it == m_frontend_sets.end())
1152  {
1153  Z_APDU *apdu =
1154  odr.create_presentResponse(
1155  apdu_req,
1156  YAZ_BIB1_SPECIFIED_RESULT_SET_DOES_NOT_EXIST,
1157  req->resultSetId);
1158  package.response() = apdu;
1159  return;
1160  }
1161  FrontendSetPtr fset = fset_it->second;
1162 
1163  Databases databases = fset->get_databases();
1164  yazpp_1::Yaz_Z_Query query = fset->get_query();
1165 
1167  BackendSetPtr found_set; // null
1168  BackendInstancePtr found_backend;
1169 
1170  get_set(package, apdu_req, databases, query, found_backend, found_set);
1171  if (!found_set)
1172  return;
1173 
1174  Z_NamePlusRecordList *npr_res = 0;
1175  // record_cache.lookup types are int's. Avoid non-fitting values
1176  if (*req->resultSetStartPoint > 0
1177  && *req->resultSetStartPoint < INT_MAX
1178  && *req->numberOfRecordsRequested > 0
1179  && *req->numberOfRecordsRequested < INT_MAX
1180  && found_set->m_record_cache.lookup(odr, &npr_res,
1181  *req->resultSetStartPoint,
1182  *req->numberOfRecordsRequested,
1183  req->preferredRecordSyntax,
1184  req->recordComposition))
1185  {
1186  Z_APDU *f_apdu_res = odr.create_presentResponse(apdu_req, 0, 0);
1187  Z_PresentResponse *f_resp = f_apdu_res->u.presentResponse;
1188 
1189  yaz_log(YLOG_LOG, "Found " ODR_INT_PRINTF "+" ODR_INT_PRINTF
1190  " records in cache %p",
1191  *req->resultSetStartPoint,
1192  *req->numberOfRecordsRequested,
1193  &found_set->m_record_cache);
1194 
1195  *f_resp->numberOfRecordsReturned = *req->numberOfRecordsRequested;
1196  *f_resp->nextResultSetPosition =
1197  *req->resultSetStartPoint + *req->numberOfRecordsRequested;
1198  // f_resp->presentStatus assumed OK.
1199  f_resp->records = (Z_Records *) odr_malloc(odr, sizeof(Z_Records));
1200  f_resp->records->which = Z_Records_DBOSD;
1201  f_resp->records->u.databaseOrSurDiagnostics = npr_res;
1202  package.response() = f_apdu_res;
1203  bc->release_backend(found_backend);
1204  return;
1205  }
1206 
1207  found_backend->timestamp();
1208 
1209  Z_APDU *p_apdu = zget_APDU(odr, Z_APDU_presentRequest);
1210  Z_PresentRequest *p_req = p_apdu->u.presentRequest;
1211  p_req->preferredRecordSyntax = req->preferredRecordSyntax;
1212  p_req->resultSetId = odr_strdup(odr, found_set->m_result_set_id.c_str());
1213  *p_req->resultSetStartPoint = *req->resultSetStartPoint;
1214  *p_req->numberOfRecordsRequested = *req->numberOfRecordsRequested;
1215  p_req->preferredRecordSyntax = req->preferredRecordSyntax;
1216  p_req->recordComposition = req->recordComposition;
1217 
1218  Package present_package(found_backend->m_session, package.origin());
1219  present_package.copy_filter(package);
1220 
1221  present_package.request() = p_apdu;
1222 
1223  present_package.move();
1224 
1225  Z_GDU *gdu = present_package.response().get();
1226  if (!present_package.session().is_closed()
1227  && gdu && gdu->which == Z_GDU_Z3950
1228  && gdu->u.z3950->which == Z_APDU_presentResponse)
1229  {
1230  Z_PresentResponse *b_resp = gdu->u.z3950->u.presentResponse;
1231  Z_APDU *f_apdu_res = odr.create_presentResponse(apdu_req, 0, 0);
1232  Z_PresentResponse *f_resp = f_apdu_res->u.presentResponse;
1233 
1234  f_resp->numberOfRecordsReturned = b_resp->numberOfRecordsReturned;
1235  f_resp->nextResultSetPosition = b_resp->nextResultSetPosition;
1236  f_resp->presentStatus= b_resp->presentStatus;
1237  f_resp->records = b_resp->records;
1238  f_resp->otherInfo = b_resp->otherInfo;
1239  package.response() = f_apdu_res;
1240 
1241  if (b_resp->records && b_resp->records->which == Z_Records_DBOSD)
1242  {
1243  Z_NamePlusRecordList *npr =
1244  b_resp->records->u.databaseOrSurDiagnostics;
1245  // record_cache.add types are int's. Avoid non-fitting values
1246  if (*req->resultSetStartPoint > 0
1247  && npr->num_records + *req->resultSetStartPoint < INT_MAX)
1248  {
1249 #if 0
1250  yaz_log(YLOG_LOG, "Adding " ODR_INT_PRINTF "+" ODR_INT_PRINTF
1251  " records to cache %p",
1252  *req->resultSetStartPoint,
1253  *f_resp->numberOfRecordsReturned,
1254  &found_set->m_record_cache);
1255 #endif
1256  found_set->m_record_cache.add(
1257  odr, npr, *req->resultSetStartPoint,
1258  p_req->recordComposition);
1259  }
1260  }
1261  bc->release_backend(found_backend);
1262  }
1263  else
1264  {
1265  bc->remove_backend(found_backend);
1266  Z_APDU *f_apdu_res =
1267  odr.create_presentResponse(
1268  apdu_req, YAZ_BIB1_TEMPORARY_SYSTEM_ERROR,
1269  "session_shared: target closed connection during present");
1270  package.response() = f_apdu_res;
1271  }
1272 }
boost::shared_ptr< BackendInstance > BackendInstancePtr
boost::shared_ptr< FrontendSet > FrontendSetPtr
void get_set(mp::Package &package, const Z_APDU *apdu_req, const Databases &databases, yazpp_1::Yaz_Z_Query &query, BackendInstancePtr &found_backend, BackendSetPtr &found_set)

◆ result_set_ref()

int mp::filter::SessionShared::Frontend::result_set_ref ( ODR  o,
const Databases databases,
Z_RPNStructure *  s,
std::string &  rset 
)

Definition at line 1019 of file filter_session_shared.cpp.

1023 {
1024  int ret = 0;
1025  switch (s->which)
1026  {
1027  case Z_RPNStructure_simple:
1028  if (s->u.simple->which == Z_Operand_resultSetId)
1029  {
1030  const char *id = s->u.simple->u.resultSetId;
1031  rset = id;
1032 
1033  FrontendSets::iterator fset_it = m_frontend_sets.find(id);
1034  if (fset_it == m_frontend_sets.end())
1035  {
1036  ret = YAZ_BIB1_SPECIFIED_RESULT_SET_DOES_NOT_EXIST;
1037  }
1038  else if (!mp::util::match(fset_it->second->get_databases(),
1039  databases))
1040  {
1041  ret = YAZ_BIB1_SPECIFIED_RESULT_SET_DOES_NOT_EXIST;
1042  }
1043  else
1044  {
1045  yazpp_1::Yaz_Z_Query query = fset_it->second->get_query();
1046  Z_Query *q = yaz_copy_Z_Query(query.get_Z_Query(), o);
1047  if (q->which == Z_Query_type_1 || q->which == Z_Query_type_101)
1048  {
1049  s->which = q->u.type_1->RPNStructure->which;
1050  s->u.simple = q->u.type_1->RPNStructure->u.simple;
1051  }
1052  else
1053  {
1054  ret = YAZ_BIB1_SPECIFIED_RESULT_SET_DOES_NOT_EXIST;
1055  }
1056  }
1057  }
1058  break;
1059  case Z_RPNStructure_complex:
1060  ret = result_set_ref(o, databases, s->u.complex->s1, rset);
1061  if (!ret)
1062  ret = result_set_ref(o, databases, s->u.complex->s2, rset);
1063  break;
1064  }
1065  return ret;
1066 }
int result_set_ref(ODR o, const Databases &databases, Z_RPNStructure *s, std::string &rset)

◆ scan()

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

Definition at line 1274 of file filter_session_shared.cpp.

1276 {
1278  int code;
1279  std::string addinfo;
1280  BackendInstancePtr backend = bc->get_backend(frontend_package,
1281  code, addinfo);
1282  if (!backend)
1283  {
1284  mp::odr odr;
1285  if (code == 0)
1286  code = YAZ_BIB1_TEMPORARY_SYSTEM_ERROR;
1287  if (addinfo.length() == 0)
1288  addinfo = "session_shared: could not create backend";
1289  Z_APDU *apdu = odr.create_scanResponse(
1290  apdu_req, code, addinfo.c_str());
1291  frontend_package.response() = apdu;
1292  }
1293  else
1294  {
1295  Package scan_package(backend->m_session, frontend_package.origin());
1296  backend->timestamp();
1297  scan_package.copy_filter(frontend_package);
1298  scan_package.request() = apdu_req;
1299  scan_package.move();
1300  frontend_package.response() = scan_package.response();
1301  if (scan_package.session().is_closed())
1302  {
1303  frontend_package.session().close();
1304  bc->remove_backend(backend);
1305  }
1306  else
1307  bc->release_backend(backend);
1308  }
1309 }

◆ search()

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

Definition at line 1068 of file filter_session_shared.cpp.

1070 {
1071  Z_SearchRequest *req = apdu_req->u.searchRequest;
1072  FrontendSets::iterator fset_it =
1073  m_frontend_sets.find(req->resultSetName);
1074  if (fset_it != m_frontend_sets.end())
1075  {
1076  // result set already exist
1077  // if replace indicator is off: we return diagnostic if
1078  // result set already exist.
1079  if (*req->replaceIndicator == 0)
1080  {
1081  mp::odr odr;
1082  Z_APDU *apdu =
1083  odr.create_searchResponse(
1084  apdu_req,
1085  YAZ_BIB1_RESULT_SET_EXISTS_AND_REPLACE_INDICATOR_OFF,
1086  0);
1087  package.response() = apdu;
1088  return;
1089  }
1090  m_frontend_sets.erase(fset_it);
1091  }
1092 
1093  Databases databases;
1094  int i;
1095  for (i = 0; i < req->num_databaseNames; i++)
1096  databases.push_back(req->databaseNames[i]);
1097 
1098 
1099  yazpp_1::Yaz_Z_Query query;
1100  query.set_Z_Query(req->query);
1101 
1102  Z_Query *q = query.get_Z_Query();
1103  if (q->which == Z_Query_type_1 || q->which == Z_Query_type_101)
1104  {
1105  mp::odr odr;
1106  std::string rset;
1107  int diag = result_set_ref(odr, databases, q->u.type_1->RPNStructure,
1108  rset);
1109  if (diag)
1110  {
1111  Z_APDU *apdu =
1112  odr.create_searchResponse(
1113  apdu_req,
1114  diag,
1115  rset.c_str());
1116  package.response() = apdu;
1117  return;
1118  }
1119  query.set_Z_Query(q);
1120  }
1121 
1122  BackendSetPtr found_set; // null
1123  BackendInstancePtr found_backend; // null
1124 
1125  get_set(package, apdu_req, databases, query, found_backend, found_set);
1126  if (!found_set)
1127  return;
1128 
1129  mp::odr odr;
1130  Z_APDU *f_apdu = odr.create_searchResponse(apdu_req, 0, 0);
1131  Z_SearchResponse *f_resp = f_apdu->u.searchResponse;
1132  *f_resp->resultCount = found_set->m_result_set_size;
1133  f_resp->additionalSearchInfo = found_set->additionalSearchInfoResponse;
1134  package.response() = f_apdu;
1135 
1136  FrontendSetPtr fset(new FrontendSet(databases, query));
1137  m_frontend_sets[req->resultSetName] = fset;
1138 
1139  m_backend_class->release_backend(found_backend);
1140 }

Member Data Documentation

◆ m_backend_class

BackendClassPtr metaproxy_1::filter::SessionShared::Frontend::m_backend_class

Definition at line 191 of file filter_session_shared.cpp.

◆ m_frontend_sets

FrontendSets metaproxy_1::filter::SessionShared::Frontend::m_frontend_sets

Definition at line 192 of file filter_session_shared.cpp.

◆ m_in_use

bool metaproxy_1::filter::SessionShared::Frontend::m_in_use

Definition at line 170 of file filter_session_shared.cpp.

◆ m_init_options

Z_Options metaproxy_1::filter::SessionShared::Frontend::m_init_options

Definition at line 171 of file filter_session_shared.cpp.

◆ m_is_virtual

bool metaproxy_1::filter::SessionShared::Frontend::m_is_virtual

Definition at line 169 of file filter_session_shared.cpp.

◆ m_p

Rep* metaproxy_1::filter::SessionShared::Frontend::m_p

Definition at line 190 of file filter_session_shared.cpp.


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