+ if (binitreq.implementation_version)
+ {
+ char *nv = (char *)
+ odr_malloc (assoc->encode,
+ strlen(binitreq.implementation_version) + 10 +
+ strlen(resp->implementationVersion));
+ sprintf (nv, "YAZ %s / %s",
+ resp->implementationVersion, binitreq.implementation_version);
+ resp->implementationVersion = nv;
+ }
+
+ if (binitres->errcode)
+ {
+ yaz_log(LOG_LOG, "Connection rejected by backend.");
+ *resp->result = 0;
+ assoc->state = ASSOC_DEAD;
+ }
+ else
+ assoc->state = ASSOC_UP;
+ return apdu;
+}
+
+/*
+ * These functions should be merged.
+ */
+
+static void set_addinfo (Z_DefaultDiagFormat *dr, char *addinfo)
+{
+#if ASN_COMPILED
+ dr->which = Z_DefaultDiagFormat_v2Addinfo;
+ dr->u.v2Addinfo = addinfo ? addinfo : "";
+#else
+ dr->which = Z_DiagForm_v2AddInfo;
+ dr->addinfo = addinfo ? addinfo : "";
+#endif
+}
+
+/*
+ * nonsurrogate diagnostic record.
+ */
+static Z_Records *diagrec(association *assoc, int error, char *addinfo)
+{
+ int oid[OID_SIZE];
+ Z_Records *rec = (Z_Records *)
+ odr_malloc (assoc->encode, sizeof(*rec));
+ oident bib1;
+ int *err = (int *)
+ odr_malloc (assoc->encode, sizeof(*err));
+ Z_DiagRec *drec = (Z_DiagRec *)
+ odr_malloc (assoc->encode, sizeof(*drec));
+ Z_DefaultDiagFormat *dr = (Z_DefaultDiagFormat *)
+ odr_malloc (assoc->encode, sizeof(*dr));
+
+ bib1.proto = assoc->proto;
+ bib1.oclass = CLASS_DIAGSET;
+ bib1.value = VAL_BIB1;
+
+ yaz_log(LOG_DEBUG, "Diagnostic: %d -- %s", error, addinfo ? addinfo :
+ "NULL");
+ *err = error;
+ rec->which = Z_Records_NSD;
+#if ASN_COMPILED
+ rec->u.nonSurrogateDiagnostic = dr;
+#else
+ rec->u.nonSurrogateDiagnostic = drec;
+ drec->which = Z_DiagRec_defaultFormat;
+ drec->u.defaultFormat = dr;
+#endif
+ dr->diagnosticSetId =
+ odr_oiddup (assoc->encode, oid_ent_to_oid(&bib1, oid));
+ dr->condition = err;
+ set_addinfo (dr, addinfo);
+ return rec;
+}
+
+/*
+ * surrogate diagnostic.
+ */
+static Z_NamePlusRecord *surrogatediagrec(association *assoc, char *dbname,
+ int error, char *addinfo)
+{
+ int oid[OID_SIZE];
+ Z_NamePlusRecord *rec = (Z_NamePlusRecord *)
+ odr_malloc (assoc->encode, sizeof(*rec));
+ int *err = (int *)odr_malloc (assoc->encode, sizeof(*err));
+ oident bib1;
+ Z_DiagRec *drec = (Z_DiagRec *)odr_malloc (assoc->encode, sizeof(*drec));
+ Z_DefaultDiagFormat *dr = (Z_DefaultDiagFormat *)
+ odr_malloc (assoc->encode, sizeof(*dr));
+
+ bib1.proto = assoc->proto;
+ bib1.oclass = CLASS_DIAGSET;
+ bib1.value = VAL_BIB1;
+
+ yaz_log(LOG_DEBUG, "SurrogateDiagnotic: %d -- %s", error, addinfo);
+ *err = error;
+ rec->databaseName = dbname;
+ rec->which = Z_NamePlusRecord_surrogateDiagnostic;
+ rec->u.surrogateDiagnostic = drec;
+ drec->which = Z_DiagRec_defaultFormat;
+ drec->u.defaultFormat = dr;
+ dr->diagnosticSetId = odr_oiddup (assoc->encode,
+ oid_ent_to_oid(&bib1, oid));
+ dr->condition = err;
+ set_addinfo (dr, addinfo);
+
+ return rec;
+}
+
+/*
+ * multiple nonsurrogate diagnostics.
+ */
+static Z_DiagRecs *diagrecs(association *assoc, int error, char *addinfo)
+{
+ int oid[OID_SIZE];
+ Z_DiagRecs *recs = (Z_DiagRecs *)odr_malloc (assoc->encode, sizeof(*recs));
+ int *err = (int *)odr_malloc (assoc->encode, sizeof(*err));
+ oident bib1;
+ Z_DiagRec **recp = (Z_DiagRec **)odr_malloc (assoc->encode, sizeof(*recp));
+ Z_DiagRec *drec = (Z_DiagRec *)odr_malloc (assoc->encode, sizeof(*drec));
+ Z_DefaultDiagFormat *rec = (Z_DefaultDiagFormat *)odr_malloc (assoc->encode, sizeof(*rec));
+
+ yaz_log(LOG_DEBUG, "DiagRecs: %d -- %s", error, addinfo ? addinfo : "");
+ bib1.proto = assoc->proto;
+ bib1.oclass = CLASS_DIAGSET;
+ bib1.value = VAL_BIB1;
+
+ *err = error;
+ recs->num_diagRecs = 1;
+ recs->diagRecs = recp;
+ recp[0] = drec;
+ drec->which = Z_DiagRec_defaultFormat;
+ drec->u.defaultFormat = rec;
+
+ rec->diagnosticSetId = odr_oiddup (assoc->encode,
+ oid_ent_to_oid(&bib1, oid));
+ rec->condition = err;
+
+#ifdef ASN_COMPILED
+ rec->which = Z_DefaultDiagFormat_v2Addinfo;
+ rec->u.v2Addinfo = addinfo ? addinfo : "";
+#else
+ rec->which = Z_DiagForm_v2AddInfo;
+ rec->addinfo = addinfo ? addinfo : "";
+#endif
+ return recs;
+}
+
+static Z_Records *pack_records(association *a, char *setname, int start,
+ int *num, Z_RecordComposition *comp,
+ int *next, int *pres, oid_value format,
+ Z_ReferenceId *referenceId)
+{
+ int recno, total_length = 0, toget = *num, dumped_records = 0;
+ Z_Records *records =
+ (Z_Records *) odr_malloc (a->encode, sizeof(*records));
+ Z_NamePlusRecordList *reclist =
+ (Z_NamePlusRecordList *) odr_malloc (a->encode, sizeof(*reclist));
+ Z_NamePlusRecord **list =
+ (Z_NamePlusRecord **) odr_malloc (a->encode, sizeof(*list) * toget);
+
+ records->which = Z_Records_DBOSD;
+ records->u.databaseOrSurDiagnostics = reclist;
+ reclist->num_records = 0;
+ reclist->records = list;
+ *pres = Z_PRES_SUCCESS;
+ *num = 0;
+ *next = 0;
+
+ yaz_log(LOG_LOG, "Request to pack %d+%d", start, toget);
+ yaz_log(LOG_DEBUG, "pms=%d, mrs=%d", a->preferredMessageSize,
+ a->maximumRecordSize);
+ for (recno = start; reclist->num_records < toget; recno++)
+ {
+ bend_fetchrequest freq;
+ bend_fetchresult *fres;
+ Z_NamePlusRecord *thisrec;
+ int this_length = 0;
+ /*
+ * we get the number of bytes allocated on the stream before any
+ * allocation done by the backend - this should give us a reasonable
+ * idea of the total size of the data so far.
+ */
+ total_length = odr_total(a->encode) - dumped_records;
+ freq.setname = setname;
+ freq.number = recno;
+ freq.comp = comp;
+ freq.format = format;
+ freq.stream = a->encode;
+ freq.print = a->print;
+ freq.surrogate_flag = 0;
+ freq.referenceId = referenceId;
+ if (!(fres = bend_fetch(a->backend, &freq, 0)))
+ {
+ *pres = Z_PRES_FAILURE;
+ return diagrec(a, 2, "Backend interface problem");
+ }
+ /* backend should be able to signal whether error is system-wide
+ or only pertaining to current record */
+ if (fres->errcode)
+ {
+ if (!freq.surrogate_flag)
+ {
+ *pres = Z_PRES_FAILURE;
+ return diagrec(a, fres->errcode, fres->errstring);
+ }
+ reclist->records[reclist->num_records] =
+ surrogatediagrec(a, fres->basename, fres->errcode,
+ fres->errstring);
+ reclist->num_records++;
+ *next = fres->last_in_set ? 0 : recno + 1;
+ continue;
+ }
+ if (fres->len >= 0)
+ this_length = fres->len;
+ else
+ this_length = odr_total(a->encode) - total_length;
+ yaz_log(LOG_DEBUG, " fetched record, len=%d, total=%d",
+ this_length, total_length);
+ if (this_length + total_length > a->preferredMessageSize)
+ {
+ /* record is small enough, really */
+ if (this_length <= a->preferredMessageSize)
+ {
+ yaz_log(LOG_DEBUG, " Dropped last normal-sized record");
+ *pres = Z_PRES_PARTIAL_2;
+ break;
+ }
+ /* record can only be fetched by itself */
+ if (this_length < a->maximumRecordSize)
+ {
+ yaz_log(LOG_DEBUG, " Record > prefmsgsz");
+ if (toget > 1)
+ {
+ yaz_log(LOG_DEBUG, " Dropped it");
+ reclist->records[reclist->num_records] =
+ surrogatediagrec(a, fres->basename, 16, 0);
+ reclist->num_records++;
+ *next = fres->last_in_set ? 0 : recno + 1;
+ dumped_records += this_length;
+ continue;
+ }
+ }
+ else /* too big entirely */
+ {
+ yaz_log(LOG_DEBUG, "Record > maxrcdsz");
+ reclist->records[reclist->num_records] =
+ surrogatediagrec(a, fres->basename, 17, 0);
+ reclist->num_records++;
+ *next = fres->last_in_set ? 0 : recno + 1;
+ dumped_records += this_length;
+ continue;
+ }
+ }
+
+ if (!(thisrec = (Z_NamePlusRecord *)
+ odr_malloc(a->encode, sizeof(*thisrec))))
+ return 0;
+ if (!(thisrec->databaseName = (char *)odr_malloc(a->encode,
+ strlen(fres->basename) + 1)))
+ return 0;
+ strcpy(thisrec->databaseName, fres->basename);
+ thisrec->which = Z_NamePlusRecord_databaseRecord;
+ thisrec->u.databaseRecord = z_ext_record(a->encode, fres->format,
+ fres->record, fres->len);
+ if (!thisrec->u.databaseRecord)
+ return 0;
+ reclist->records[reclist->num_records] = thisrec;
+ reclist->num_records++;
+ *next = fres->last_in_set ? 0 : recno + 1;
+ }
+ *num = reclist->num_records;
+ return records;