/* This file is part of simpleserver.
- * Copyright (C) 2000-2011 Index Data.
+ * Copyright (C) 2000-2013 Index Data.
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
#include <stdio.h>
#include <yaz/mutex.h>
#include <yaz/oid_db.h>
+#include <yaz/yaz-version.h>
#ifdef WIN32
#else
#include <unistd.h>
#endif
#include <stdlib.h>
#include <ctype.h>
-#define GRS_MAX_FIELDS 500
+#define GRS_MAX_FIELDS 500
#ifdef ASN_COMPILED
#include <yaz/ill.h>
#endif
typedef struct {
SV *ghandle; /* Global handle specified at creation */
SV *handle; /* Per-connection handle set at Init */
-#if 0
-/* ### These callback-reference elements are never used! */
- SV *init_ref;
- SV *close_ref;
- SV *sort_ref;
- SV *search_ref;
- SV *fetch_ref;
- SV *present_ref;
- SV *esrequest_ref;
- SV *delete_ref;
- SV *scan_ref;
- SV *explain_ref;
-#endif /*0*/
NMEM nmem;
int stop_flag; /* is used to stop server prematurely .. */
} Zfront_handle;
SV *delete_ref = NULL;
SV *scan_ref = NULL;
SV *explain_ref = NULL;
+SV *start_ref = NULL;
PerlInterpreter *root_perl_context;
#define GRS_BUF_SIZE 8192
CV * simpleserver_sv2cv(SV *handler) {
STRLEN len;
char *buf;
-
+
if (SvPOK(handler)) {
CV *ret;
buf = SvPV( handler, len);
fprintf( stderr, "simpleserver_sv2cv: No such handler '%s'\n\n", buf );
exit(1);
}
-
+
return ret;
} else {
return (CV *) handler;
#ifdef USE_ITHREADS
void tst_clones(void)
{
- int i;
+ int i;
PerlInterpreter *parent = PERL_GET_CONTEXT;
for (i = 0; i<5000; i++)
{
PerlInterpreter *current_interp = PERL_GET_CONTEXT;
/* If current Perl Interp is different from root interp, then
- * we're in threaded mode and we must destroy..
+ * we're in threaded mode and we must destroy..
*/
if (current_interp != root_perl_context) {
PL_perl_destruct_level = 2;
r = (Z_GenericRecord *)odr_malloc(o, sizeof(*r));
r->elements = (Z_TaggedElement **) odr_malloc(o, sizeof(Z_TaggedElement*) * GRS_MAX_FIELDS);
r->num_elements = 0;
-
+
for (;;)
{
Z_TaggedElement *t;
Z_ElementData *c;
int len;
-
+
ptr = strchr(str, '\n');
if (!ptr) {
return r;
oid2str(oid, buf);
return buf;
}
-
+
WRBUF zquery2pquery(Z_Query *q)
{
WRBUF buf = wrbuf_alloc();
- if (q->which != Z_Query_type_1 && q->which != Z_Query_type_101)
+ if (q->which != Z_Query_type_1 && q->which != Z_Query_type_101)
return 0;
yaz_rpnquery_to_wrbuf(buf, q->u.type_1);
return buf;
case Z_Operand_APT:
return f_Term_to_SV(o->u.attributesPlusTerm->term,
- o->u.attributesPlusTerm->attributes);
+ o->u.attributesPlusTerm->attributes);
default:
fatal("unknown RPN simple type %d", (int) o->which);
}
default:
fatal("unknown RPN node type %d", (int) s->which);
}
-
+
return 0;
}
hv_store(sort_spec, "SORT_ATTR", 9, newRV( sv_2mortal( (SV*) list ) ), 0);
- for (i = 0; i < attr_list->num_attributes; i++)
+ for (i = 0; i < attr_list->num_attributes; i++)
{
- Z_AttributeElement *attr = *attr_list->attributes++;
+ Z_AttributeElement *attr = *attr_list->attributes++;
HV *attr_spec = newHV();
-
+
av_push(list, newRV( sv_2mortal( (SV*) attr_spec ) ));
hv_store(attr_spec, "ATTR_TYPE", 9, newSViv(*attr->attributeType), 0);
else if (key->which == Z_SortKey_elementSpec)
{
Z_Specification *zspec = key->u.elementSpec;
-
+
hv_store(sort_spec, "ELEMENTSPEC_TYPE", 16,
newSViv(zspec->which), 0);
SV *sv;
HV *hv;
- if (q->which != Z_Query_type_1 && q->which != Z_Query_type_101)
+ if (q->which != Z_Query_type_1 && q->which != Z_Query_type_101)
return 0;
sv = newObject("Net::Z3950::APDU::Query", (SV*) (hv = newHV()));
if (q->u.type_1->attributeSetId)
Zfront_handle *zhandle = (Zfront_handle *)handle;
Z_SortKeySpecList *sort_spec = rr->sort_sequence;
int i;
-
+
dSP;
ENTER;
SAVETMPS;
-
+
aref = newAV();
input_setnames = rr->input_setnames;
for (i = 0; i < rr->num_input_setnames; i++)
return 0;
}
}
-
+
href = newHV();
hv_store(href, "INPUT", 5, newRV( (SV*) aref), 0);
hv_store(href, "OUTPUT", 6, newSVpv(rr->output_setname, 0), 0);
hv_undef(href);
av_undef(aref);
av_undef(sort_seq);
-
+
sv_free( (SV*) aref);
sv_free( (SV*) href);
sv_free( (SV*) sort_seq);
rr->errcode = SvIV(err_code);
rr->sort_status = SvIV(status);
-
+
ptr = SvPV(err_str, len);
ODR_err_str = (char *)odr_malloc(rr->stream, len + 1);
strcpy(ODR_err_str, ptr);
sv_free(err_code);
sv_free(err_str);
sv_free(status);
-
+
PUTBACK;
FREETMPS;
LEAVE;
if (facet_field->attributes) {
setMember(hv, "attributes",
attributes2perl(facet_field->attributes));
- }
+ }
terms = newObject("Net::Z3950::FacetTerms", (SV *) (av = newAV()));
for (i = 0; i < facet_field->num_terms; i++) {
strlen(z_term->u.characterString));
}
tmp = newObject("Net::Z3950::FacetTerm", (SV *) (hv = newHV()));
-
+
setMember(hv, "count", sv_count);
setMember(hv, "term", sv_term);
-
+
av_push(av, tmp);
}
setMember(hv, "terms", terms);
AV *av;
int i;
sv = newObject("Net::Z3950::FacetList", (SV *) (av = newAV()));
-
+
for (i = 0; i < facet_list->num; i++) {
SV *sv = f_FacetField_to_SV(facet_list->elements[i]);
av_push(av, sv);
STRLEN s_len;
char *s_buf;
HV *hv_elem = (HV*) SvRV(sv_2mortal(av_shift(sv_terms)));
-
+
Z_FacetTerm *facet_term =
(Z_FacetTerm *) odr_malloc(odr, sizeof(*facet_term));
(*fl)->terms[i] = facet_term;
{
AV *entries = (AV *) SvRV(sv);
int num_facets;
- if (entries && SvTYPE(entries) == SVt_PVAV &&
+ if (entries && SvTYPE(entries) == SVt_PVAV &&
(num_facets = av_len(entries) + 1) > 0)
{
Z_OtherInformation *oi;
zhandle->stop_flag = 1;
}
#endif
- href = newHV();
+ href = newHV();
hv_store(href, "SETNAME", 7, newSVpv(rr->setname, 0), 0);
- if (rr->srw_sortKeys && *rr->srw_sortKeys)
+ if (rr->srw_sortKeys && *rr->srw_sortKeys)
hv_store(href, "SRW_SORTKEYS", 12, newSVpv(rr->srw_sortKeys, 0), 0);
hv_store(href, "REPL_SET", 8, newSViv(rr->replace_set), 0);
hv_store(href, "ERR_CODE", 8, newSViv(0), 0);
hv_store(href, "GHANDLE", 7, newSVsv(zhandle->ghandle), 0);
hv_store(href, "HANDLE", 6, zhandle->handle, 0);
hv_store(href, "PID", 3, newSViv(getpid()), 0);
+ hv_store(href, "PRESENT_NUMBER", 14, newSViv(rr->present_number), 0);
if ((rpnSV = zquery2perl(rr->query)) != 0) {
hv_store(href, "RPN", 3, rpnSV, 0);
}
newSVpv(rr->query->u.type_104->u.cql, 0), 0);
}
else
- {
+ {
rr->errcode = 108;
return 0;
}
PUSHMARK(sp);
-
+
XPUSHs(sv_2mortal(newRV( (SV*) href)));
-
+
PUTBACK;
handler_cv = simpleserver_sv2cv( search_ref );
point = newSVsv(*temp);
temp = hv_fetch(href, "OUTPUTFACETS", 12, 1);
- f_SV_to_FacetList(*temp, &rr->search_info, rr->stream);
+ if (SvTYPE(*temp) != SVt_NULL)
+ f_SV_to_FacetList(*temp, &rr->search_info, rr->stream);
hv_undef(href);
av_undef(aref);
zhandle->handle = point;
- sv_free( (SV*) href);
+ sv_free( (SV*) href);
PUTBACK;
FREETMPS;
if (simple->which == Z_ElementSetNames_generic)
{
hv_store(href, "COMP", 4, newSVpv(simple->u.generic, 0), 0);
- }
+ }
else
{
rr->errcode = 26;
XPUSHs(sv_2mortal(newRV( (SV*) href)));
PUTBACK;
-
+
handler_cv = simpleserver_sv2cv( fetch_ref );
perl_call_sv( (SV *) handler_cv, G_SCALAR | G_DISCARD);
hv_undef(href);
-
+
ptr = SvPV(basename, length);
ODR_basename = (char *)odr_malloc(rr->stream, length + 1);
strcpy(ODR_basename, ptr);
zhandle->handle = point;
handle = zhandle;
rr->last_in_set = SvIV(last);
-
+
if (!(rr->errcode))
{
rr->errcode = SvIV(err_code);
PUTBACK;
FREETMPS;
LEAVE;
-
+
return 0;
}
if (simple->which == Z_ElementSetNames_generic)
{
hv_store(href, "COMP", 4, newSVpv(simple->u.generic, 0), 0);
- }
+ }
else
{
rr->errcode = 26;
}
PUSHMARK(sp);
-
+
XPUSHs(sv_2mortal(newRV( (SV*) href)));
-
+
PUTBACK;
-
+
handler_cv = simpleserver_sv2cv( present_ref );
perl_call_sv( (SV *) handler_cv, G_SCALAR | G_DISCARD);
-
+
SPAGAIN;
temp = hv_fetch(href, "ERR_CODE", 8, 1);
PUTBACK;
FREETMPS;
LEAVE;
-
+
hv_undef(href);
rr->errcode = SvIV(err_code);
struct scan_entry *scan_list;
struct scan_entry *buffer;
int *step_size = rr->step_size;
+ int scan_list_size = rr->num_entries;
int i;
char **basenames;
SV **temp;
temp = hv_fetch(href, "STATUS", 6, 1);
status = newSVsv(*temp);
-
+
temp = hv_fetch(href, "NUMBER", 6, 1);
number = newSVsv(*temp);
rr->errcode = SvIV(err_code);
rr->num_entries = SvIV(number);
rr->status = SvIV(status);
+ if (yaz_version(NULL, NULL) >= 0x4022c && rr->num_entries <= scan_list_size) {
+ /* entries has been initialized by yaz and is big enough to hold all entries */
+ scan_list = rr->entries;
+ } else {
scan_list = (struct scan_entry *) odr_malloc (rr->stream, rr->num_entries * sizeof(*scan_list));
+ }
buffer = scan_list;
entries = (AV *)SvRV(entries_ref);
if (rr->errcode == 0) for (i = 0; i < rr->num_entries; i++)
scan_item = (HV *)SvRV(sv_2mortal(av_shift(entries)));
temp = hv_fetch(scan_item, "TERM", 4, 1);
ptr = SvPV(*temp, len);
- buffer->term = (char *) odr_malloc (rr->stream, len + 1);
+ buffer->term = (char *) odr_malloc (rr->stream, len + 1);
strcpy(buffer->term, ptr);
- temp = hv_fetch(scan_item, "OCCURRENCE", 10, 1);
+ temp = hv_fetch(scan_item, "OCCURRENCE", 10, 1);
buffer->occurrences = SvIV(*temp);
+ if (hv_exists(scan_item, "DISPLAY_TERM", 12))
+ {
+ temp = hv_fetch(scan_item, "DISPLAY_TERM", 12, 1);
+ ptr = SvPV(*temp, len);
+ buffer->display_term = (char *) odr_malloc (rr->stream, len + 1);
+ strcpy(buffer->display_term, ptr);
+ }
buffer++;
hv_undef(scan_item);
}
q->bend_explain = bend_explain;
}
- href = newHV();
+ href = newHV();
/* ### These should be given initial values from the client */
hv_store(href, "IMP_ID", 6, newSVpv("", 0), 0);
hv_store(href, "PASS", 4, newSVpv(passwd, 0), 0);
}
- PUSHMARK(sp);
+ PUSHMARK(sp);
XPUSHs(sv_2mortal(newRV((SV*) href)));
PUTBACK;
FREETMPS;
LEAVE;
-
- return r;
+
+ return r;
}
void bend_close(void *handle)
XPUSHs(sv_2mortal(newRV((SV *)href)));
PUTBACK;
-
+
handler_cv = simpleserver_sv2cv( close_ref );
perl_call_sv( (SV *) handler_cv, G_SCALAR | G_DISCARD);
-
+
SPAGAIN;
sv_free((SV*) href);
return;
}
+static void start_stop(struct statserv_options_block *sob, SV *handler_ref)
+{
+ HV *href;
+ dSP;
+ ENTER;
+ SAVETMPS;
+
+ href = newHV();
+ hv_store(href, "CONFIG", 6, newSVpv(sob->configname, 0), 0);
+
+ PUSHMARK(sp);
+
+ XPUSHs(sv_2mortal(newRV((SV*) href)));
+
+ PUTBACK;
+
+ if (handler_ref != NULL)
+ {
+ CV* handler_cv = simpleserver_sv2cv( handler_ref );
+ perl_call_sv( (SV *) handler_cv, G_SCALAR | G_DISCARD);
+ }
+
+ SPAGAIN;
+
+ PUTBACK;
+ FREETMPS;
+ LEAVE;
+
+
+}
+
+void bend_start(struct statserv_options_block *sob)
+{
+ start_stop(sob, start_ref);
+}
MODULE = Net::Z3950::SimpleServer PACKAGE = Net::Z3950::SimpleServer
SV *arg
CODE:
_global_ghandle = newSVsv(arg);
-
+
void
set_init_handler(arg)
SV *arg
CODE:
init_ref = newSVsv(arg);
-
+
void
set_close_handler(arg)
CODE:
explain_ref = newSVsv(arg);
+void
+set_start_handler(arg)
+ SV *arg
+ CODE:
+ start_ref = newSVsv(arg);
+
int
start_server(...)
PREINIT:
char *ptr;
int i;
STRLEN len;
+ struct statserv_options_block *sob;
CODE:
argv_buf = (char **)xmalloc((items + 1) * sizeof(char *));
argv = argv_buf;
{
ptr = SvPV(ST(i), len);
*argv_buf = (char *)xmalloc(len + 1);
- strcpy(*argv_buf++, ptr);
+ strcpy(*argv_buf++, ptr);
}
*argv_buf = NULL;
+
+ sob = statserv_getcontrol();
+ sob->bend_start = bend_start;
+ statserv_setcontrol(sob);
+
root_perl_context = PERL_GET_CONTEXT;
yaz_mutex_create(&simpleserver_mutex);
#if 0
/* only for debugging perl_clone .. */
tst_clones();
#endif
-
+
RETVAL = statserv_main(items, argv, bend_init, bend_close);
OUTPUT:
RETVAL
OUTPUT:
RETVAL
-
+
void
yazlog(arg)
SV *arg