X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=src%2Fseshigh.c;h=e29973e207e4922a5320f5f66cd1b6a8f167793d;hb=f6379872ace49628473c47d23b29e9f46b5afbe4;hp=079a30db96e686fef399091209eef747e048c1de;hpb=b64382a1e420049b882b87fb05fe058aa6592d1c;p=yaz-moved-to-github.git diff --git a/src/seshigh.c b/src/seshigh.c index 079a30d..e29973e 100644 --- a/src/seshigh.c +++ b/src/seshigh.c @@ -1,8 +1,8 @@ /* - * Copyright (C) 1995-2005, Index Data ApS + * Copyright (C) 1995-2006, Index Data ApS * See the file LICENSE for details. * - * $Id: seshigh.c,v 1.99 2006-09-27 11:39:02 adam Exp $ + * $Id: seshigh.c,v 1.105 2006-12-04 14:56:55 adam Exp $ */ /** * \file seshigh.c @@ -264,83 +264,31 @@ static void do_close(association *a, int reason, char *message) do_close_req (a, reason, message, req); } -/* - * This is where PDUs from the client are read and the further - * processing is initiated. Flow of control moves down through the - * various process_* functions below, until the encoded result comes back up - * to the output handler in here. - * - * h : the I/O channel that has an outstanding event. - * event : the current outstanding event. - */ -void ir_session(IOCHAN h, int event) + +int ir_read(IOCHAN h, int event) { - int res; association *assoc = (association *)iochan_getdata(h); COMSTACK conn = assoc->client_link; request *req; - - assert(h && conn && assoc); - if (event == EVENT_TIMEOUT) + + if ((assoc->cs_put_mask & EVENT_INPUT) == 0 && (event & assoc->cs_get_mask)) { - if (assoc->state != ASSOC_UP) + yaz_log(YLOG_DEBUG, "ir_session (input)"); + /* We aren't speaking to this fellow */ + if (assoc->state == ASSOC_DEAD) { - yaz_log(YLOG_DEBUG, "Final timeout - closing connection."); - /* do we need to lod this at all */ + yaz_log(log_sessiondetail, "Connection closed - end of session"); cs_close(conn); destroy_association(assoc); iochan_destroy(h); + return 0; } - else - { - yaz_log(log_sessiondetail, - "Session idle too long. Sending close."); - do_close(assoc, Z_Close_lackOfActivity, 0); - } - return; - } - if (event & assoc->cs_accept_mask) - { - if (!cs_accept (conn)) - { - yaz_log (YLOG_WARN, "accept failed"); - destroy_association(assoc); - iochan_destroy(h); - } - iochan_clearflag (h, EVENT_OUTPUT); - if (conn->io_pending) - { /* cs_accept didn't complete */ - assoc->cs_accept_mask = - ((conn->io_pending & CS_WANT_WRITE) ? EVENT_OUTPUT : 0) | - ((conn->io_pending & CS_WANT_READ) ? EVENT_INPUT : 0); + assoc->cs_get_mask = EVENT_INPUT; - iochan_setflag (h, assoc->cs_accept_mask); - } - else - { /* cs_accept completed. Prepare for reading (cs_get) */ - assoc->cs_accept_mask = 0; - assoc->cs_get_mask = EVENT_INPUT; - iochan_setflag (h, assoc->cs_get_mask); - } - return; - } - if ((event & assoc->cs_get_mask) || (event & EVENT_WORK)) /* input */ - { - if ((assoc->cs_put_mask & EVENT_INPUT) == 0 && (event & assoc->cs_get_mask)) + do { - yaz_log(YLOG_DEBUG, "ir_session (input)"); - /* We aren't speaking to this fellow */ - if (assoc->state == ASSOC_DEAD) - { - yaz_log(log_sessiondetail, "Connection closed - end of session"); - cs_close(conn); - destroy_association(assoc); - iochan_destroy(h); - return; - } - assoc->cs_get_mask = EVENT_INPUT; - res = cs_get(conn, &assoc->input_buffer, - &assoc->input_buffer_len); + int res = cs_get(conn, &assoc->input_buffer, + &assoc->input_buffer_len); if (res < 0 && cs_errno(conn) == CSBUFSIZE) { yaz_log(log_session, "Connection error: %s res=%d", @@ -348,31 +296,26 @@ void ir_session(IOCHAN h, int event) req = request_get(&assoc->incoming); /* get a new request */ do_close_req(assoc, Z_Close_protocolError, "Incoming package too large", req); - return; + return 0; } else if (res <= 0) { - yaz_log(log_sessiondetail, "Connection closed by client"); - cs_close(conn); - destroy_association(assoc); - iochan_destroy(h); - return; + yaz_log(log_session, "Connection closed by client"); + assoc->state = ASSOC_DEAD; + return 0; } else if (res == 1) /* incomplete read - wait for more */ { if (conn->io_pending & CS_WANT_WRITE) assoc->cs_get_mask |= EVENT_OUTPUT; iochan_setflag(h, assoc->cs_get_mask); - return; + return 1; } - if (cs_more(conn)) /* more stuff - call us again later, please */ - iochan_setevent(h, EVENT_INPUT); - /* we got a complete PDU. Let's decode it */ yaz_log(YLOG_DEBUG, "Got PDU, %d bytes: lead=%02X %02X %02X", res, - assoc->input_buffer[0] & 0xff, - assoc->input_buffer[1] & 0xff, - assoc->input_buffer[2] & 0xff); + assoc->input_buffer[0] & 0xff, + assoc->input_buffer[1] & 0xff, + assoc->input_buffer[2] & 0xff); req = request_get(&assoc->incoming); /* get a new request */ odr_reset(assoc->decode); odr_setbuf(assoc->decode, assoc->input_buffer, res, 0); @@ -396,20 +339,87 @@ void ir_session(IOCHAN h, int event) assoc->state = ASSOC_DEAD; process_gdu_response(assoc, req, p); } - return; + return 0; } req->request_mem = odr_extract_mem(assoc->decode); if (assoc->print) { if (!z_GDU(assoc->print, &req->gdu_request, 0, 0)) yaz_log(YLOG_WARN, "ODR print error: %s", - odr_errmsg(odr_geterror(assoc->print))); + odr_errmsg(odr_geterror(assoc->print))); odr_reset(assoc->print); } request_enq(&assoc->incoming, req); } + while (cs_more(conn)); + } + return 1; +} - /* can we do something yet? */ +/* + * This is where PDUs from the client are read and the further + * processing is initiated. Flow of control moves down through the + * various process_* functions below, until the encoded result comes back up + * to the output handler in here. + * + * h : the I/O channel that has an outstanding event. + * event : the current outstanding event. + */ +void ir_session(IOCHAN h, int event) +{ + int res; + association *assoc = (association *)iochan_getdata(h); + COMSTACK conn = assoc->client_link; + request *req; + + assert(h && conn && assoc); + if (event == EVENT_TIMEOUT) + { + if (assoc->state != ASSOC_UP) + { + yaz_log(YLOG_DEBUG, "Final timeout - closing connection."); + /* do we need to lod this at all */ + cs_close(conn); + destroy_association(assoc); + iochan_destroy(h); + } + else + { + yaz_log(log_sessiondetail, + "Session idle too long. Sending close."); + do_close(assoc, Z_Close_lackOfActivity, 0); + } + return; + } + if (event & assoc->cs_accept_mask) + { + if (!cs_accept (conn)) + { + yaz_log (YLOG_WARN, "accept failed"); + destroy_association(assoc); + iochan_destroy(h); + } + iochan_clearflag (h, EVENT_OUTPUT); + if (conn->io_pending) + { /* cs_accept didn't complete */ + assoc->cs_accept_mask = + ((conn->io_pending & CS_WANT_WRITE) ? EVENT_OUTPUT : 0) | + ((conn->io_pending & CS_WANT_READ) ? EVENT_INPUT : 0); + + iochan_setflag (h, assoc->cs_accept_mask); + } + else + { /* cs_accept completed. Prepare for reading (cs_get) */ + assoc->cs_accept_mask = 0; + assoc->cs_get_mask = EVENT_INPUT; + iochan_setflag (h, assoc->cs_get_mask); + } + return; + } + if (event & assoc->cs_get_mask) /* input */ + { + if (!ir_read(h, event)) + return; req = request_head(&assoc->incoming); if (req->state == REQUEST_IDLE) { @@ -565,33 +575,6 @@ static int srw_bend_init(association *assoc, Z_SRW_diagnostic **d, int *num, Z_S return 1; } -static const char *get_esn(Z_RecordComposition *comp) -{ - if (comp && comp->which == Z_RecordComp_complex) - { - if (comp->u.complex->generic - && comp->u.complex->generic->elementSpec - && (comp->u.complex->generic->elementSpec->which == - Z_ElementSpec_elementSetName)) - return comp->u.complex->generic->elementSpec->u.elementSetName; - } - else if (comp && comp->which == Z_RecordComp_simple && - comp->u.simple->which == Z_ElementSetNames_generic) - return comp->u.simple->u.generic; - return 0; -} - -static void set_esn(Z_RecordComposition **comp_p, const char *esn, NMEM nmem) -{ - Z_RecordComposition *comp = nmem_malloc(nmem, sizeof(*comp)); - - comp->which = Z_RecordComp_simple; - comp->u.simple = nmem_malloc(nmem, sizeof(*comp->u.simple)); - comp->u.simple->which = Z_ElementSetNames_generic; - comp->u.simple->u.generic = nmem_strdup(nmem, esn); - *comp_p = comp; -} - static int retrieve_fetch(association *assoc, bend_fetch_rr *rr) { #if YAZ_HAVE_XML2 @@ -602,7 +585,7 @@ static int retrieve_fetch(association *assoc, bend_fetch_rr *rr) if (assoc->server) { int r; - const char *input_schema = get_esn(rr->comp); + const char *input_schema = yaz_get_esn(rr->comp); Odr_oid *input_syntax_raw = rr->request_format_raw; const char *backend_schema = 0; @@ -647,7 +630,7 @@ static int retrieve_fetch(association *assoc, bend_fetch_rr *rr) } if (backend_schema) { - set_esn(&rr->comp, backend_schema, rr->stream->mem); + yaz_set_esn(&rr->comp, backend_schema, rr->stream->mem); } if (backend_syntax) { @@ -1013,114 +996,112 @@ static void srw_bend_search(association *assoc, request *req, srw_res->resultSetIdleTime = odr_intdup(assoc->encode, *rr.srw_setnameIdleTime ); } - if (number > 0) + + if ((rr.hits > 0 && start > rr.hits) || start < 1) + { + yaz_add_srw_diagnostic( + assoc->encode, + &srw_res->diagnostics, &srw_res->num_diagnostics, + YAZ_SRW_FIRST_RECORD_POSITION_OUT_OF_RANGE, 0); + } + else if (number > 0) { int i; + int ok = 1; + if (start + number > rr.hits) + number = rr.hits - start + 1; - if (start > rr.hits) + /* Call bend_present if defined */ + if (assoc->init->bend_present) { - yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, - &srw_res->num_diagnostics, - YAZ_SRW_FIRST_RECORD_POSITION_OUT_OF_RANGE, 0); + bend_present_rr *bprr = (bend_present_rr*) + odr_malloc (assoc->decode, sizeof(*bprr)); + bprr->setname = "default"; + bprr->start = start; + bprr->number = number; + bprr->format = VAL_TEXT_XML; + if (srw_req->recordSchema) + { + bprr->comp = (Z_RecordComposition *) odr_malloc(assoc->decode, + sizeof(*bprr->comp)); + bprr->comp->which = Z_RecordComp_simple; + bprr->comp->u.simple = (Z_ElementSetNames *) + odr_malloc(assoc->decode, sizeof(Z_ElementSetNames)); + bprr->comp->u.simple->which = Z_ElementSetNames_generic; + bprr->comp->u.simple->u.generic = srw_req->recordSchema; + } + else + { + bprr->comp = 0; + } + bprr->stream = assoc->encode; + bprr->referenceId = 0; + bprr->print = assoc->print; + bprr->request = req; + bprr->association = assoc; + bprr->errcode = 0; + bprr->errstring = NULL; + (*assoc->init->bend_present)(assoc->backend, bprr); + + if (!bprr->request) + return; + if (bprr->errcode) + { + srw_error = yaz_diag_bib1_to_srw (bprr->errcode); + yaz_add_srw_diagnostic(assoc->encode, + &srw_res->diagnostics, + &srw_res->num_diagnostics, + srw_error, bprr->errstring); + ok = 0; + } } - else + + if (ok) { - int ok = 1; - if (start + number > rr.hits) - number = rr.hits - start + 1; - - /* Call bend_present if defined */ - if (assoc->init->bend_present) + int j = 0; + int packing = Z_SRW_recordPacking_string; + if (srw_req->recordPacking){ + if (!strcmp(srw_req->recordPacking, "xml")) + packing = Z_SRW_recordPacking_XML; + if (!strcmp(srw_req->recordPacking, "url")) + packing = Z_SRW_recordPacking_URL; + } + srw_res->records = (Z_SRW_record *) + odr_malloc(assoc->encode, + number * sizeof(*srw_res->records)); + + srw_res->extra_records = (Z_SRW_extra_record **) + odr_malloc(assoc->encode, + number*sizeof(*srw_res->extra_records)); + + for (i = 0; idecode, sizeof(*bprr)); - bprr->setname = "default"; - bprr->start = start; - bprr->number = number; - bprr->format = VAL_TEXT_XML; - if (srw_req->recordSchema) - { - bprr->comp = (Z_RecordComposition *) odr_malloc(assoc->decode, - sizeof(*bprr->comp)); - bprr->comp->which = Z_RecordComp_simple; - bprr->comp->u.simple = (Z_ElementSetNames *) - odr_malloc(assoc->decode, sizeof(Z_ElementSetNames)); - bprr->comp->u.simple->which = Z_ElementSetNames_generic; - bprr->comp->u.simple->u.generic = srw_req->recordSchema; - } - else - { - bprr->comp = 0; - } - bprr->stream = assoc->encode; - bprr->referenceId = 0; - bprr->print = assoc->print; - bprr->request = req; - bprr->association = assoc; - bprr->errcode = 0; - bprr->errstring = NULL; - (*assoc->init->bend_present)(assoc->backend, bprr); + int errcode; + const char *addinfo = 0; - if (!bprr->request) - return; - if (bprr->errcode) + srw_res->records[j].recordPacking = packing; + srw_res->records[j].recordData_buf = 0; + srw_res->extra_records[j] = 0; + yaz_log(YLOG_DEBUG, "srw_bend_fetch %d", i+start); + errcode = srw_bend_fetch(assoc, i+start, srw_req, + srw_res->records + j, + &addinfo); + if (errcode) { - srw_error = yaz_diag_bib1_to_srw (bprr->errcode); yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, &srw_res->num_diagnostics, - srw_error, bprr->errstring); - ok = 0; - } - } - - if (ok) - { - int j = 0; - int packing = Z_SRW_recordPacking_string; - if (srw_req->recordPacking){ - if (!strcmp(srw_req->recordPacking, "xml")) - packing = Z_SRW_recordPacking_XML; - if (!strcmp(srw_req->recordPacking, "url")) - packing = Z_SRW_recordPacking_URL; - } - srw_res->records = (Z_SRW_record *) - odr_malloc(assoc->encode, - number * sizeof(*srw_res->records)); - - srw_res->extra_records = (Z_SRW_extra_record **) - odr_malloc(assoc->encode, - number*sizeof(*srw_res->extra_records)); - - for (i = 0; irecords[j].recordPacking = packing; - srw_res->records[j].recordData_buf = 0; - srw_res->extra_records[j] = 0; - yaz_log(YLOG_DEBUG, "srw_bend_fetch %d", i+start); - errcode = srw_bend_fetch(assoc, i+start, srw_req, - srw_res->records + j, - &addinfo); - if (errcode) - { - yaz_add_srw_diagnostic(assoc->encode, - &srw_res->diagnostics, - &srw_res->num_diagnostics, - yaz_diag_bib1_to_srw (errcode), - addinfo); - - break; - } - if (srw_res->records[j].recordData_buf) - j++; + break; } - srw_res->num_records = j; - if (!j) - srw_res->records = 0; + if (srw_res->records[j].recordData_buf) + j++; } + srw_res->num_records = j; + if (!j) + srw_res->records = 0; } } } @@ -1479,24 +1460,60 @@ static void srw_bend_update(association *assoc, request *req, rr.uri = 0; rr.message = 0; rr.details = 0; - + + if ( rr.operation == 0 ){ + yaz_add_sru_update_diagnostic(assoc->encode, &srw_res->diagnostics, + &srw_res->num_diagnostics, + 9, "action" ); + return; + } yaz_log(YLOG_DEBUG, "basename = %s", rr.basenames[0] ); yaz_log(YLOG_DEBUG, "Operation = %s", rr.operation ); if ( !strcmp( rr.operation, "delete" ) ){ if ( !srw_req->recordId ){ - yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, - &srw_res->num_diagnostics, - 7, "recordId" ); + if ( srw_req->record.recordData_len ){ + if ( srw_req->record.recordSchema == 0 ){ + yaz_add_sru_update_diagnostic(assoc->encode, &srw_res->diagnostics, + &srw_res->num_diagnostics, + 9, "recordSchema" ); + } + else { + rr.record_schema = odr_strdup(assoc->encode, + srw_req->record.recordSchema ); + } + switch (srw_req->record.recordPacking) + { + case Z_SRW_recordPacking_string: + rr.record_packing = "string"; + break; + case Z_SRW_recordPacking_XML: + rr.record_packing = "xml"; + break; + case Z_SRW_recordPacking_URL: + rr.record_packing = "url"; + break; + } + rr.record_data = odr_strdupn(assoc->encode, + srw_req->record.recordData_buf, + srw_req->record.recordData_len ); + rr.request_extra_record = srw_req->extra_record; + } + else { + yaz_add_sru_update_diagnostic(assoc->encode, &srw_res->diagnostics, + &srw_res->num_diagnostics, + 9, "recordIdentifier OR recordData" ); + } } else { rr.record_id = srw_req->recordId; + if ( srw_req->record.recordData_len ){ + yaz_add_sru_update_diagnostic(assoc->encode, + &srw_res->diagnostics, + &srw_res->num_diagnostics, + 9, "recordData" ); + } } - if ( !srw_req->recordVersion ){ - yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, - &srw_res->num_diagnostics, - 7, "recordVersion" ); - } - else { + if ( srw_req->recordVersion ){ rr.record_version = odr_strdup( assoc->encode, srw_req->recordVersion ); @@ -1512,17 +1529,17 @@ static void srw_bend_update(association *assoc, request *req, } else if ( !strcmp( rr.operation, "replace" ) ){ if ( !srw_req->recordId ){ - yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, - &srw_res->num_diagnostics, - 7, "recordId" ); + yaz_add_sru_update_diagnostic(assoc->encode, &srw_res->diagnostics, + &srw_res->num_diagnostics, + 9, "recordIdentifier" ); } else { rr.record_id = srw_req->recordId; } if ( srw_req->record.recordSchema == 0 ){ - yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, - &srw_res->num_diagnostics, - 7, "recordSchema" ); + yaz_add_sru_update_diagnostic(assoc->encode, &srw_res->diagnostics, + &srw_res->num_diagnostics, + 9, "recordSchema" ); } else { rr.record_schema = odr_strdup(assoc->encode, @@ -1547,21 +1564,20 @@ static void srw_bend_update(association *assoc, request *req, rr.request_extra_record = srw_req->extra_record; } else { - yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, - &srw_res->num_diagnostics, - 7, "recordData" ); + yaz_add_sru_update_diagnostic(assoc->encode, &srw_res->diagnostics, + &srw_res->num_diagnostics, + 9, "recordData" ); } if (srw_req->extraRequestData) rr.extra_request_data = odr_strdup(assoc->encode, srw_req->extraRequestData ); } - else if ( !strcmp( rr.operation, "insert" ) ) - { + else if (!strcmp( rr.operation, "insert" ) ) { rr.record_id = srw_req->recordId; if ( srw_req->record.recordSchema == 0 ){ - yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, - &srw_res->num_diagnostics, - 7, "recordSchema" ); + yaz_add_sru_update_diagnostic(assoc->encode, &srw_res->diagnostics, + &srw_res->num_diagnostics, + 9, "recordSchema" ); } else { rr.record_schema = odr_strdup(assoc->encode, @@ -1588,13 +1604,18 @@ static void srw_bend_update(association *assoc, request *req, rr.request_extra_record = srw_req->extra_record; } else - yaz_add_srw_diagnostic(assoc->encode, &srw_res->diagnostics, - &srw_res->num_diagnostics, - 7, "recordData" ); + yaz_add_sru_update_diagnostic(assoc->encode, &srw_res->diagnostics, + &srw_res->num_diagnostics, + 9, "recordData" ); if ( srw_req->extraRequestData ) rr.extra_request_data = odr_strdup(assoc->encode, srw_req->extraRequestData ); } + else { + yaz_add_sru_update_diagnostic(assoc->encode, &srw_res->diagnostics, + &srw_res->num_diagnostics, + 100, rr.operation ); + } if (srw_res->num_diagnostics == 0) { if ( assoc->init->bend_srw_update) @@ -2105,13 +2126,18 @@ static int process_gdu_response(association *assoc, request *req, Z_GDU *res) iochan_setflag(assoc->client_chan, EVENT_OUTPUT); assoc->cs_put_mask = EVENT_OUTPUT; /* Is there more work to be done? give that to the input handler too */ -#if 1 - if (request_head(&assoc->incoming)) + for (;;) { - yaz_log (YLOG_DEBUG, "more work to be done"); - iochan_setevent(assoc->client_chan, EVENT_WORK); + req = request_head(&assoc->incoming); + if (req && req->state == REQUEST_IDLE) + { + yaz_log(YLOG_LOG, "process next request 3"); + request_deq(&assoc->incoming); + process_gdu_request(assoc, req); + } + else + break; } -#endif return 0; } @@ -2323,7 +2349,7 @@ static Z_APDU *process_initRequest(association *assoc, request *reqb) assoc->init->implementation_name, odr_prepend(assoc->encode, "GFS", resp->implementationName)); - version = odr_strdup(assoc->encode, "$Revision: 1.99 $"); + version = odr_strdup(assoc->encode, "$Revision: 1.105 $"); if (strlen(version) > 10) /* check for unexpanded CVS strings */ version[strlen(version)-2] = '\0'; resp->implementationVersion = odr_prepend(assoc->encode, @@ -3499,6 +3525,15 @@ static Z_APDU *process_ESRequest(association *assoc, request *reqb, int *fd) return apdu; } +int bend_assoc_is_alive(bend_association assoc) +{ + if (assoc->state == ASSOC_DEAD) + return 0; /* already marked as dead. Don't check I/O chan anymore */ + + return iochan_is_alive(assoc->client_chan); +} + + /* * Local variables: * c-basic-offset: 4