+ 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;
+ }
+ if (*gdu->u.z3950->u.initResponse->result
+ && !init_package.session().is_closed())
+ {
+ 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;
+ }
+ }
+ else
+ {
+ yazpp_1::GDU empty_gdu;
+ m_init_response = empty_gdu;
+ }
+
+ if (!init_package.session().is_closed())
+ {
+ init_package.copy_filter(frontend_package);
+ init_package.session().close();
+ init_package.move();
+ }
+ return null;
+}
+
+
+yf::SessionShared::BackendClass::BackendClass(const yazpp_1::GDU &init_request,
+ int resultset_ttl,
+ int resultset_max,
+ int session_ttl,
+ Odr_int preferredMessageSize,
+ Odr_int maximumRecordSize)
+ : 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),
+ m_preferredMessageSize(preferredMessageSize),
+ m_maximumRecordSize(maximumRecordSize)
+{}
+
+yf::SessionShared::BackendClass::~BackendClass()
+{}
+
+void yf::SessionShared::Rep::stat()
+{
+ int no_classes = 0;
+ int no_instances = 0;
+ BackendClassMap::const_iterator it;
+ {
+ boost::mutex::scoped_lock lock(m_mutex_backend_map);
+ for (it = m_backend_map.begin(); it != m_backend_map.end(); it++)
+ {
+ BackendClassPtr bc = it->second;
+ no_classes++;
+ BackendInstanceList::iterator bit = bc->m_backend_list.begin();
+ for (; bit != bc->m_backend_list.end(); bit++)
+ no_instances++;
+ }
+ }
+ yaz_log(YLOG_LOG, "backend classes=%d instances=%d", no_classes,
+ no_instances);
+}
+
+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_preferredMessageSize,
+ m_maximumRecordSize));
+ m_backend_map[k] = b;
+ frontend->m_backend_class = b;
+ }
+ else
+ {
+ frontend->m_backend_class = it->second;
+ }
+ }
+ BackendClassPtr bc = frontend->m_backend_class;
+ 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_backend_list.size() == 0)
+ {
+ BackendInstancePtr backend = bc->create_backend(package);
+ if (backend)
+ bc->release_backend(backend);
+ }
+
+ yazpp_1::GDU init_response;
+ {
+ boost::mutex::scoped_lock lock(bc->m_mutex_backend_class);
+
+ init_response = bc->m_init_response;
+ }
+
+ if (init_response.get())
+ {
+ Z_GDU *response_gdu = init_response.get();
+ mp::util::transfer_referenceId(odr, gdu->u.z3950,
+ response_gdu->u.z3950);
+ Z_InitResponse *init_res = response_gdu->u.z3950->u.initResponse;
+ Z_Options *server_options = init_res->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);
+
+ if (!m_preferredMessageSize ||
+ *init_res->preferredMessageSize > *req->preferredMessageSize)
+ *init_res->preferredMessageSize = *req->preferredMessageSize;
+
+ if (!m_maximumRecordSize ||
+ *init_res->maximumRecordSize > *req->maximumRecordSize)
+ *init_res->maximumRecordSize = *req->maximumRecordSize;
+
+ package.response() = init_response;
+ if (!*response_gdu->u.z3950->u.initResponse->result)
+ package.session().close();
+ }
+ else
+ {
+ Z_APDU *apdu =
+ odr.create_initResponse(
+ gdu->u.z3950, YAZ_BIB1_TEMPORARY_SYSTEM_ERROR,
+ "session_shared: target closed connection during init");
+ *apdu->u.initResponse->result = 0;
+ package.response() = apdu;