+ else if (gdu && gdu->which == Z_GDU_Z3950
+ && gdu->u.z3950->which == Z_APDU_initResponse
+ && *gdu->u.z3950->u.initResponse->result)
+ {
+ /* successful init response */
+ Z_InitResponse *res = gdu->u.z3950->u.initResponse;
+ m_init_response = gdu->u.z3950;
+ if (ODR_MASK_GET(res->options, Z_Options_namedResultSets))
+ {
+ m_named_result_sets = true;
+ }
+ }
+ else
+ {
+ /* not init or init rejected */
+ init_package.copy_filter(frontend_package);
+ init_package.session().close();
+ init_package.move();
+ return null;
+ }
+ bp->m_in_use = true;
+ time(&bp->m_time_last_use);
+ bp->m_sequence_this = 0;
+ bp->m_result_set_sequence = 0;
+ m_backend_list.push_back(bp);
+
+ return bp;
+}
+
+
+yf::SessionShared::BackendClass::BackendClass(const yazpp_1::GDU &init_request,
+ int resultset_ttl,
+ int resultset_max,
+ int session_ttl)
+ : m_named_result_sets(false), m_init_request(init_request),
+ m_sequence_top(0), m_backend_set_ttl(resultset_ttl),
+ m_backend_expiry_ttl(session_ttl), m_backend_set_max(resultset_max)
+{}
+
+yf::SessionShared::BackendClass::~BackendClass()
+{}
+
+void yf::SessionShared::Rep::init(mp::Package &package, const Z_GDU *gdu,
+ FrontendPtr frontend)
+{
+ Z_InitRequest *req = gdu->u.z3950->u.initRequest;
+
+ frontend->m_is_virtual = true;
+ frontend->m_init_options = *req->options;
+ InitKey k(req);
+ {
+ boost::mutex::scoped_lock lock(m_mutex_backend_map);
+ BackendClassMap::const_iterator it;
+ it = m_backend_map.find(k);
+ if (it == m_backend_map.end())
+ {
+ BackendClassPtr b(new BackendClass(gdu->u.z3950,
+ m_resultset_ttl,
+ m_resultset_max,
+ m_session_ttl));
+ m_backend_map[k] = b;
+ frontend->m_backend_class = b;
+ }
+ else
+ {
+ frontend->m_backend_class = it->second;
+ }
+ }
+ BackendClassPtr bc = frontend->m_backend_class;
+ BackendInstancePtr backend;
+ mp::odr odr;
+
+ // we only need to get init response from "first" target in
+ // backend class - the assumption being that init response is
+ // same for all
+ if (bc->m_init_response.get() == 0)
+ {
+ backend = bc->get_backend(package);
+ }
+ {
+ boost::mutex::scoped_lock lock(bc->m_mutex_backend_class);
+ if (bc->m_init_response.get() == 0)
+ {
+ Z_APDU *apdu = odr.create_initResponse(gdu->u.z3950, 0, 0);
+ *apdu->u.initResponse->result = 0;
+ package.response() = apdu;
+ package.session().close();
+ }
+ else
+ {
+ yazpp_1::GDU init_response = bc->m_init_response;
+ Z_GDU *response_gdu = init_response.get();
+ mp::util::transfer_referenceId(odr, gdu->u.z3950,
+ response_gdu->u.z3950);
+
+ Z_Options *server_options =
+ response_gdu->u.z3950->u.initResponse->options;
+ Z_Options *client_options = &frontend->m_init_options;
+
+ int i;
+ for (i = 0; i < 30; i++)
+ if (!ODR_MASK_GET(client_options, i))
+ ODR_MASK_CLEAR(server_options, i);
+ package.response() = init_response;
+ }
+ }
+ if (backend)
+ bc->release_backend(backend);
+}
+
+void yf::SessionShared::BackendSet::timestamp()
+{
+ time(&m_time_last_use);
+}
+
+yf::SessionShared::BackendSet::BackendSet(
+ const std::string &result_set_id,
+ const Databases &databases,
+ const yazpp_1::Yaz_Z_Query &query) :
+ m_result_set_id(result_set_id),
+ m_databases(databases), m_result_set_size(0), m_query(query)
+{
+ timestamp();
+}
+
+static int get_diagnostic(Z_DefaultDiagFormat *r)
+{
+ return *r->condition;