From: Jiří Škrábal Date: Thu, 20 Jan 2005 12:26:12 +0000 (+0000) Subject: - module for LB Proxy server X-Git-Tag: glite-deployment-lb_R_1_0_1~11 X-Git-Url: http://scientific.zcu.cz/git/?a=commitdiff_plain;h=44e14d99171d23d4512b18b51f853a01af7d9edd;p=jra1mw.git - module for LB Proxy server --- diff --git a/org.glite.lb.proxy/.Makefile.swp b/org.glite.lb.proxy/.Makefile.swp new file mode 100644 index 0000000..c4f1255 Binary files /dev/null and b/org.glite.lb.proxy/.Makefile.swp differ diff --git a/org.glite.lb.proxy/LICENSE b/org.glite.lb.proxy/LICENSE new file mode 100644 index 0000000..259a91f --- /dev/null +++ b/org.glite.lb.proxy/LICENSE @@ -0,0 +1,69 @@ +LICENSE file for EGEE Middleware +================================ + +Copyright (c) 2004 on behalf of the EU EGEE Project: +The European Organization for Nuclear Research (CERN), +Istituto Nazionale di Fisica Nucleare (INFN), Italy +Datamat Spa, Italy +Centre National de la Recherche Scientifique (CNRS), France +CS Systeme d'Information (CSSI), France +Royal Institute of Technology, Center for Parallel Computers (KTH-PDC), Sweden +Universiteit van Amsterdam (UvA), Netherlands +University of Helsinki (UH.HIP), Finlan +University of Bergen (UiB), Norway +Council for the Central Laboratory of the Research Councils (CCLRC), United Kingdom + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +3. The end-user documentation included with the redistribution, if +any, must include the following acknowledgment: "This product includes +software developed by The EU EGEE Project (http://cern.ch/eu-egee/)." +Alternatively, this acknowledgment may appear in the software itself, if +and wherever such third-party acknowledgments normally appear. + +4. The names EGEE and the EU EGEE Project must not be +used to endorse or promote products derived from this software without +prior written permission. For written permission, please contact +. + +5. You are under no obligation whatsoever to provide anyone with any +bug fixes, patches, or upgrades to the features, functionality or +performance of the Software ("Enhancements") that you may develop over +time; however, if you choose to provide your Enhancements to The EU +EGEE Project, or if you choose to otherwise publish or distribute your +Enhancements, in source code form without contemporaneously requiring +end users of The EU EGEE Proejct to enter into a separate written license +agreement for such Enhancements, then you hereby grant The EU EGEE Project +a non-exclusive, royalty-free perpetual license to install, use, copy, +modify, prepare derivative works, incorporate into the EGEE Middleware +or any other computer software, distribute, and sublicense your +Enhancements or derivative works thereof, in binary and source code +form (if any), whether developed by The EU EGEE Project or third parties. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL PROJECT OR ITS CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +This software consists of voluntary contributions made by many +individuals on behalf of the EU EGEE Prject. For more information on The +EU EGEE Project, please see http://cern.ch/eu-egee/. For more information on +EGEE Middleware, please see http://egee-jra1.web.cern.ch/egee-jra1/ + + diff --git a/org.glite.lb.proxy/Makefile b/org.glite.lb.proxy/Makefile new file mode 100644 index 0000000..aa66bc6 --- /dev/null +++ b/org.glite.lb.proxy/Makefile @@ -0,0 +1,134 @@ +# defaults +top_srcdir=. +builddir=build +top_builddir=${top_srcdir}/${builddir} +stagedir=. +distdir=. +globalprefix=glite +lbprefix=lb +package=glite-lb-server +version=0.2.0 +PREFIX=/opt/glite + +glite_location=/opt/glite +globus_prefix=/opt/globus +nothrflavour=gcc32 +thrflavour=gcc32pthr +expat_prefix=/opt/expat +ares_prefix=/opt/ares +gsoap_prefix=/opt/gsoap + +-include Makefile.inc +-include ../Makefile.inc + +CC=gcc +YACC=bison -y + +VPATH=${top_srcdir}/src:${top_srcdir}/test:${top_srcdir}/examples:${top_srcdir}/project +AT3=perl -I${top_srcdir}/project ${top_srcdir}/project/at3 + +TEST_LIBS:=-L${cppunit}/lib -lcppunit +TEST_INC:=-I${cppunit}/include + +SUFFIXES = .T + +DEBUG:=-g -O0 -Wall + +CFLAGS:= ${DEBUG} \ + -DVERSION=\"${version}\" \ + -I${stagedir}/include -I${top_srcdir}/src -I. \ + -I${expat_prefix}/include \ + -I${ares_prefix}/include \ + -I${gsoap_prefix}/include \ + ${COVERAGE_FLAGS} \ + -I${mysql_prefix}/include -I${mysql_prefix}/include/mysql \ + -I${globus_prefix}/include/${nothrflavour} \ + -I${gridsite_prefix}/include -I${globus_prefix}/include/${nothrflavour}/openssl \ + -D_GNU_SOURCE + + +LINK:=libtool --mode=link ${CC} ${LDFLAGS} +LINKXX:=libtool --mode=link ${CXX} ${LDFLAGS} +INSTALL:=libtool --mode=install install +LINKXX:=libtool --mode=link ${CXX} -rpath ${stagedir}/lib ${LDFLAGS} + +GLOBUS_LIBS:= -L${globus_prefix}/lib \ + -lglobus_common_${nothrflavour} \ + -lglobus_gssapi_gsi_${nothrflavour} \ + +ifneq (${mysql_prefix},/usr) + myslqlib := -L${mysql_prefix}/lib +endif + +ifneq (${expat_prefix},/usr) + expatlib := -L${expat_prefix}/lib +endif + +EXT_LIBS:= -L${ares_prefix}/lib -lares \ + ${myslqlib} -lmysqlclient -lz\ + ${expatlib} -lexpat \ + ${GLOBUS_LIBS} + +SRVBONES_LIB:= -L${stagedir}/lib -lglite_lb_server_bones +COMMON_LIB:= -L${stagedir}/lib -lglite_lb_common_${nothrflavour} +LB_SERVER_SHARE_LIB:= -L${stagedir}/lib -lglite_lb_server +LB_PROXY_COMMON_LIB:= -L${stagedir}/lib -lglite_lb_common_${nothrflavour} + + +LB_PROXY_OBJS:= lbproxy.o + +glite_lb_proxy: ${LB_PROXY_OBJS} + ${LINK} -o $@ ${LB_PROXY_OBJS} ${LB_SERVER_SHARE_LIB} ${COMMON_LIB} ${SRVBONES_LIB} ${EXT_LIBS} + +default all: compile + +compile: glite_lb_proxy + +check: compile + -echo No test so far + +examples: + +doc: + +stage: compile + $(MAKE) install PREFIX=${stagedir} DOSTAGE=yes + +dist: distsrc distbin + +distsrc: + mkdir -p ${top_srcdir}/${package}-${version} + cd ${top_srcdir} && GLOBIGNORE="${package}-${version}" && cp -Rf * ${package}-${version} + cd ${top_srcdir} && tar -czf ${distdir}/${package}-${version}_src.tar.gz --exclude-from=project/tar_exclude ${package}-${version} + rm -rf ${top_srcdir}/${package}-${version} + +distbin: + $(MAKE) install PREFIX=`pwd`/tmpbuilddir${stagedir} + save_dir=`pwd`; cd tmpbuilddir${stagedir} && tar -czf $$save_dir/${top_srcdir}/${distdir}/${package}-${version}_bin.tar.gz *; cd $$save_dir + rm -rf tmpbuilddir + +install: + -mkdir -p ${PREFIX}/bin ${PREFIX}/etc ${PREFIX}/etc/init.d + -mkdir -p ${PREFIX}/share/doc/${package}-${version} + ${INSTALL} -m 644 ${top_srcdir}/LICENSE ${PREFIX}/share/doc/${package}-${version} + ${INSTALL} -m 755 glite_lb_proxy ${PREFIX}/bin/glite-lb-proxy + ${INSTALL} -m 644 ${top_srcdir}/config/glite-lb-dbsetup.sql ${PREFIX}/etc + +clean: + +%.c: %.c.T + rm -f $@ + ${AT3} $< >$@ || rm -f $@ + chmod -w $@ >/dev/null + +%.o: %.y + ${YACC} -d ${YFLAGS} $< + mv y.tab.c $*.c + mv y.tab.h $*.h + ${CC} -c ${CFLAGS} $*.c + rm $*.c + +%.cpp: %.cpp.T + rm -f $@ + ${AT3} $< >$@ || rm -f $@ + chmod -w $@ >/dev/null diff --git a/org.glite.lb.proxy/build.xml b/org.glite.lb.proxy/build.xml new file mode 100755 index 0000000..363037e --- /dev/null +++ b/org.glite.lb.proxy/build.xml @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.glite.lb.proxy/build/Makefile.inc b/org.glite.lb.proxy/build/Makefile.inc new file mode 100644 index 0000000..e8788fd --- /dev/null +++ b/org.glite.lb.proxy/build/Makefile.inc @@ -0,0 +1,21 @@ + +top_srcdir=.. +builddir=build +stagedir=/home/nykolas/work/Egee/glite/stage +distdir=../dist +globalprefix=glite +lbprefix=lb +package=glite-lb-proxy +PREFIX=/opt/glite +version=1.1.0 +glite_location=/home/nykolas/work/Egee/glite/stage +globus_prefix=/software/globus-2.2.4 +thrflavour=gcc32dbgpthr +nothrflavour=gcc32dbg +expat_prefix=/home/nykolas/work/Egee/repository/expat/1.95.7/rhel30_gcc32 +ares_prefix=/packages/run/ares-1.1.1 +mysql_prefix=/home/nykolas/work/Egee/repository/mysql/4.0.20/rhel30_gcc32 +cppunit=/home/nykolas/work/Egee/repository/cppunit/1.10.2/rhel30_gcc32 +gridsite_prefix=/home/nykolas/work/Egee/glite/stage +gsoap_prefix=/software/gsoap-2.6 + \ No newline at end of file diff --git a/org.glite.lb.proxy/build/glite_lb_proxy b/org.glite.lb.proxy/build/glite_lb_proxy new file mode 100755 index 0000000..5b01a45 Binary files /dev/null and b/org.glite.lb.proxy/build/glite_lb_proxy differ diff --git a/org.glite.lb.proxy/config/glite-lb-dbsetup.sql b/org.glite.lb.proxy/config/glite-lb-dbsetup.sql new file mode 100644 index 0000000..af04974 --- /dev/null +++ b/org.glite.lb.proxy/config/glite-lb-dbsetup.sql @@ -0,0 +1,112 @@ +create table jobs ( + jobid char(32) binary not null, + dg_jobid varchar(255) binary not null, + userid char(32) binary not null, + aclid char(32) binary null, + + primary key (jobid), + unique (dg_jobid), + index (userid) +); + +create table users ( + userid char(32) binary not null, + cert_subj varchar(255) binary not null, + + primary key (userid), + unique (cert_subj) +); + +create table events ( + jobid char(32) binary not null, + event int not null, + code int not null, + prog varchar(255) binary not null, + host varchar(255) binary not null, + time_stamp datetime not null, + userid char(32) binary null, + usec int null, + level int null, + + arrived datetime not null, + + + primary key (jobid,event), + index (time_stamp), + index (host), + index (arrived) +); + +create table short_fields ( + jobid char(32) binary not null, + event int not null, + name varchar(200) binary not null, + value varchar(255) binary null, + + primary key (jobid,event,name) +); + +create table long_fields ( + jobid char(32) binary not null, + event int not null, + name varchar(200) binary not null, + value mediumblob null, + + primary key (jobid,event,name) +); + +create table states ( + jobid char(32) binary not null, + status int not null, + seq int not null, + int_status mediumblob not null, + version varchar(32) not null, + parent_job varchar(32) binary not null, + + primary key (jobid), + index (parent_job) + +); + +create table status_tags ( + jobid char(32) binary not null, + seq int not null, + name varchar(200) binary not null, + value varchar(255) binary null, + + primary key (jobid,seq,name) +); + +create table server_state ( + prefix varchar(100) not null, + name varchar(100) binary not null, + value varchar(255) binary not null, + + primary key (prefix,name) +); + +create table acls ( + aclid char(32) binary not null, + value mediumblob not null, + refcnt int not null, + + primary key (aclid) +); + +create table notif_registrations ( + notifid char(32) binary not null, + destination varchar(200) not null, + valid datetime not null, + userid char(32) binary not null, + conditions mediumblob not null, + + primary key (notifid) +); + +create table notif_jobs ( + notifid char(32) binary not null, + jobid char(32) binary not null, + + primary key (notifid,jobid), + index (jobid) +); diff --git a/org.glite.lb.proxy/project/MultiStruct.pm b/org.glite.lb.proxy/project/MultiStruct.pm new file mode 100644 index 0000000..9cd847c --- /dev/null +++ b/org.glite.lb.proxy/project/MultiStruct.pm @@ -0,0 +1,191 @@ +package MultiStruct; + +use StructField; + +sub new { + shift; + my $self = {}; + $self->{comments} = {}; # typ->comment + $self->{fields} = {}; # typ->{ name->StructField, ... } + $self->{order} = {}; + + bless $self; +} + +sub selectType { + my $self = shift; + my $type = shift; + $self->{type} = $type; + 1; +} + +sub addType { + my $self = shift; + my $type = shift; + my $comment = shift; + $self->selectType($type); + $self->{comments}->{$type} = $comment; + $self->{fields}->{$type} = {}; + 1; +} + +sub selectField { + my $self = shift; + $self->{field} = shift; + $self->getField; +} + +sub addField { + my $self = shift; + my $field = shift; + + die "unselected type" unless $self->{type}; + $self->{fields}->{$self->{type}}->{$field->{name}} = $field; + $self->selectField($field->{name}); + 1; +} + +sub getField { + my $self = shift; + my $f = $self->{fields}->{$self->{type}}->{$self->{field}}; + return $f ? $f : $self->{fields}->{_common_}->{$self->{field}}; +} + +sub load { + my $self = shift; + my $fh = shift; + local $_; + + while ($_ = <$fh>) { + + chomp; + s/#.*$//; + next if /^\s*$/; + + if (/^\@type\s+(\S+)\s*(.*$)$/) { + $self->addType($1,$2); + $self->{order}->{$1} = $.; + next; + } + + s/^\s*//; + my ($ftype,$fname,$comment) = split /\s+/,$_,3; + if ($ftype eq '_code_') { + my $f = $self->getField(); + addCode $f $fname,$comment; + } + elsif ($ftype eq '_alias_') { + my $f = $self->getField(); + addAlias $f $fname,$comment; + } + elsif ($ftype eq '_special_') { + my $f = $self->getField(); + addSpecial $f $fname; + } + elsif ($ftype eq '_null_') { + my $f = $self->getField(); + setNull $f $fname; + } + elsif ($ftype eq '_optional_') { + my $f = $self->getField(); + $f->{optional} = 1; + } + elsif ($ftype eq '_index_') { + my $f = $self->getField(); + $f->{index} = 1; + } + else { + my $f = new StructField $fname,$ftype,$comment,$.; + $self->addField($f); + } + } +} + +sub getTypes { + my $self = shift; + my @out; + local $_; + + for (keys %{$self->{fields}}) { + push @out,$_ unless $_ eq '_common_'; + } + @out; +} + +sub getTypesOrdered { + my $self = shift; + my @names = getTypes $self; + + sort { + my $oa = $self->{order}->{$a}; + my $ob = $self->{order}->{$b}; + $oa <=> $ob; + } @names; +} + +sub getTypeComment { + my $self = shift; + my $type = shift || $self->{type}; + $self->{comments}->{$type}; +} + +sub getFieldComment { + my $self = shift; + my $fname = shift; + $self->{fields}->{$self->{type}}->{$fname}->{comment}; +} + +sub getFields { + my $self = shift; + keys %{$self->{fields}->{$self->{type}}}; +} + +sub getFieldsOrdered { + my $self = shift; + my @names = $self->getFields; + sort { + my $oa = $self->selectField($a)->{order}; + my $ob = $self->selectField($b)->{order}; + $oa <=> $ob; + } @names; +} + +sub getFieldOccurence { + my $self = shift; + my $fname = shift; + my @out; + local $_; + + for (keys %{$self->{fields}}) { + push @out,$_ if $self->{fields}->{$_}->{$fname}; + } + @out; +} + +sub getAllFields { + my $self = shift; + my %out; + local $_; + + for my $t (values %{$self->{fields}}) { + $out{$_->{name}} = 1 for (values %$t); + } + keys %out; +} + +sub getAllFieldsOrdered { + my $self = shift; + my @names = getAllFields $self; + + sort { + my @occ = $self->getFieldOccurence($a); + $self->selectType($occ[0]); + my $oa = $self->selectField($a)->{order}; + @occ = $self->getFieldOccurence($b); + $self->selectType($occ[0]); + my $ob = $self->selectField($b)->{order}; + $oa <=> $ob; + } @names; +} + +1; diff --git a/org.glite.lb.proxy/project/StructField.pm b/org.glite.lb.proxy/project/StructField.pm new file mode 100644 index 0000000..95d33b8 --- /dev/null +++ b/org.glite.lb.proxy/project/StructField.pm @@ -0,0 +1,116 @@ +package StructField; + +$lang = 'C'; +1; + +sub new { + shift; + my $self = {}; + $self->{name} = shift; + $self->{type} = shift; + $self->{comment} = shift; + $self->{order} = shift; + $self->{null} = $main::DefaultNullValue{$self->{type}}; + bless $self; +} + +sub addCode { + my $self = shift; + my $code = shift; + my $comment = shift; + push @{$self->{codes}},{name=>$code,comment=>$comment}; + 1; +} + +sub addSpecial { + my $self = shift; + my $special = shift; + $self->{special} = $special; + 1; +} + +sub addAlias { + my $self = shift; + my $name = shift; + my $lang = shift; + $self->{aliases}->{$lang} = $name; + 1; +} + +sub hasAlias { + my $self = shift; + my $lang = shift; + return $self->{aliases}->{$lang} ? 1 : 0; +} + +sub getName { + my $self = shift; + my $lang = shift || $lang; + $self->{aliases}->{$lang} || $self->{name}; +# return $self->{aliases}->{$lang} ? $self->{aliases}->{$lang} : $self->{name}; +} + +sub getComment { + my $self = shift; + $self->{comment}; +} + +sub getDefaultNullValue { + my $self = shift; + $self->{null}; +} + +sub toString { + my $self = shift; + my $src = shift; + my $dst = shift; + + eval $main::toString{$lang}->{$self->{type}}; +} + +sub fromString { + my $self = shift; + my $src = shift; + my $dst = shift; + + eval $main::fromString{$lang}->{$self->{type}}; +} + +sub isNULL { + my $self = shift; + my $a = shift; + my $b = $self->{null}; + + eval $main::compare{$lang}->{$self->{type}}; +} + +sub isnotNULL { + my $self = shift; + my $src = shift; + + '!('.$self->isNULL($src).')'; +} + +sub compare { + my $self = shift; + my $a = shift; + my $b = shift; + eval $main::compare{$lang}->{$self->{type}}; +} + +sub toFormatString { + my $self = shift; + + eval $main::toFormatString{$lang}->{$self->{type}}; +} + +sub setNull { + my $self = shift; + $self->{null} = shift; +} + +sub getType { + my $self = shift; + + eval $main::types{$lang}->{$self->{type}}; +} diff --git a/org.glite.lb.proxy/project/at3 b/org.glite.lb.proxy/project/at3 new file mode 100644 index 0000000..8ff52ec --- /dev/null +++ b/org.glite.lb.proxy/project/at3 @@ -0,0 +1,93 @@ +#!/usr/bin/perl -w + +use File::Basename; +my $dir; +BEGIN{ + $dir = dirname $0; +} + +my $lines = $ENV{AT3_LINES}; + +use lib $dir; +use MultiStruct; +require 'types.T'; + +my $eventsn; +for (@INC) { + if (-f "$_/events.T") { + $eventsn="$_/events.T"; + last; + } +} + +my $statusn; +for (@INC) { + if (-f "$_/status.T") { + $statusn = "$_/status.T"; + last; + } +} + +my $indent = ''; + +my $event = new MultiStruct; +my $status = new MultiStruct; + +sub gen { + local $_ = shift; + + s/^\n!//; + s/\n!/\n/g; + print $_; +} + + +open EVENTS,$eventsn or die "$eventsn: $!\n"; +$event->load(\*EVENTS); +close EVENTS; + +open STATUS,$statusn or die "$statusn: $!\n"; +$status->load(\*STATUS); +close STATUS; + +my $code; +my $startcode; +while (<>) { + chomp; + if (/^\@\@\@LANG: (\S+)$/) { + $StructField::lang = $1; + next; + } + + if ($code) { + if (/^\@\@\@}$/) { + $code .= "1;\n"; + print "#line $startcode \"$ARGV\"\n/* begin */\n" if $lines; + eval $code or warn "eval: $@ at $ARGV:$.\n"; + my $nxtline = $.+1; + print "/* end */\n#line $nxtline \"$ARGV\"\n" if $lines; + undef $code; + } + else { $code .= $_."\n"; } + } + else { + if (/^\@\@\@{$/) { + $startcode = $.; + $code = "\n"; + } + elsif (/^\@\@\@AUTO$/) { + print qq{ + !! Automatically generated file + !! Do not edit, your changes will be discarded upon build + !! Change the corresponding template file $ARGV + +}; + print "#line $. \"$ARGV\"\n" if $lines; + } + else { + print "$_\n"; + } + } +} + +# print $event_common{prog}->copy('bla','hu'); diff --git a/org.glite.lb.proxy/project/build.properties b/org.glite.lb.proxy/project/build.properties new file mode 100644 index 0000000..e69de29 diff --git a/org.glite.lb.proxy/project/configure.properties.xml b/org.glite.lb.proxy/project/configure.properties.xml new file mode 100644 index 0000000..9238a36 --- /dev/null +++ b/org.glite.lb.proxy/project/configure.properties.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + +top_srcdir=.. +builddir=build +stagedir=${stage.abs.dir} +distdir=${dist.dir} +globalprefix=${global.prefix} +lbprefix=${subsystem.prefix} +package=${module.package.name} +PREFIX=${install.dir} +version=${module.version} +glite_location=${with.glite.location} +globus_prefix=${with.globus.prefix} +thrflavour=${with.globus.thr.flavor} +nothrflavour=${with.globus.nothr.flavor} +expat_prefix=${with.expat.prefix} +ares_prefix=${with.ares.prefix} +mysql_prefix=${with.mysql.prefix} +cppunit=${with.cppunit.prefix} +gridsite_prefix=${with.gridsite.prefix} +gsoap_prefix=${with.gsoap.prefix} + + + diff --git a/org.glite.lb.proxy/project/events.T b/org.glite.lb.proxy/project/events.T new file mode 100644 index 0000000..b8e5399 --- /dev/null +++ b/org.glite.lb.proxy/project/events.T @@ -0,0 +1,183 @@ +@type _common_ + timeval timestamp timestamp of event generation + _alias_ date ULM + timeval arrived timestamp of event store + _alias_ arr_date ULM + _optional_ + string host hostname of the machine where the event was generated + _alias_ host ULM + int level logging level (system, debug, ...) + _alias_ lvl ULM + _code_ EMERGENCY emergency + _code_ ALERT alert + _code_ ERROR error + _code_ WARNING warning + _code_ AUTH authentication + _code_ SECURITY security + _code_ USAGE usage + _code_ SYSTEM system + _code_ IMPORTANT important + _code_ DEBUG debug + int priority message priority (yet 0 for asynchronous and 1 for synchronous transfers) + _null_ -1 + jobid jobId DataGrid job id of the source job + string seqcode sequence code assigned to the event + string user identity (cert. subj.) of the generator + logsrc source source (WMS component) which generated this event +# string prog name of program ("EDG WMS" of name of the application) + string src_instance instance of WMS component (e.g. service communication endpoint) + _optional_ + +@type Transfer Start, success, or failure of job transfer to another component + logsrc destination destination where the job is being transfered to + string dest_host destination hostname + string dest_instance destination instance + _optional_ + string job job description in receiver language + int result result of the attempt + _code_ START the sending component has started or is about to start the transfer + _code_ OK job was sent successfully + _code_ REFUSED job was refused by the other component + _code_ FAIL transfer failed for other reason than explicit refusal (eg. network timeout) + string reason detailed description of transfer, especially reason of failure + _optional_ + string dest_jobid destination internal jobid + _optional_ + +@type Accepted Accepting job (successful couterpart to Transfer) + logsrc from where was the job received from + string from_host sending component hostname + string from_instance sending component instance + _optional_ + string local_jobid new jobId (Condor, Globus ...) assigned by the receiving component + +@type Refused Refusing job (unsuccessful couterpart to Transfer) + logsrc from where was the job received from + string from_host sending component hostname + string from_instance sending component instance + _optional_ + string reason reason of refusal + +@type EnQueued The job has been enqueued in an inter-component queue + string queue destination queue + string job job description in receiver language + int result result of the attempt + _code_ START the sending component has started or is about to start the transfer + _code_ OK job was sent successfully + _code_ REFUSED job was refused by the other component + _code_ FAIL transfer failed for other reason than explicit refusal (eg. network timeout) + string reason detailed description of transfer, especially reason of failure + +@type DeQueued The job has been dequeued from an inter-component queue + string queue queue name + string local_jobid new jobId assigned by the receiving component + +@type HelperCall Helper component is called + string helper_name name of the called component + string helper_params parameters of the call + int src_role whether the logging component is called or calling one + _code_ CALLING the logging component is caller + _code_ CALLED the logging component is callee + +@type HelperReturn Helper component is returning the control + string helper_name name of the called component + string retval returned data + int src_role whether the logging component is called or calling one + _code_ CALLING the logging component is caller + _code_ CALLED the logging component is callee + +@type Running Executable started + string node worker node where the executable is run + +@type Resubmission Result of resubmission decision + int result result code + _code_ WILLRESUB will be resubmitted + _code_ WONTRESUB will not be resubmitted + string reason reason for the decision + string tag value of the attribute on which the decision is based + +@type Done Execution terminated (normally or abnormally) + int status_code way of termination + _code_ OK terminated by itself + _code_ FAILED disappeared from LRMS + _code_ CANCELLED cancelled by user request + string reason reason for the change + int exit_code process exit code + _null_ -1 + +@type Cancel Cancel operation has been attempted on the job + int status_code classification of the cancel + _code_ REQ request acknowledged + _code_ REFUSE request declined by this component + _code_ DONE request completed by whole WMS + _code_ ABORT request refused by whole WMS + string reason detailed description + +@type Abort Job aborted by system + string reason reason of abort + +@type Clear Job cleared, output sandbox removed + int reason why the job was cleared + _code_ USER user retrieved output sandbox + _code_ TIMEOUT timed out, resource purge forced + _code_ NOOUTPUT no output was generated + +@type Purge Job is purged from bookkepping server + +@type Match Matching CE found + string dest_id Id of the destination CE/queue + +@type Pending No match found yet + string reason why matching CE cannot be found + +@type RegJob New job registration + string jdl job description + string ns NetworkServer handling the job + jobid parent jobid of parent job + _optional_ + + int jobtype job type + _code_ SIMPLE simple job + _code_ DAG dag (containing static set of subjobs) + _code_ PARTITIONABLE partitionable (may become partitioned) + _code_ PARTITIONED partitioned (dynamically created dag) + + int nsubjobs number of subjobs + _optional_ + string seed seed for subjob id generation + _optional_ + +@type Chkpt Application-specific checkpoint record + string tag checkpoint tag + string classad checkpoint value + +@type Listener Listening network port for interactive control + string svc_name port instance name + string svc_host hostname + port svc_port port number + +@type CurDescr current state of job processing (optional event) + string descr description of current job transformation (output of helper) + +@type UserTag user tag -- arbitrary name=value pair + string name tag name + string value tag value + +@type ChangeACL Management of ACL stored on bookkepping server + string user_id DN or VOMS parameter (in format VO:group) + int user_id_type type of information given in user_id (DN or VOMS) + _null_ -1 + int permission ACL permission to change (currently only READ) + _null_ -1 + int permission_type type of permission requested ('allow', 'deny') + _null_ -1 + int operation operation requested to perform with ACL (add, remove) + _null_ -1 + +@type Notification Management of notification service + notifid notifId notification id + string owner owner + string dest_host destination host + port dest_port destination port + string jobstat job status + diff --git a/org.glite.lb.proxy/project/properties.xml b/org.glite.lb.proxy/project/properties.xml new file mode 100755 index 0000000..3bc980c --- /dev/null +++ b/org.glite.lb.proxy/project/properties.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/org.glite.lb.proxy/project/status.T b/org.glite.lb.proxy/project/status.T new file mode 100644 index 0000000..10071ac --- /dev/null +++ b/org.glite.lb.proxy/project/status.T @@ -0,0 +1,77 @@ +@type _common_ +jobid jobId Id of the job +string owner Job owner +_index_ + +int jobtype Type of job + _null_ -1 + _code_ SIMPLE simple job + _code_ DAG composite job +jobid parent_job parent job of subjob + +string seed string used for generation of subjob IDs +int children_num number of subjobs +strlist children list of subjob IDs + _special_ XMLstructured +intlist children_hist summary (histogram) of children job states + _special_ XMLstructured +stslist children_states full status information of the children + _special_ XMLstructured + +string condorId Id within Condor-G +string globusId Globus allocated Id +string localId Id within LRMS + +string jdl User submitted job description +string matched_jdl Full job description after matchmaking +string destination ID of CE where the job is being sent +_index_ +string condor_jdl ClassAd passed to Condor-G for last job execution +string rsl Job RSL sent to Globus + +string reason Reason of being in this status, if any + +string location Where the job is being processed +_index_ +string ce_node Worker node where the job is executed +string network_server Network server handling the job + +bool subjob_failed Subjob failed (the parent job will fail too) +int done_code Return code + _null_ -1 + _code_ OK Finished correctly + _code_ FAILED Execution failed + _code_ CANCELLED Cancelled by user +int exit_code Unix exit code +bool resubmitted The job was resubmitted + +bool cancelling Cancellation request in progress +string cancelReason Reason of cancel + +int cpuTime Consumed CPU time + _null_ -1 + +taglist user_tags List of pairs (user_tag, user_value) + _special_ XMLstructured + +timeval stateEnterTime When entered this status +timeval lastUpdateTime Last known event of the job + +intlist stateEnterTimes When all previous states were entered + _special_ XMLstructured + +bool expectUpdate Some logged information has not arrived yet +string expectFrom Sources of the missing information +string acl ACL of the job + +@type Submitted entered by the user to the User Interface or registered by Job Partitioner +@type Waiting Accepted by WMS, waiting for resource allocation +@type Ready Matching resources found +@type Scheduled Accepted by LRMS queue +@type Running Executable is running +@type Done Execution finished, output is available +@type Cleared Output transfered back to user and freed +@type Aborted Aborted by system (at any stage) +@type Cancelled Cancelled by user +@type Unknown Status cannot be determined +@type Purged Job has been purged from bookkeeping server (for LB->RGMA interface) diff --git a/org.glite.lb.proxy/project/tar_exclude b/org.glite.lb.proxy/project/tar_exclude new file mode 100644 index 0000000..b3133e4 --- /dev/null +++ b/org.glite.lb.proxy/project/tar_exclude @@ -0,0 +1,10 @@ +tar_exclude +CVS +build.xml +build +build.properties +properties.xml +configure-options.xml +.cvsignore +.project +.cdtproject diff --git a/org.glite.lb.proxy/project/types.T b/org.glite.lb.proxy/project/types.T new file mode 100644 index 0000000..ccabc74 --- /dev/null +++ b/org.glite.lb.proxy/project/types.T @@ -0,0 +1,108 @@ +%types = ( + C=>{ + bool=>'"int"', + string=>'"char *"', + strlist=>'"char **"', + intlist=>'"int *"', + taglist=>'"edg_wll_TagValue *"', + stslist=>'"struct _edg_wll_JobStat *"', + timeval=>'"struct timeval"', + jobid=>'"edg_wlc_JobId"', + notifid=>'"edg_wll_NotifId"', + logsrc=>'"edg_wll_Source"', + port=>'"uint16_t"', +# level=>'"enum edg_wll_Level"', + int=>'"int"' + }, + 'C++'=>{ + string=>'"std::string"', + timeval=>'"struct timeval"', + jobid=>'"edg::workload::common::jobid::JobId"', + bool=>'"int"', + intlist=>'"std::vector"', + strlist=>'"std::vector"', + taglist=>'"std::vector>"', + stslist=>'"std::vector"', + logsrc=>'"int"', + port=>'"int"', + int=>'"int"' + } +); + +%toString = ( + C=>{ + int=>'qq{asprintf(&$dst,"%d",$src);}', + port=>'qq{asprintf(&$dst,"%d",(int) $src);}', + bool=>'qq{asprintf(&$dst,"%d",$src);}', + string=>'qq{$dst = $src?strdup($src):NULL;}', + timeval=>'qq{edg_wll_ULMTimevalToDate(($src).tv_sec,($src).tv_usec,$dst);}', + jobid=>'qq{$dst = edg_wlc_JobIdUnparse($src);}', + notifid=>'qq{$dst = edg_wll_NotifIdUnparse($src);}', +# level=>'qq{$dst = edg_wll_LevelToString($src);}', + logsrc=>'qq{$dst = edg_wll_SourceToString($src);}', +# strlist, intlist, stslist are used only in consumer API, they don't need toString method + } +); + +%ULMasString = ( + logsrc=>1 +); + +%fromString = ( + C=>{ + int=>'qq{$dst = atoi($src);}', + port=>'qq{$dst = (uint16_t) atoi($src);}', + bool=>'qq{$dst = atoi($src);}', + string=>'qq{$dst = strdup($src);}', + timeval=>'qq{edg_wll_ULMDateToTimeval($src,&$dst);}', + jobid=>'qq{edg_wlc_JobIdParse($src,&$dst);}', + notifid=>'qq{edg_wll_NotifIdParse($src,&$dst);}', +# level=>'qq{$dst = edg_wll_StringToLevel($src);}', + logsrc=>'qq{$dst = edg_wll_StringToSource($src);}', +# strlist, intlist, stslist are used only in consumer API, they don't need fromString method + } +); + +%DefaultNullValue = ( + int=>0, + port=>0, +# level=>'EDG_WLL_LEVEL_UNDEFINED', + bool=>0, + string=>'NULL', + jobid=>'NULL', + notifid=>'NULL', + logsrc=>'EDG_WLL_SOURCE_NONE', + timeval=>'null_timeval', + strlist=>'NULL', + intlist=>'NULL', + taglist=>'NULL', + stslist=>'NULL', +); + +%compare = ( + C=>{ + int=>'"($a == $b)"', + port=>'"($a == $b)"', +# level=>'"($a == $b)"', + bool=>'"(($a || !$b) && ($b || !$a))"', + string=>'"(($a) == NULL && ($b) == NULL) || (($a)&&($b)&& !strcmp($a,$b))"', + jobid=>'"(($a) == NULL && ($b) == NULL) || (($a)&&($b)&& !strcmp(edg_wlc_JobIdUnparse($a),edg_wlc_JobIdUnparse($b)))"', + notifid=>'"($a) == ($b)"', + logsrc=>'"($a) == ($b)"', + timeval=>'"($a).tv_sec == ($b).tv_sec && ($a).tv_usec == ($b).tv_usec"', + } +); + +%toFormatString = ( + C=>{ + int=>'"%d"', + port=>'"%d"', + bool=>'"%d"', +# level=>'"%s"', + string=>'"%|Us"', + jobid=>'"%s"', + notifid=>'"%s"', + logsrc=>'"%s"', + timeval=>'"%s"', + } +); diff --git a/org.glite.lb.proxy/project/version.properties b/org.glite.lb.proxy/project/version.properties new file mode 100644 index 0000000..acd8cb9 --- /dev/null +++ b/org.glite.lb.proxy/project/version.properties @@ -0,0 +1,4 @@ +#Wed Jan 12 04:18:30 CET 2005 +module.version=1.1.0 +module.build=0 +module.age=0 diff --git a/org.glite.lb.proxy/src/lbproxy.c b/org.glite.lb.proxy/src/lbproxy.c new file mode 100644 index 0000000..1d305de --- /dev/null +++ b/org.glite.lb.proxy/src/lbproxy.c @@ -0,0 +1,543 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "glite/lb/srvbones.h" +#include "glite/lb/context.h" +#include "glite/lb/context-int.h" + +extern int edg_wll_DBCheckVersion(edg_wll_Context); +extern edg_wll_ErrorCode edg_wll_Open(edg_wll_Context ctx, char *cs); +extern edg_wll_ErrorCode edg_wll_Close(edg_wll_Context); +extern int edg_wll_StoreProtoProxy(edg_wll_Context ctx); +extern int edg_wll_ServerHTTP(edg_wll_Context ctx); + +extern char *lbproxy_ilog_socket_path; +extern char *lbproxy_ilog_file_prefix; + + +#define DEFAULTCS "lbserver/@localhost:lbserver20" +/* +#define DEFAULTCS "lbserver/@localhost:lbproxy" +*/ + +#define CON_QUEUE 20 /* accept() */ +#define SLAVE_OVERLOAD 10 /* queue items per slave */ +#define CLNT_TIMEOUT 10 /* keep idle connection that many seconds */ +#define TOTAL_CLNT_TIMEOUT 60 /* one client may ask one slave multiple times */ + /* but only limited time to avoid DoS attacks */ +#define CLNT_REJECT_TIMEOUT 100000 /* time limit for client rejection in !usec! */ +#define DNS_TIMEOUT 5 /* how long wait for DNS lookup */ +#define SLAVE_CONNS_MAX 500 /* commit suicide after that many connections */ +#define MASTER_TIMEOUT 30 /* maximal time of one-round of master network communication */ +#define SLAVE_TIMEOUT 30 /* maximal time of one-round of slave network communication */ + +/* file to store pid and generate semaphores key + */ +#ifndef GLITE_LBPROXY_PIDFILE +#define GLITE_LBPROXY_PIDFILE "/var/run/glite-lbproxy.pid" +#endif + +#ifndef GLITE_LBPROXY_SOCK_PREFIX +#define GLITE_LBPROXY_SOCK_PREFIX "/tmp/lb_proxy_" +#endif + +#ifndef dprintf +#define dprintf(x) { if (debug) printf x; } +#endif + +#define sizofa(a) (sizeof(a)/sizeof((a)[0])) + + +int debug = 0; +static const int one = 1; +static char *dbstring = NULL; +static char sock_store[PATH_MAX], + sock_serve[PATH_MAX]; +static int slaves = 10, + semaphores = -1, + semset; + + +static struct option opts[] = { + {"port", 1, NULL, 'p'}, + {"debug", 0, NULL, 'd'}, + {"mysql", 1, NULL, 'm'}, + {"slaves", 1, NULL, 's'}, + {"semaphores", 1, NULL, 'l'}, + {"pidfile", 1, NULL, 'i'}, + {"proxy-il-sock", 1, NULL, 'X'}, + {"proxy-il-fprefix", 1, NULL, 'Y'}, + {NULL,0,NULL,0} +}; + +static const char *get_opt_string = "p:dm:s:l:i:X:Y:"; + +static void usage(char *me) +{ + fprintf(stderr,"usage: %s [option]\n" + "\t-p, --sock\t path-name to the local socket\n" + "\t-m, --mysql\t database connect string\n" + "\t-d, --debug\t don't run as daemon, additional diagnostics\n" + "\t-s, --slaves\t number of slave servers to fork\n" + "\t-l, --semaphores number of semaphores (job locks) to use\n" + "\t-i, --pidfile\t file to store master pid\n" + "\t--proxy-il-sock\t socket to send events to\n" + "\t--proxy-il-fprefix\t file prefix for events\n" + ,me); +} + +static void wait_for_open(edg_wll_Context,const char *); + + +/* + * SERVER BONES structures and handlers + */ +int clnt_data_init(void **); + + /* + * Serve & Store handlers + */ +int clnt_reject(int); +int handle_conn(int, struct timeval, void *); +int accept_serve(int, void *); +int accept_store(int, void *); +int clnt_disconnect(int, void *); + +#define SRV_SERVE 0 +#define SRV_STORE 1 +static struct glite_srvbones_service service_table[] = { + { "serve", -1, handle_conn, accept_serve, clnt_reject, clnt_disconnect }, + { "store", -1, handle_conn, accept_store, clnt_reject, clnt_disconnect }, +}; + +struct clnt_data_t { + edg_wll_Context ctx; + void *mysql; +}; + + + +int main(int argc, char *argv[]) +{ + int i; + struct sockaddr_un a; + int opt; + char pidfile[PATH_MAX] = GLITE_LBPROXY_PIDFILE, + socket_path_prefix[PATH_MAX] = GLITE_LBPROXY_SOCK_PREFIX, + *name; + FILE *fpid; + key_t semkey; + edg_wll_Context ctx; + struct timeval to; + + + + name = strrchr(argv[0],'/'); + if (name) name++; else name = argv[0]; + + if (geteuid()) snprintf(pidfile,sizeof pidfile,"%s/glite_lb_proxy.pid", getenv("HOME")); + + while ((opt = getopt_long(argc, argv, get_opt_string, opts, NULL)) != EOF) switch (opt) { + case 'p': strcpy(socket_path_prefix, optarg); break; + case 'd': debug = 1; break; + case 'm': dbstring = optarg; break; + case 's': slaves = atoi(optarg); break; + case 'l': semaphores = atoi(optarg); break; + case 'X': lbproxy_ilog_socket_path = strdup(optarg); break; + case 'Y': lbproxy_ilog_file_prefix = strdup(optarg); break; + case 'i': strcpy(pidfile, optarg); break; + case '?': usage(name); return 1; + } + + if ( optind < argc ) { usage(name); return 1; } + + setlinebuf(stdout); + setlinebuf(stderr); + + fpid = fopen(pidfile,"r"); + if ( fpid ) { + int opid = -1; + + if ( fscanf(fpid,"%d",&opid) == 1 ) { + if ( !kill(opid,0) ) { + fprintf(stderr,"%s: another instance running, pid = %d\n",argv[0],opid); + return 1; + } + else if (errno != ESRCH) { perror("kill()"); return 1; } + } + fclose(fpid); + } else if (errno != ENOENT) { perror(pidfile); return 1; } + + fpid = fopen(pidfile, "w"); + if ( !fpid ) { perror(pidfile); return 1; } + fprintf(fpid, "%d", getpid()); + fclose(fpid); + + semkey = ftok(pidfile,0); + + if ( semaphores == -1 ) semaphores = slaves; + semset = semget(semkey, 0, 0); + if ( semset >= 0 ) semctl(semset, 0, IPC_RMID); + semset = semget(semkey, semaphores, IPC_CREAT | 0600); + if ( semset < 0 ) { perror("semget()"); return 1; } + dprintf(("Using %d semaphores, set id %d\n", semaphores, semset)); + for ( i = 0; i < semaphores; i++ ) { + struct sembuf s; + + s.sem_num = i; s.sem_op = 1; s.sem_flg = 0; + if (semop(semset,&s,1) == -1) { perror("semop()"); return 1; } + } + + service_table[SRV_SERVE].conn = socket(PF_UNIX, SOCK_STREAM, 0); + if ( service_table[SRV_SERVE].conn < 0 ) { perror("socket()"); return 1; } + memset(&a, 0, sizeof(a)); + a.sun_family = AF_UNIX; + sprintf(sock_serve, "%s%s", socket_path_prefix, "serve.sock"); + strcpy(a.sun_path, sock_serve); + + if( connect(service_table[SRV_SERVE].conn, (struct sockaddr *)&a, sizeof(a.sun_path)) < 0) { + if( errno == ECONNREFUSED ) { + dprintf(("removing stale input socket %s\n", sock_serve)); + unlink(sock_serve); + } + } else { perror("another instance of lb-proxy is running"); return 1; } + + if ( bind(service_table[SRV_SERVE].conn, (struct sockaddr *) &a, sizeof(a)) < 0 ) { + char buf[100]; + + snprintf(buf, sizeof(buf), "bind(%s)", sock_serve); + perror(buf); + return 1; + } + + if ( listen(service_table[SRV_SERVE].conn, CON_QUEUE) ) { perror("listen()"); return 1; } + + service_table[SRV_STORE].conn = socket(PF_UNIX, SOCK_STREAM, 0); + if ( service_table[SRV_STORE].conn < 0 ) { perror("socket()"); return 1; } + memset(&a, 0, sizeof(a)); + a.sun_family = AF_UNIX; + sprintf(sock_store, "%s%s", socket_path_prefix, "store.sock"); + strcpy(a.sun_path, sock_store); + + if( connect(service_table[SRV_STORE].conn, (struct sockaddr *)&a, sizeof(a.sun_path)) < 0) { + if( errno == ECONNREFUSED ) { + dprintf(("removing stale input socket %s\n", sock_store)); + unlink(sock_store); + } + } else { perror("another instance of lb-proxy is running"); return 1; } + + if ( bind(service_table[SRV_STORE].conn, (struct sockaddr *) &a, sizeof(a))) { + char buf[100]; + + snprintf(buf, sizeof(buf), "bind(%s)", sock_store); + perror(buf); + return 1; + } + if ( listen(service_table[SRV_STORE].conn, CON_QUEUE) ) { perror("listen()"); return 1; } + + dprintf(("Listening at %s, %s ...\n", sock_store, sock_serve)); + + if (!dbstring) dbstring = getenv("LBPROXYDB"); + if (!dbstring) dbstring = DEFAULTCS; + + + /* Just check the database and let it be. The slaves do the job. */ + /* XXX: InitContextProxy() !!! + * edg_wll_InitContext(&ctx) causes segfault + */ + if ( !(ctx = (edg_wll_Context) malloc(sizeof(*ctx))) ) { + perror("InitContext()"); + return -1; + } + memset(ctx, 0, sizeof(*ctx)); + wait_for_open(ctx, dbstring); + if (edg_wll_DBCheckVersion(ctx)) { + char *et,*ed; + edg_wll_Error(ctx,&et,&ed); + + fprintf(stderr,"%s: open database: %s (%s)\n",argv[0],et,ed); + return 1; + } + edg_wll_Close(ctx); + edg_wll_FreeContext(ctx); + + if ( !debug ) { + if ( daemon(1,0) == -1 ) { perror("deamon()"); exit(1); } + + fpid = fopen(pidfile,"w"); + if ( !fpid ) { perror(pidfile); return 1; } + fprintf(fpid, "%d", getpid()); + fclose(fpid); + openlog(name, LOG_PID, LOG_DAEMON); + } else { setpgid(0, getpid()); } + + + glite_srvbones_set_param(GLITE_SBPARAM_SLAVES_CT, slaves); + glite_srvbones_set_param(GLITE_SBPARAM_SLAVE_OVERLOAD, SLAVE_OVERLOAD); + glite_srvbones_set_param(GLITE_SBPARAM_SLAVE_CONNS_MAX, SLAVE_CONNS_MAX); + to = (struct timeval){CLNT_TIMEOUT, 0}; + glite_srvbones_set_param(GLITE_SBPARAM_CLNT_TIMEOUT, &to); + to = (struct timeval){TOTAL_CLNT_TIMEOUT, 0}; + glite_srvbones_set_param(GLITE_SBPARAM_TOTAL_CLNT_TIMEOUT, &to); + + glite_srvbones_run(clnt_data_init, service_table, sizofa(service_table), debug); + + + semctl(semset, 0, IPC_RMID, 0); + unlink(pidfile); + for ( i = 0; i < sizofa(service_table); i++ ) + if ( service_table[i].conn >= 0 ) close(service_table[i].conn); + unlink(sock_serve); + unlink(sock_store); + + + return 0; +} + + +int clnt_data_init(void **data) +{ + edg_wll_Context ctx; + struct clnt_data_t *cdata; + + + if ( !(cdata = calloc(1, sizeof(*cdata))) ) + return -1; + + if ( !(ctx = (edg_wll_Context) malloc(sizeof(*ctx))) ) { free(cdata); return -1; } + memset(ctx, 0, sizeof(*ctx)); + + dprintf(("[%d] opening database ...\n", getpid())); + wait_for_open(ctx, dbstring); + cdata->mysql = ctx->mysql; + edg_wll_FreeContext(ctx); + + *data = cdata; + return 0; +} + + +int handle_conn(int conn, struct timeval client_start, void *data) +{ + struct clnt_data_t *cdata = (struct clnt_data_t *)data; + edg_wll_Context ctx; + struct timeval total_to = { TOTAL_CLNT_TIMEOUT,0 }; + + + if ( !(ctx = (edg_wll_Context) calloc(1, sizeof(*ctx))) ) { + fprintf(stderr, "Couldn't create context"); + return -1; + } + cdata->ctx = ctx; + + /* Shared structures (pointers) + */ + ctx->mysql = cdata->mysql; + + /* set globals + */ + ctx->allowAnonymous = 1; + ctx->isProxy = 1; + ctx->noAuth = 1; + ctx->noIndex = 1; + ctx->semset = semset; + ctx->semaphores = semaphores; + + ctx->p_tmp_timeout.tv_sec = SLAVE_TIMEOUT; + ctx->p_tmp_timeout.tv_usec = 0; + if ( total_to.tv_sec < ctx->p_tmp_timeout.tv_sec ) { + ctx->p_tmp_timeout.tv_sec = total_to.tv_sec; + ctx->p_tmp_timeout.tv_usec = total_to.tv_usec; + } + + ctx->connProxy = (edg_wll_ConnProxy *) calloc(1, sizeof(edg_wll_ConnProxy)); + if ( !ctx->connProxy ) { + perror("calloc"); + edg_wll_FreeContext(ctx); + + return -1; + } + + if ( edg_wll_plain_accept(conn, &ctx->connProxy->conn) ) { + perror("accept"); + edg_wll_FreeContext(ctx); + + return -1; + } + + + return 0; +} + + +int accept_store(int conn, void *cdata) +{ + edg_wll_Context ctx = ((struct clnt_data_t *) cdata)->ctx; + + if ( edg_wll_StoreProtoProxy(ctx) ) { + char *errt, *errd; + + errt = errd = NULL; + switch ( edg_wll_Error(ctx, &errt, &errd) ) { + case ETIMEDOUT: + case EPIPE: + dprintf(("[%d] %s (%s)\n", getpid(), errt, errd)); + if (!debug) syslog(LOG_ERR,"%s (%s)", errt, errd); + /* fallthrough + */ + case ENOTCONN: + edg_wll_FreeContext(ctx); + ctx = NULL; + free(errt); free(errd); + dprintf(("[%d] Connection closed\n", getpid())); + return 1; + break; + + case ENOENT: + case EINVAL: + case EPERM: + case EEXIST: + case EDG_WLL_ERROR_NOINDEX: + case E2BIG: + dprintf(("[%d] %s (%s)\n", getpid(), errt, errd)); + if ( !debug ) syslog(LOG_ERR, "%s (%s)", errt, errd); + break; + + default: + dprintf(("[%d] %s (%s)\n", getpid(), errt, errd)); + if ( !debug ) syslog(LOG_CRIT, "%s (%s)", errt, errd); + return -1; + } + free(errt); free(errd); + } + + return 0; +} + +int accept_serve(int conn, void *cdata) +{ + edg_wll_Context ctx = ((struct clnt_data_t *) cdata)->ctx; + + /* + * serve the request + */ + if ( edg_wll_ServerHTTP(ctx) ) { + char *errt, *errd; + + + errt = errd = NULL; + switch ( edg_wll_Error(ctx, &errt, &errd) ) { + case ETIMEDOUT: + case EPIPE: + dprintf(("[%d] %s (%s)\n", getpid(), errt, errd)); + if (!debug) syslog(LOG_ERR,"%s (%s)", errt, errd); + /* fallthrough + */ + case ENOTCONN: + edg_wll_FreeContext(ctx); + ctx = NULL; + free(errt); free(errd); + dprintf(("[%d] Connection closed\n", getpid())); + /* + * "recoverable" error - return (>0) + */ + return 1; + break; + + case ENOENT: + case EINVAL: + case EPERM: + case EEXIST: + case EDG_WLL_ERROR_NOINDEX: + case E2BIG: + dprintf(("[%d] %s (%s)\n", getpid(), errt, errd)); + if ( !debug ) syslog(LOG_ERR,"%s (%s)", errt, errd); + /* + * no action for non-fatal errors + */ + break; + + default: + dprintf(("[%d] %s (%s)\n", getpid(), errt, errd)); + if (!debug) syslog(LOG_CRIT,"%s (%s)",errt,errd); + /* + * unknown error - do rather return (<0) (slave will be killed) + */ + return -1; + } + free(errt); free(errd); + } + + return 0; +} + + +int clnt_disconnect(int conn, void *cdata) +{ + edg_wll_Context ctx = ((struct clnt_data_t *) cdata)->ctx; + + edg_wll_FreeContext(ctx); + + return 0; +} + +int clnt_reject(int conn) +{ + return 0; +} + +static void wait_for_open(edg_wll_Context ctx, const char *dbstring) +{ + char *dbfail_string1, *dbfail_string2; + + dbfail_string1 = dbfail_string2 = NULL; + + while (edg_wll_Open(ctx, (char *) dbstring)) { + char *errt,*errd; + + if (dbfail_string1) free(dbfail_string1); + edg_wll_Error(ctx,&errt,&errd); + asprintf(&dbfail_string1,"%s (%s)\n",errt,errd); + if (dbfail_string1 != NULL) { + if (dbfail_string2 == NULL || strcmp(dbfail_string1,dbfail_string2)) { + if (dbfail_string2) free(dbfail_string2); + dbfail_string2 = dbfail_string1; + dbfail_string1 = NULL; + dprintf(("[%d]: %s\nStill trying ...\n",getpid(),dbfail_string2)); + if (!debug) syslog(LOG_ERR,dbfail_string2); + } + } + sleep(5); + } + + if (dbfail_string1) free(dbfail_string1); + if (dbfail_string2 != NULL) { + free(dbfail_string2); + dprintf(("[%d]: DB connection established\n",getpid())); + if (!debug) syslog(LOG_INFO,"DB connection established\n"); + } +}