initial import
authorZdeněk Šustr <sustr4@cesnet.cz>
Wed, 21 Jan 2009 14:43:52 +0000 (14:43 +0000)
committerZdeněk Šustr <sustr4@cesnet.cz>
Wed, 21 Jan 2009 14:43:52 +0000 (14:43 +0000)
19 files changed:
org.glite.lbjp-common.jp-interface/Makefile [new file with mode: 0644]
org.glite.lbjp-common.jp-interface/build.xml [new file with mode: 0755]
org.glite.lbjp-common.jp-interface/configure [new file with mode: 0755]
org.glite.lbjp-common.jp-interface/interface/attr.h [new file with mode: 0644]
org.glite.lbjp-common.jp-interface/interface/backend.h [new file with mode: 0644]
org.glite.lbjp-common.jp-interface/interface/builtin_plugins.h [new file with mode: 0644]
org.glite.lbjp-common.jp-interface/interface/context.h [new file with mode: 0644]
org.glite.lbjp-common.jp-interface/interface/file_plugin.h [new file with mode: 0644]
org.glite.lbjp-common.jp-interface/interface/indexdb.h [new file with mode: 0644]
org.glite.lbjp-common.jp-interface/interface/known_attr.h [new file with mode: 0644]
org.glite.lbjp-common.jp-interface/interface/type_plugin.h [new file with mode: 0644]
org.glite.lbjp-common.jp-interface/interface/types.h [new file with mode: 0644]
org.glite.lbjp-common.jp-interface/project/ChangeLog [new file with mode: 0644]
org.glite.lbjp-common.jp-interface/project/version.properties [new file with mode: 0644]
org.glite.lbjp-common.jp-interface/src/attr.c [new file with mode: 0644]
org.glite.lbjp-common.jp-interface/src/context.c [new file with mode: 0644]
org.glite.lbjp-common.jp-interface/src/indexdb.c [new file with mode: 0644]
org.glite.lbjp-common.jp-interface/src/utils.c [new file with mode: 0644]
org.glite.lbjp-common.jp-interface/test/type_test.cpp [new file with mode: 0644]

diff --git a/org.glite.lbjp-common.jp-interface/Makefile b/org.glite.lbjp-common.jp-interface/Makefile
new file mode 100644 (file)
index 0000000..aada424
--- /dev/null
@@ -0,0 +1,90 @@
+# defaults
+top_srcdir=..
+builddir=build
+top_builddir=${top_srcdir}/${builddir}
+stagedir=.
+globalprefix=glite
+jpprefix=jp
+package=glite-lbjp-common-jp-interface
+version=0.0.0
+PREFIX=/opt/glite
+
+globus_prefix=/opt/globus
+nothrflavour=gcc32
+thrflavour=gcc32pthr
+expat_prefix=/opt/expat
+gsoap_prefix=/software/gsoap-2.6
+
+CC=gcc
+
+-include Makefile.inc
+
+
+VPATH=${top_srcdir}/src:${top_srcdir}/test:${top_srcdir}/project:${jpproject}
+
+DEBUG:=-g -O0 -W -Wno-sign-compare
+CFLAGS:=${DEBUG} -D_GNU_SOURCE -I. -I${top_srcdir}/interface -I${stagedir}/include
+
+offset=0
+version_info:=-version-info ${shell \
+       perl -e '$$,=":"; @F=split "\\.","${version}"; print $$F[0]+$$F[1]+${offset},$$F[2],$$F[1]' }
+
+
+LINK:=libtool --mode=link ${CC} ${LDFLAGS} -rpath ${stagedir}/lib ${version_info}
+LINKXX:=libtool --mode=link ${CXX} ${LDFLAGS} 
+INSTALL:=libtool --mode=install install
+COMPILE:=libtool --mode=compile ${CC} ${CFLAGS}
+
+HDRS:=types.h context.h attr.h known_attr.h backend.h builtin_plugins.h file_plugin.h indexdb.h type_plugin.h
+
+SRCS:=context.c attr.c utils.c indexdb.c
+OBJS:=${SRCS:.c=.lo}
+THROBJS:=${OBJS:.o=.thr.lo}
+LIBS:=-L${stagedir}/lib -lglite_jobid -lglite_lbu_db
+THRLIBS:=${LIBS}
+
+commonlib:= libglite_jp_common_${nothrflavour}.la
+commonlib_thr:= libglite_jp_common_${thrflavour}.la
+
+TEST_LIBS:=-L${cppunit}/lib -lcppunit -ldl
+TEST_INC:=-I${cppunit}/include
+
+
+default all: compile
+
+compile: ${commonlib} ${commonlib_thr}
+
+${commonlib}: ${OBJS}
+       ${LINK} -o $@ ${OBJS} ${LIBS}
+
+${commonlib_thr}: ${THROBJS}
+       ${LINK} -o $@ ${THROBJS} ${THRLIBS}
+
+check: type_test
+       ./type_test type_test.xml
+
+type_test: %: %.cpp compile
+       ${CXX} -c ${CFLAGS} ${TEST_INC} $<
+       ${LINKXX} -o $@ $@.o ${commonlib} ${TEST_LIBS} 
+
+doc:
+
+stage: compile
+       $(MAKE) install PREFIX=${stagedir}
+
+install:
+       -mkdir -p ${PREFIX}/include/${globalprefix}/${jpprefix}
+       cd ${top_srcdir}/interface && install -m 644 ${HDRS} ${PREFIX}/include/${globalprefix}/${jpprefix}
+       -mkdir -p ${PREFIX}/lib
+       ${INSTALL} -m 755 ${commonlib} ${commonlib_thr} ${PREFIX}/lib
+
+clean:
+       rm -rvf *.o *.lo .libs lib*
+       rm -rvf log.xml project/ rpmbuild/ RPMS/ tgz/
+       rm -f glite jp
+
+%.thr.lo: %.c
+       ${COMPILE} -o $@ -c $<
+
+%.lo: %.c
+       ${COMPILE} -o $@ -c $< 
diff --git a/org.glite.lbjp-common.jp-interface/build.xml b/org.glite.lbjp-common.jp-interface/build.xml
new file mode 100755 (executable)
index 0000000..32dd0b9
--- /dev/null
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+       Copyright (c) Members of the EGEE Collaboration. 2004 
+       See http://eu-egee.org/partners/ for details on the copyright holders
+       For license conditions see the license file or http://eu-egee.org/license.html
+
+       Build file for the GLite JP Common module
+       
+       Authors: Ales Krenek <ljocha@ics.muni.cz>
+       Version info: $Id$
+       Release: $Name$
+
+       Revision history:
+       $Log$
+       Revision 1.3  2005/05/26 15:13:25  zurek
+       inserted module.build.file
+
+       Revision 1.2  2004/11/22 13:36:42  dimeglio
+       First version of this file
+       
+       Revision 1.1.1.1  2004/10/15 09:49:02  akrenek
+-->
+
+<project name="common" default="dist">
+       
+       <!-- =========================================
+                Builds the GLite JP Primary Module
+            ========================================= -->
+       
+       <!-- =========================================
+            Import properties (order is important)
+            ========================================= -->
+
+       <!-- import baseline & user properties -->
+       <import file="../org.glite/project/baseline.properties.xml" />
+
+       <!-- import component build properties,
+                       component properties &
+                       component common properties -->
+       <import file="./project/properties.xml"/>
+       
+       <!-- import subsystem build properties,
+                       subsystem properties &
+                       subsystem common properties -->
+       <import file="${subsystem.properties.file}"/>
+
+       <!-- import global build properties &
+                       global properties -->
+       <import file="${global.properties.file}" />
+               
+       <!-- =========================================
+                Load dependency property files (order is important)
+            ========================================= -->
+       <property file="${user.dependencies.file}"/>
+       <property file="${component.dependencies.file}" />
+       <property file="${subsystem.dependencies.file}" />
+       <property file="${global.dependencies.file}"/>
+       
+       <!-- =========================================
+                 Load configure options (order is important)
+             ========================================= -->
+        <import file="${global.configure.options.file}"/>
+        <import file="${component.configure.options.file}"/>
+       
+       <!-- =========================================
+                Import task definitions (order is important)
+            ========================================= -->
+       <import file="${subsystem.taskdefs.file}" />
+       <import file="${global.taskdefs.file}" />
+                       
+       <!-- =========================================
+                Load common targets
+            ========================================= -->
+       <import file="${global.targets-simple_make.file}" />
+
+       <!-- =========================================
+                Load version file 
+            ========================================= -->
+       <property file="${module.version.file}"/>
+       <property file="${module.build.file}"/>
+               
+       <!-- ==============================================
+                Local private targets
+            ============================================== -->
+       
+       <target name="localinit"
+               description="Module specific initialization tasks">
+
+               <antcall target="lbmakefiles" />
+       </target>
+               
+       <target name="localcompile"
+               description="Module specific compile tasks">
+       </target>
+       
+       <target name="localclean"
+               description="Module specific cleaning tasks">
+       </target>
+       
+</project>             
diff --git a/org.glite.lbjp-common.jp-interface/configure b/org.glite.lbjp-common.jp-interface/configure
new file mode 100755 (executable)
index 0000000..90b22ef
--- /dev/null
@@ -0,0 +1,586 @@
+#!/usr/bin/perl
+
+# WARNING: Don't edit this file unless it is the master copy in org.glite.lb
+#
+# For the purpose of standalone builds of lb/jobid/lbjp-common components
+# it is copied on tagging 
+
+# $Header$
+
+use Getopt::Long;
+
+my $pwd = `pwd`; chomp $pwd;
+my $prefix = $pwd.'/stage';
+my $stagedir;
+my $staged;
+my $module;
+my $thrflavour = 'gcc64dbgpthr';
+my $nothrflavour = 'gcc64dbg';
+my $mode = 'build';
+my $help = 0;
+my $listmodules;
+my $version;
+my $output;
+
+my @nodes = qw/client server logger utils client-java doc ws-test/;
+my %enable_nodes;
+my %disable_nodes;
+
+my %extern_prefix = (
+       cares => '/opt/c-ares',
+       classads => '/opt/classads',
+       cppunit => '/usr',
+       expat => '/usr',
+       globus => '/opt/globus',
+       gsoap => '/usr',
+       mysql => '/usr',
+       voms => '/opt/glite',
+       gridsite => '/opt/glite',
+       lcas => '/opt/glite',
+);
+
+my %jar = (
+       'commons-codec' => '/usr/share/java/commons-codec-1.3.jar',
+);
+
+
+my %glite_prefix;
+my %need_externs;
+my %need_externs_type;
+my %need_jars;
+my %extrafull;
+my %extranodmod;
+my %deps;
+my %deps_type;
+my %topbuild;
+
+my %lbmodules = (
+       'lb' => [ qw/client client-java common doc logger server state-machine types utils ws-interface ws-test/], 
+       'security' => [qw/gss gsoap-plugin/],
+       'lbjp-common' => [qw/db maildir server-bones trio/],
+       'jobid' => [qw/api-c api-cpp api-java/],
+       );
+
+
+my @opts = (
+       'prefix=s' => \$prefix,
+       'staged=s' => \$staged,
+       'module=s' => \$module,
+       'thrflavour=s' => \$thrflavour,
+       'nothrflavour=s' => \$nothrflavour,
+       'mode=s' => \$mode,
+       'listmodules=s' => \$listmodules,
+       'version=s' => \$version,
+       'output=s' => \$output,
+       'stage=s' => \$stagedir,
+       'help' => \$help,
+);
+
+for (@nodes) {
+       $enable_nodes{$_} = 0;
+       $disable_nodes{$_} = 0;
+       
+       push @opts,"disable-$_",\$disable_nodes{$_};
+       push @opts,"enable-$_",\$enable_nodes{$_};
+}
+
+push @opts,"with-$_=s",\$extern_prefix{$_} for keys %extern_prefix;
+push @opts,"with-$_=s",\$jar{$_} for keys %jar;
+
+my @keeparg = @ARGV;
+
+GetOptions @opts or die "Errors parsing command line\n";
+
+if ($help) { usage(); exit 0; }
+
+if ($listmodules) {
+       my @m = map "org.glite.$listmodules.$_",@{$lbmodules{$listmodules}};
+       print "@m\n";
+       exit 0;
+}
+
+warn "$0: --version and --output make sense only in --mode=etics\n"
+       if ($version || $output) && $mode ne 'etics';
+
+my $en;
+for (keys %enable_nodes) { $en = 1 if $enable_nodes{$_}; }
+
+my $dis;
+for (keys %disable_nodes) { $dis = 1 if $disable_nodes{$_}; }
+
+die "--enable-* and --disable-* are mutually exclusive\n"
+       if $en && $dis;
+
+die "--module cannot be used with --enable-* or --disable-*\n"
+       if $module && ($en || $dis);
+
+die "$module: unknown module\n" if $module && ! grep $module,@{$lbmodules{lb}},@{$lbmodules{security}};
+
+if ($dis) {
+       for (@nodes) {
+               $enable_nodes{$_} = 1 unless $disable_nodes{$_};
+       }
+}
+
+if (!$en && !$dis) { $enable_nodes{$_} = 1 for (@nodes) } ;
+
+for (keys %enable_nodes) { delete $enable_nodes{$_} unless $enable_nodes{$_}; }
+
+$stagedir = $prefix unless $stagedir;
+
+if ($mode eq 'build') {
+       print "Writing config.status\n";
+       open CONF,">config.status" or die "config.status: $!\n";
+       print CONF "$0 @keeparg\n";
+       close CONF;
+}
+
+
+my @modules;
+my %aux;
+
+if ($module) {
+       push @modules,$module;
+}
+else {
+       @modules = map 'lb.'.($extranodmod{$_} ? $extranodmod{$_} : $_),keys %enable_nodes;
+       
+       my $n;
+
+       do {
+               local $"="\n";
+               $n = $#modules;
+               push @modules,(map @{$deps{$_}},@modules);
+
+               undef %aux; @aux{@modules} = (1) x ($#modules+1);
+               @modules = keys %aux;
+       } while ($#modules > $n);
+}
+
+@aux{@modules} = (1) x ($#modules+1);
+delete $aux{$_} for (split /,/,$staged);
+@modules = keys %aux;
+
+mode_build() if $mode eq 'build';
+mode_checkout() if $mode eq 'checkout';
+mode_etics($module) if $mode eq 'etics';
+
+sub mode_build {
+       print "\nBuilding modules: @modules\n";
+       
+       my @ext = map @{$need_externs{$_}},@modules;
+       my @myjars = map @{$need_jars{$_}},@modules;
+       undef %aux; @aux{@ext} = 1;
+       @ext = keys %aux;
+       undef %aux; @aux{@myjars} = (1) x ($#myjars+1);
+       @myjars = keys %aux;
+       
+       print "\nRequired externals:\n";
+       print "\t$_: $extern_prefix{$_}\n" for @ext;
+       print "\t$_: $jar{$_}\n" for @myjars;
+       print "\nThis is a poor-man configure, it's up to you to have sources and externals there\n\n";
+       
+       mkinc($_) for @modules;
+       
+       print "Creating Makefile\n";
+       
+       open MAK,">Makefile" or die "Makefile: $!\n";
+       
+       print MAK "all: @modules\n\nclean:\n";
+       
+       for (@modules) {
+               my $full = full($_);
+               my $build = $topbuild{$_} ? '': '/build';
+               print MAK "\tcd $full$build && \${MAKE} clean\n"
+       }
+       
+       print MAK "\ndistclean:\n";
+       
+       for (@modules) {
+               my $full = full($_);
+               print MAK $topbuild{$_} ?
+                       "\tcd $full$build && \${MAKE} distclean\n" :
+                       "\trm -rf $full$build\n"
+       }
+       
+       print MAK "\n";
+       
+       for (@modules) {
+               my %ldeps; undef %ldeps;  
+               @ldeps{@{$deps{$_}}} = 1;
+               for my $x (split /,/,$staged) { delete $ldeps{$x}; }
+               my @dnames = keys %ldeps;
+       
+               my $full = full($_);
+               my $build = $topbuild{$_} ? '': '/build';
+       
+               print MAK "$_: @dnames\n\tcd $full$build && \${MAKE} && \${MAKE} install\n\n";
+       }
+       
+       close MAK;
+}
+       
+sub mode_checkout() {
+       for (@modules) {
+               $_ = full($_);
+               print "\n*** Checking out $_\n";
+               system("cvs checkout $_") == 0 or die "cvs checkout $_: $?\n";
+       }
+}
+
+BEGIN{
+%need_externs_aux = (
+       'lb.client' => [ qw/cppunit:B classads/ ],
+       'lb.common' => [ qw/expat cppunit:B classads/ ],
+       'lb.doc' => [],
+       'lb.logger' => [ qw/cppunit:B/ ],
+       'lb.server' => [ qw/globus expat cares mysql cppunit:B gsoap:B classads voms lcas gridsite/ ],
+       'lb.state-machine' => [ qw/classads/ ],
+       'lb.utils' => [ qw/cppunit:B/ ],
+       'lb.ws-interface' => [],
+       'lb.ws-test' => [ qw/gsoap:B/ ],
+       'lb.types' => [ qw// ],
+       'lbjp-common.db' => [ qw/mysql/ ],
+       'lbjp-common.maildir' => [ qw// ],
+       'lbjp-common.server-bones' => [ qw// ],
+       'lbjp-common.trio' => [ qw/cppunit:B/ ],
+       'security.gss' =>  [ qw/globus cares cppunit:B/ ],
+       'security.gsoap-plugin' =>  [ qw/cppunit:B globus cares gsoap:B/ ],
+       'jobid.api-c' =>  [ qw/cppunit:B/ ],
+       'jobid.api-cpp' =>  [ qw/cppunit:B/ ],
+       'jobid.api-java' =>  [ qw// ],
+);
+
+for my $ext (keys %need_externs_aux) {
+       for (@{$need_externs_aux{$ext}}) {
+               /([^:]*)(?::(.*))?/;
+               push @{$need_externs{$ext}},$1;
+               my $type = $2 ? $2 : 'BR';
+               $need_externs_type{$ext}->{$1} = $type;
+       }
+}
+
+%need_jars = (
+       'jobid.api-java' => [ qw/commons-codec/ ],
+);
+
+for my $jar (keys %need_jars) {
+       for (@{$need_jars{$jar}}) {
+               $need_externs_type{$jar}->{$_} = 'BR';  # XXX
+       }
+}
+
+%deps_aux = (
+       'lb.client' => [ qw/
+               lb.types:B lb.common
+               lbjp-common.trio
+               jobid.api-cpp jobid.api-c
+               security.gss
+       / ],
+       'lb.client-java' => [ qw/
+               lb.types:B
+               jobid.api-java
+       / ],
+       'lb.common' => [ qw/
+               jobid.api-cpp jobid.api-c
+               lb.types:B lbjp-common.trio security.gss
+       / ],
+       'lb.doc' => [ qw/lb.types:B/ ],
+       'lb.logger' => [ qw/
+               lbjp-common.trio
+               jobid.api-c
+               lb.common
+               security.gss
+       / ],
+       'lb.server' => [ qw/
+               lb.ws-interface lb.types:B lb.common lb.state-machine
+               lbjp-common.db lbjp-common.server-bones lbjp-common.trio lbjp-common.maildir
+               jobid.api-c
+               security.gsoap-plugin security.gss
+       / ],
+       'lb.state-machine' => [ qw/lb.common jp.common security.gss/ ],
+       'lb.utils' => [ qw/
+               jp.common
+               jobid.api-c
+               lbjp-common.trio lbjp-common.maildir
+               lb.client lb.state-machine
+       / ],
+       'lb.ws-test' => [ qw/security.gsoap-plugin lb.ws-interface/ ],
+       'lb.ws-interface' => [ qw/lb.types:B/ ],
+       'lb.types' => [ qw// ],
+       'lbjp-common.db' => [ qw/lbjp-common.trio/ ],
+       'lbjp-common.maildir' => [ qw// ],
+       'lbjp-common.server-bones' => [ qw// ],
+       'lbjp-common.trio' => [ qw// ],
+       'security.gss' =>  [ qw// ],
+       'security.gsoap-plugin' =>  [ qw/security.gss/ ],
+       'jobid.api-c' =>  [ qw// ],
+       'jobid.api-cpp' =>  [ qw/jobid.api-c/ ],
+       'jobid.api-java' =>  [ qw// ],
+
+       'jp.common' => [ qw/lbjp-common.db/ ],
+);
+
+for my $ext (keys %deps_aux) {
+       for (@{$deps_aux{$ext}}) {
+               /([^:]*)(?::(.*))?/;
+               push @{$deps{$ext}},$1;
+               my $type = $2 ? $2 : 'BR';
+               $deps_type{$ext}->{$1} = $type;
+       }
+}
+
+
+%extrafull = ( gridsite=>'org.gridsite.core');
+
+# %extranodmod = ( java => 'client-java' );
+
+my @t = qw/lb.client-java jobid.api-java lb.types/;
+@topbuild{@t} = (1) x ($#t+1);
+}
+
+sub full
+{
+       my $short = shift;
+       return $extrafull{$short} ? $extrafull{$short} : 'org.glite.'.$short;
+}
+
+sub mkinc
+{
+       my %aux;
+       undef %aux;
+       my @m=qw/
+lb.client lb.doc lb.state-machine lb.ws-interface lb.logger lb.types lb.common lb.server lb.utils lb.ws-test lb.client-java
+security.gss security.gsoap-plugin
+jobid.api-c jobid.api-cpp jobid.api-java
+lbjp-common.db lbjp-common.maildir lbjp-common.server-bones lbjp-common.trio
+jp.common/;
+       @aux{@m} = (1) x ($#m+1);
+
+       my $short = shift;
+       my $full = full $short;
+
+       unless ($aux{$short}) {
+               print "Makefile.inc not needed in $full\n";
+               return;
+       }
+
+       my $build = '';
+       
+       unless ($topbuild{$_}) {
+               $build = '/build';
+               unless (-d "$full/build") {
+                       mkdir "$full/build" or die "mkdir $full/build: $!\n";
+               }
+               unlink "$full/build/Makefile";
+               symlink "../Makefile","$full/build/Makefile" or die "symlink ../Makefile $full/build/Makefile: $!\n";
+       }
+
+       open MKINC,">$full$build/Makefile.inc"
+               or die "$full$build/Makefile.inc: $!\n";
+
+       print "Creating $full$build/Makefile.inc\n";
+
+       print MKINC qq{
+PREFIX = $prefix
+stagedir = $stagedir
+thrflavour = $thrflavour
+nothrflavour = $nothrflavour
+};
+
+       for (@{$need_externs{$short}}) {
+               print MKINC "${_}_prefix = $extern_prefix{$_}\n"
+       }
+
+       for (@{$need_jars{$short}}) {
+               print MKINC "${_}_jar = $jar{$_}\n"
+       }
+
+       my $need_gsoap = 0;
+       for (@{$need_externs{$short}})  { $need_gsoap = 1 if $_ eq 'gsoap'; }
+
+       print MKINC "gsoap_default_version=".gsoap_version()."\n"  if $need_gsoap;
+
+       close MKINC;
+}
+
+my %etics_externs;
+my %etics_projects;
+BEGIN{
+       %etics_externs = (
+               globus=>'vdt_globus_essentials',
+               cares=>'c-ares',
+               voms=>'org.glite.security.voms-api-c',
+               gridsite=>'org.gridsite.shared',
+               lcas=>'org.glite.security.lcas',
+       );
+       %etics_projects = (
+               vdt=>[qw/globus/],
+               'org.glite'=>[qw/voms gridsite lcas/],
+       );
+};
+
+sub mode_etics {
+       $fmod = shift;
+
+       die "$0: --module required with --etics\n" unless $fmod;
+       
+       my ($subsys,$module) = split /\./,$fmod;
+
+       my ($major,$minor,$rev,$age);
+
+       if ($version) {
+               $version =~ /([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)-(.+)/;
+               ($major,$minor,$rev,$age) = ($1,$2,$3,$4);
+       }
+       else { 
+               open V,"org.glite.$subsys.$module/project/version.properties"
+                       or die "org.glite.$subsys.$module/project/version.properties: $!\n";
+       
+               while ($_ = <V>) {
+                       chomp;
+                       ($major,$minor,$rev) = ($1,$2,$3) if /module\.version\s*=\s*([[:digit:]]+)\.([[:digit:]]+)\.([[:digit:]]+)/;
+                       $age = $1 if /module\.age\s*=\s*([[:digit:]]+)/;
+               }
+               close V;
+       }
+
+       my @copts = ();
+       my %ge;
+       @ge{@{$etics_projects{'org.glite'}}} = (1) x ($#{$etics_projects{'org.glite'}}+1);
+
+       for (@{$need_externs{"$subsys.$module"}}) {
+               my $eext = $etics_externs{$_} ? $etics_externs{$_} : $_;
+               push @copts,$ge{$_} ? "--with-$_=\${stageDir}" : "--with-$_=\${$eext.location}";
+       }
+
+       for (@{$need_jars{"$subsys.$module"}}) {
+               my $eext = $etics_externs{$_} ? $etics_externs{$_} : $_;
+
+               push @copts,"--with-$_ \${$eext.location}/$_*.jar";
+       }
+
+
+       my $conf = "glite-$subsys-${module}_R_${major}_${minor}_${rev}_${age}";
+       my $file = $output ? $output : "$conf.ini";
+       open C,">$file" or die "$file: $!\n";
+
+       my $buildroot = $topbuild{"$subsys.$module"} ? '' : "build.root = build\n";
+
+       my $confdir = $topbuild{"$subsys.$module"} ? '..' : '../..';
+
+       print STDERR "Writing $file\n";
+       print C qq{
+[Configuration-$conf]
+profile = None
+moduleName = org.glite.$subsys.$module
+displayName = $conf
+description = org.glite.$subsys.$module
+projectName = org.glite
+age = $age
+deploymentType = None
+tag = $conf
+version = $major.$minor.$rev
+path = \${projectName}/\${moduleName}/\${version}/\${platformName}/\${packageName}-\${version}-\${age}.tar.gz
+
+[Platform-default:VcsCommand]
+displayName = None
+description = None
+tag = cvs -d \${vcsroot} tag -R \${tag} \${moduleName}
+branch = None
+commit = None
+checkout = cvs -d \${vcsroot} co -r \${tag} \${moduleName}
+
+[Platform-default:BuildCommand]
+postpublish = None
+packaging = None
+displayName = None
+description = None
+doc = None
+prepublish = None
+publish = None
+compile = make
+init = None
+install = make install
+clean = make clean
+test = make check
+configure = cd $confdir && \${moduleName}/configure --prefix=\${prefix} --stage=\${stageDir} --module $subsys.$module @copts
+checkstyle = None
+
+[Platform-default:Property]
+$buildroot
+
+[Platform-default:DynamicDependency]
+
+};
+       for (@{$need_externs{"$subsys.$module"}},@{$need_jars{"$subsys.$module"}}) {
+               my $eext = $etics_externs{$_} ? $etics_externs{$_} : $_;
+
+               my $proj = 'externals';
+               for my $p (keys %etics_projects) {
+                       for $m (@{$etics_projects{$p}}) {
+                               $proj = $p if $m eq $_;
+                       }
+               }
+
+               my $type = $need_externs_type{"$subsys.$module"}->{$_};
+               print C "$proj|$eext = $type\n";
+       }
+
+       for (@{$deps{"$subsys.$module"}}) {
+               my $type = $deps_type{"$subsys.$module"}->{$_};
+               print C "org.glite|org.glite.$_ = $type\n";
+       }
+
+       close C;
+}
+
+sub gsoap_version {
+       local $_;
+       my $gsoap_version;
+       open S,"$extern_prefix{gsoap}/bin/soapcpp2 -v 2>&1 |" or die "$extern_prefix{gsoap}/bin/soapcpp2: $!\n";
+
+       while ($_ = <S>) {
+               chomp;
+
+               $gsoap_version = $1 if /The gSOAP Stub and Skeleton Compiler for C and C\+\+ ([.[:digit:][:alpha:]]+)$/;
+       }
+       close S;
+       return $gsoap_version;
+}
+
+
+sub usage {
+       my @ext = keys %extern_prefix;
+       my @myjars, keys %jar;
+
+       print STDERR qq{
+usage: $0 options
+
+General options (defaults in []):
+  --prefix=PREFIX              destination directory [./stage]
+  --staged=module,module,...   what is already in PREFIX (specify without org.glite.)
+  --thrflavour=flavour
+  --nothrflavour=flavour       threaded and non-treaded flavours [gcc64dbgpthr,gcc64dbg]
+  --listmodules=subsys         list modules of a subsystem
+  
+Mode of operation:
+  --mode={checkout|build|etics}        what to do [build]
+  
+What to build:
+  --module=module              build this module only (mostly in-Etics operation)
+  --enable-NODE                        build this "node" (set of modules) only. Available nodes are
+                                       @{$lbmodules{lb}},@{$lbmodules{security}}
+  --disable-NODE               don't build this node
+
+Dependencies:
+  --with-EXTERNAL=PATH         where to look for an external. Required externals
+                               (not all for all modules) are:
+                                       @ext
+  --with-JAR=JAR               where to look for jars. Required jars are:
+                                       @myjars
+                               Summary of what will be used is always printed
+
+};
+
+}
diff --git a/org.glite.lbjp-common.jp-interface/interface/attr.h b/org.glite.lbjp-common.jp-interface/interface/attr.h
new file mode 100644 (file)
index 0000000..b8c559f
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef GLITE_JP_ATTR_H
+#define GLITE_JP_ATTR_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void glite_jp_attrval_free(glite_jp_attrval_t *,int);
+void glite_jp_attrval_copy(glite_jp_attrval_t *,const glite_jp_attrval_t *);
+
+/* Search through registered type plugins and call appropriate plugin method.
+ * See type_plugin.h for detailed description.
+ */
+
+int glite_jp_attrval_cmp(glite_jp_context_t ctx,const glite_jp_attrval_t *a,const glite_jp_attrval_t *b,int *result);
+
+char *glite_jp_attrval_to_db_full(glite_jp_context_t ctx,const glite_jp_attrval_t *attr);
+char *glite_jp_attrval_to_db_index(glite_jp_context_t ctx,const glite_jp_attrval_t *attr,int len);
+
+int glite_jp_attrval_from_db(glite_jp_context_t ctx,const char *str,glite_jp_attrval_t *attr);
+const char *glite_jp_attrval_db_type_full(glite_jp_context_t ctx,const char *attr);
+const char *glite_jp_attrval_db_type_index(glite_jp_context_t ctx,const char *attr,int len);
+
+time_t glite_jp_attr2time(const char *);
+char * glite_jp_time2attr(time_t);
+
+#ifdef __cplusplus
+};
+#endif
+
+
+#endif /* GLITE_JP_ATTR_H */
diff --git a/org.glite.lbjp-common.jp-interface/interface/backend.h b/org.glite.lbjp-common.jp-interface/interface/backend.h
new file mode 100644 (file)
index 0000000..3c8c1da
--- /dev/null
@@ -0,0 +1,114 @@
+#ifndef GLITE_JP_BACKEND_H
+#define GLITE_JP_BACKEND_H
+
+/* do we need it?
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int glite_jppsbe_get_names(
+       glite_jp_context_t ctx,
+       const char *job,
+       const char * /* class */,
+       char    ***names_out
+);
+
+int glite_jppsbe_destination_info(
+       glite_jp_context_t ctx,
+       const char *destination,
+       char **job_out,
+       char **class_out,
+       char **name_out
+);
+
+int glite_jppsbe_get_job_url(
+       glite_jp_context_t ctx,
+       const char *job,
+       const char * /* class */,
+       const char *name,       /* optional within class */
+       char **url_out
+);
+
+int glite_jppsbe_open_file(
+       glite_jp_context_t ctx,
+       const char *job,
+       const char * /* class */,
+       const char *name,       /* optional within class */
+       int mode,
+       void **handle_out
+);
+
+int glite_jppsbe_close_file(
+       glite_jp_context_t ctx,
+       void *handle
+);
+
+int glite_jppsbe_file_attrs(
+       glite_jp_context_t ctx,
+       void *handle,
+       struct stat *buf
+);
+
+int glite_jppsbe_pread(
+       glite_jp_context_t ctx,
+       void *handle,
+       void *buf,
+       size_t nbytes,
+       off_t offset,
+       ssize_t *nbytes_ret
+);
+
+int glite_jppsbe_pwrite(
+       glite_jp_context_t ctx,
+       void *handle,
+       void *buf,
+       size_t nbytes,
+       off_t offset
+);
+
+int glite_jppsbe_append(
+       glite_jp_context_t ctx,
+       void *handle,
+       void *buf,
+       size_t nbytes
+);
+
+int glite_jppsbe_is_metadata(
+       glite_jp_context_t ctx,
+       const char *attr
+);
+
+int glite_jppsbe_get_job_metadata(
+       glite_jp_context_t ctx,
+       const char *job,
+       glite_jp_attrval_t attrs_inout[]
+);
+
+int glite_jppsbe_query(
+       glite_jp_context_t ctx,
+       const glite_jp_query_rec_t query[],
+       char *attrs[],
+       void *arg,
+       int (*callback)(
+               glite_jp_context_t ctx,
+               const char *job,
+               const glite_jp_attrval_t metadata[],
+               void *arg
+       )
+);
+
+char* glite_jpps_get_namespace(
+       const char* attr
+);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* GLITE_JP_BACKEND_H */
+
diff --git a/org.glite.lbjp-common.jp-interface/interface/builtin_plugins.h b/org.glite.lbjp-common.jp-interface/interface/builtin_plugins.h
new file mode 100644 (file)
index 0000000..70d900b
--- /dev/null
@@ -0,0 +1,8 @@
+
+#define GLITE_JP_FILETYPE_TAGS   "urn:org.glite.jp.primary:tags"
+#define GLITE_JP_FILETYPE_LB     "urn:org.glite.jp.primary:lb"
+#define GLITE_JP_FILETYPE_CLASSAD "urn:org.glite.jp.primary:classad"
+#define GLITE_JP_FILETYPE_ISB    "urn:org.glite.jp.primary:isb"
+#define GLITE_JP_FILETYPE_OSB    "urn:org.glite.jp.primary:osb"
+
+#define GLITE_JP_FPLUG_TAGS_APPEND     0
diff --git a/org.glite.lbjp-common.jp-interface/interface/context.h b/org.glite.lbjp-common.jp-interface/interface/context.h
new file mode 100644 (file)
index 0000000..4203f56
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef GLITE_JP_CONTEXT_H
+#define GLITE_JP_CONTEXT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int glite_jp_init_context(glite_jp_context_t *);
+void glite_jp_free_context(glite_jp_context_t);
+void glite_jp_free_query_rec(glite_jp_query_rec_t *);
+
+char *glite_jp_peer_name(glite_jp_context_t);
+char *glite_jp_error_chain(glite_jp_context_t);
+
+int glite_jp_stack_error(glite_jp_context_t, const glite_jp_error_t *);
+int glite_jp_clear_error(glite_jp_context_t); 
+
+int glite_jp_add_deferred(glite_jp_context_t,int (*)(glite_jp_context_t,void *),void *);
+int glite_jp_run_deferred(glite_jp_context_t);
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /* GLITE_JP_CONTEXT_H */
diff --git a/org.glite.lbjp-common.jp-interface/interface/file_plugin.h b/org.glite.lbjp-common.jp-interface/interface/file_plugin.h
new file mode 100644 (file)
index 0000000..eea7d05
--- /dev/null
@@ -0,0 +1,86 @@
+#ifndef GLITE_JP_FILEPLUGIN_H
+#define GLITE_JP_FILEPLUGIN_H
+
+/** Methods of the file plugin. */
+
+typedef struct _glite_jpps_fplug_op_t {
+
+/** Open a file.
+\param[in] fpctx       Context of the plugin, returned by its init.
+\param[in] bhandle     Handle of the file via JPPS backend.
+\param[in] uri         URI (type) of the opened file.
+\param[out] handle     Handle to the opened file structure, to be passed to other plugin functions.
+*/
+       int     (*open)(void *fpctx,void *bhandle,const char *uri,void **handle);
+/** Open from a string.
+\param[in] fpctx       Context of the plugin, returned by its init.
+\param[in] str         The string to use.
+\param[in] uri         URI (type) of the string
+\param[in] ns          namespace to handle 
+\param[out] handle      Handle to the opened file structure, to be passed to other plugin functions.
+*/
+
+       int     (*open_str)(void *fpctx,const char *str,const char *uri,const char *ns,void **handle);
+
+/** Close the file. Free data associated to a handle */
+       int     (*close)(void *fpctx,void *handle);
+
+/** "Preprocess" the file -- this function is called once after the file is commited */
+       int     (*filecom)(void *fpctx,void *handle);
+
+/** Retrieve value(s) of an attribute.
+\param[in] fpctx       Plugin context.
+\param[in] handle      Handle of the opened file.
+\param[in] ns          Namespace of queried attribute.
+\param[in] attr                Queried attribute.
+\param[out] attrval    GLITE_JP_ATTR_UNDEF-terminated list of value(s) of the attribute.
+                       If there are more and there is an interpretation of their order
+                       they must be sorted, eg. current value of tag is the last one.
+\retval        0 success
+\retval ENOSYS this attribute is not defined by this type of file
+\retval ENOENT no value is present 
+*/
+       int     (*attr)(void *fpctx,void *handle, const char *attr,glite_jp_attrval_t **attrval);
+
+/** File type specific operation. 
+\param[in] fpctx       Plugin context.
+\param[in] handle      Handle of the opened file.
+\param[in] oper                Code of the operation, specific for a concrete plugin.
+*/
+       int     (*generic)(void *fpctx,void *handle,int oper,...);
+       
+} glite_jpps_fplug_op_t;
+
+/** Data describing a plugin. */
+typedef struct _glite_jpps_fplug_data_t {
+       void    *fpctx;         /**< Context passed to plugin operations. */
+       char    **uris;         /**< NULL-terminated list of file types (URIs)
+                                       handled by the plugin. */
+       char    **classes;      /**< The same as uris but filesystem-friendly
+                                       (can be used to construct file names).*/
+       char    **namespaces;   /**< Which attribute namespaces this plugin handles. */
+
+       glite_jpps_fplug_op_t ops;      /**< Plugin operations. */
+} glite_jpps_fplug_data_t;
+       
+/** Initialisation function of the plugin. 
+  Called after dlopen(), must be named "init".
+\param[in] ctx         JPPS context
+\param[out] data       filled-in plugin data
+*/
+  
+typedef int (*glite_jpps_fplug_init_t)(
+       glite_jp_context_t ctx,
+       glite_jpps_fplug_data_t *plugin_data
+);
+
+
+
+
+/* XXX: not really public interface follows */
+
+int glite_jpps_fplug_load(glite_jp_context_t ctx,int argc,char **argv);
+int glite_jpps_fplug_lookup(glite_jp_context_t ctx,const char *uri, glite_jpps_fplug_data_t ***plugin_data);
+int glite_jpps_fplug_lookup_byclass(glite_jp_context_t, const char *class,glite_jpps_fplug_data_t ***plugin_data);
+
+#endif /* GLITE_JP_FILEPLUGIN_H */
diff --git a/org.glite.lbjp-common.jp-interface/interface/indexdb.h b/org.glite.lbjp-common.jp-interface/interface/indexdb.h
new file mode 100644 (file)
index 0000000..7130d73
--- /dev/null
@@ -0,0 +1,59 @@
+#ifndef GLITE_JP_INDEXDB_H
+#define GLITE_JP_INDEXDB_H
+
+/**
+ * \file indexdb.h
+ * \brief Helper functions for accessing Job Provenance Index Server database.
+ */
+
+#include "glite/lbu/db.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifdef GLITE_JP_INDEX_COMPILE
+
+/**
+ * For generating table names.
+ */
+#define GLITE_JP_INDEXDB_TABLE_ATTR_PREFIX "attr_"
+
+#endif
+
+
+/**
+ * Returns internal id from attribute name.
+ *
+ * The attribute id is used in some places in the database schema. Because of the future possible changes in the schema, you should rather use other functions to get SQL commands (table names and where conditions).
+ *
+ * \param[in] name     attribute name
+ * \return             attribute id string
+ */
+char *glite_jp_indexdb_attr2id(const char *name);
+
+/**
+ * Get parts of the SQL SELECT command to the given attribute:
+ *
+ *   SELECT column, full_value_column FROM table WHERE where;
+ *
+ * This is quick version requiring additional information about indexing of the attribute.
+ */
+int glite_jp_indexdb_attr2select_from_index(const char *name, int indexed, char **column, char **full_value_column, char **table, char **where);
+
+/**
+ * Get parts of the SQL SELECT command to the given attribute:
+ *
+ *   SELECT column, full_value_column FROM table WHERE where;
+ *
+ * This is the most portable way - it will peep to the DB for information about indexing.
+ */
+int glite_jp_indexdb_attr2select_from_db(const char *name, glite_lbu_DBContext dbctx, char **column, char **full_value_column, char **table, char **where);
+
+#ifdef __cplusplus
+};
+#endif
+
+
+#endif /* GLITE_JP_INDEXDB_H */
diff --git a/org.glite.lbjp-common.jp-interface/interface/known_attr.h b/org.glite.lbjp-common.jp-interface/interface/known_attr.h
new file mode 100644 (file)
index 0000000..8876831
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef GLITE_JP_KNOWN_ATTR_H
+#define GLITE_JP_KNOWN_ATTR_H
+
+/** Namespace of JP system attributes */
+#define GLITE_JP_SYSTEM_NS     "http://egee.cesnet.cz/en/Schema/JP/System"
+#define GLITE_JP_WORKFLOW_NS   "http://egee.cesnet.cz/en/Schema/JP/Workflow"
+
+/** Job owner, as specified with RegisterJob JPPS operation */
+#define GLITE_JP_ATTR_OWNER    GLITE_JP_SYSTEM_NS ":owner" 
+
+/** JobId */
+#define GLITE_JP_ATTR_JOBID    GLITE_JP_SYSTEM_NS ":jobId" 
+
+/** Timestamp of job registration in JP.
+ * Should be almost the same time as registration with LB. */
+#define GLITE_JP_ATTR_REGTIME  GLITE_JP_SYSTEM_NS ":regtime" 
+
+/** Workflow node relationships. */
+#define GLITE_JP_ATTR_WF_ANCESTOR GLITE_JP_WORKFLOW_NS ":ancestor"
+#define GLITE_JP_ATTR_WF_SUCCESSOR GLITE_JP_WORKFLOW_NS ":successor"
+
+/** Attributes derived from LB system data
+ * \see jp_job_attrs.h */
+
+/** Namespace for LB user tags, schemaless, all values are strings */
+#define GLITE_JP_LBTAG_NS      "http://egee.cesnet.cz/en/WSDL/jp-lbtag"
+#define GLITE_JP_JDL_NS        "http://jdl"
+
+/** Namespace for Sandboxes */
+#define GLITE_JP_ISB_NS       "http://egee.cesnet.cz/en/Schema/JP/ISB"
+#define GLITE_JP_OSB_NS       "http://egee.cesnet.cz/en/Schema/JP/OSB"
+
+/** Namespace for file names listed from tar  */
+#define GLITE_JP_ATTR_ISB_FILENAME     GLITE_JP_ISB_NS ":filename"
+#define GLITE_JP_ATTR_OSB_FILENAME     GLITE_JP_OSB_NS ":filename"
+
+/** Namespace for filenames to be unpacked from sanbox tar */
+#define GLITE_JP_ISB_CONTENT_NS     GLITE_JP_ISB_NS ":content"
+#define GLITE_JP_OSB_CONTENT_NS     GLITE_JP_OSB_NS ":content"
+
+#endif /* GLITE_JP_KNOWN_ATTR_H */
diff --git a/org.glite.lbjp-common.jp-interface/interface/type_plugin.h b/org.glite.lbjp-common.jp-interface/interface/type_plugin.h
new file mode 100644 (file)
index 0000000..d3fffd2
--- /dev/null
@@ -0,0 +1,74 @@
+#ifndef GLITE_JP_TYPEPLUGIN_H
+#define GLITE_JP_TYPEPLUGIN_H
+
+typedef struct _glite_jp_tplug_data_t {
+       
+       char    *namespace;
+       void    *pctx;
+
+/** Compare attribute values. 
+  * \param[in] a value to compare
+  * \param[in] b value to compare
+  * \param[out] result like strcmp()
+  * \param[out] err set if the values cannot be compared
+  * \retval 0 OK
+  * \retval other error
+  */
+       int (*cmp)(
+               void    *ctx,
+               const glite_jp_attrval_t *a,
+               const glite_jp_attrval_t *b,
+               int     *result);
+
+/** Convert to database string representation.
+ * It is guaranteed the returned value can be converted back with
+ * from_db().
+ * The resulting value may not be suitable for indexing with db engine.
+ *
+ * \param[in] attr the attribute value to convert
+ * \retval NULL can't be converted
+ * \retval other the string representation.
+ * */
+       char * (*to_db_full)(void *ctx,const glite_jp_attrval_t *attr);
+
+/** Convert to a database string representation suitable for indexing.
+ * The function is non-decreasing (wrt. cmp() above and strcmp()), however it
+ * is not guaranteed to be one-to-one.
+ *
+ * \param[in] attr the value to convert
+ * \param[in] len maximum length of the converted value.
+ * \retval NULL can't be converted
+ * \retval other the string representation
+ */
+       char * (*to_db_index)(void *ctx,const glite_jp_attrval_t *attr,int len);
+
+/** Convert from the database format.
+ * \param[in] str the string value
+ * \param[inout] attr name contains the name of the attribute to be converted
+ *             the rest of attr is filled in.
+ */
+       int (*from_db)(void *ctx,const char *str,glite_jp_attrval_t *attr);
+
+/** Query for database types suitable to store values returned by
+ * to_db_full() and to_db_index(). 
+ * Useful for db column dynamic creation etc.
+ * Return pointer to internal static data, non-reentrant.
+ */
+       const char * (*db_type_full)(void *ctx,const char *attr);
+       const char * (*db_type_index)(void *ctx,const char *attr,int len);
+
+} glite_jp_tplug_data_t;
+
+/** Plugin init function.
+    Must be called init, supposed to be called as many times as required
+    for different param's (e.g. xsd files).
+    Registers the plugin in ctx.
+ */
+
+typedef int (*glite_jp_tplug_init_t)(
+       glite_jp_context_t      ctx,
+       const char              *param,
+       glite_jp_tplug_data_t   *plugin_data
+);
+
+#endif /* GLITE_JP_TYPEPLUGIN_H */
diff --git a/org.glite.lbjp-common.jp-interface/interface/types.h b/org.glite.lbjp-common.jp-interface/interface/types.h
new file mode 100644 (file)
index 0000000..8aaaaae
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef GLITE_JP_TYPES_H
+#define GLITE_JP_TYPES_H
+
+#include <sys/time.h>
+
+typedef struct _glite_jp_error_t {
+       int     code;
+       const char      *desc;
+       const char      *source;
+       struct _glite_jp_error_t *reason;
+} glite_jp_error_t;
+
+typedef struct _glite_jp_context {
+       glite_jp_error_t *error;
+       int     (**deferred_func)(struct _glite_jp_context *,void *);
+       void    **deferred_arg;
+       void    *feeds;
+       struct soap     *other_soap;
+       char    *peer;
+       void    **plugins;
+       void    **type_plugins;
+       void    *dbhandle;
+       char    **trusted_peers;
+       char    *myURL;
+       int     noauth;
+} *glite_jp_context_t;
+
+typedef enum {
+       GLITE_JP_ATTR_ORIG_ANY,         /**< for queries: don't care about origin */
+       GLITE_JP_ATTR_ORIG_SYSTEM,      /**< JP internal, e.g. job owner */
+       GLITE_JP_ATTR_ORIG_USER,        /**< inserted by user explicitely */
+       GLITE_JP_ATTR_ORIG_FILE         /**< coming from uploaded file */
+} glite_jp_attr_orig_t;
+
+typedef struct {
+       char    *name;          /**< including namespace */
+       char    *value;
+       int     binary;         /**< value is binary */
+       size_t  size;           /**< in case of binary value */
+       glite_jp_attr_orig_t    origin; 
+       char    *origin_detail; /**< where it came from, i.e. file URI:name */
+       time_t  timestamp;
+} glite_jp_attrval_t;
+
+
+typedef enum {
+       GLITE_JP_QUERYOP_UNDEF,
+       GLITE_JP_QUERYOP_EQUAL,
+       GLITE_JP_QUERYOP_UNEQUAL,
+       GLITE_JP_QUERYOP_LESS,
+       GLITE_JP_QUERYOP_GREATER,
+       GLITE_JP_QUERYOP_WITHIN,
+       GLITE_JP_QUERYOP_EXISTS,
+       GLITE_JP_QUERYOP__LAST,
+} glite_jp_queryop_t;
+
+typedef struct {
+       char    *attr;
+       glite_jp_queryop_t op;
+       char    *value, *value2;
+       int     binary;
+       size_t  size,size2;
+       glite_jp_attr_orig_t origin;
+} glite_jp_query_rec_t;
+
+#endif /* GLITE_JP_TYPES_H */
diff --git a/org.glite.lbjp-common.jp-interface/project/ChangeLog b/org.glite.lbjp-common.jp-interface/project/ChangeLog
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/org.glite.lbjp-common.jp-interface/project/version.properties b/org.glite.lbjp-common.jp-interface/project/version.properties
new file mode 100644 (file)
index 0000000..31863ee
--- /dev/null
@@ -0,0 +1,3 @@
+#$Header$
+module.version=1.0.0
+module.age=0
diff --git a/org.glite.lbjp-common.jp-interface/src/attr.c b/org.glite.lbjp-common.jp-interface/src/attr.c
new file mode 100644 (file)
index 0000000..1b7285c
--- /dev/null
@@ -0,0 +1,291 @@
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include "glite/jobid/strmd5.h"
+#include "types.h"
+#include "attr.h"
+#include "type_plugin.h"
+#include "context.h"
+
+void glite_jp_attrval_free(glite_jp_attrval_t *a,int f)
+{
+       free(a->name);
+       free(a->value);
+       free(a->origin_detail);
+       memset(a,0,sizeof *a);
+       if (f) free(a);
+}
+
+void glite_jp_attrval_copy(glite_jp_attrval_t *dst,const glite_jp_attrval_t *src)
+{
+       dst->name = strdup(src->name);
+       dst->origin = src->origin;
+       dst->size = src->size;
+       dst->timestamp = src->timestamp;
+       dst->origin_detail = src->origin_detail ? 
+               strdup(src->origin_detail) : NULL;
+       if ((dst->binary = src->binary)) {
+               dst->value = malloc(src->size);
+               memcpy(dst->value,src->value,src->size);
+       }
+       else dst->value = strdup(src->value);
+}
+
+
+#define min(x,y) ((x) > (y) ? (y) : (x))
+
+static int fb_cmp(void *ctx,const glite_jp_attrval_t *a,const glite_jp_attrval_t *b,int *result)
+{
+       if (a->binary != b->binary) return EINVAL;
+       if (a->binary) {
+               *result = memcmp(a->value,b->value,min(a->size,b->size));
+               if (!*result && a->size != b->size) 
+                       *result = a->size > b->size ? 1 : -1;
+       }
+       else *result = strcmp(a->value,b->value);
+       return 0;
+}
+
+/* XXX: depends on specific definition of glite_jp_attr_orig_t */
+static char orig_char[] = "ASUF";
+
+/* XXX: don't allocate memory, don't grow more than twice */
+static int escape_colon(const char *in, char *out)
+{
+       int     i,o;
+
+       for (i=o=0; in[i]; i++) switch (in[i]) {
+               case ':': out[o++] = '\\'; out[o++] = ':'; break;
+               case '\\': out[o++] = '\\'; out[o++] = '\\'; break;
+               default: out[o++] = in[i]; break;
+       }
+       out[o] = 0;
+       return o;
+}
+
+/* XXX: read until unescaped colon is found 
+ *      allocates output */
+static char * unescape_colon(const char *in,int *rd)
+{
+       int     i,o;
+       char    *out;
+
+       for (i=o=0; in[i] && in[i] != ':'; i++,o++)
+               if (in[i] == '\\') i++;
+
+       out = malloc(o+1);
+
+       for (i=o=0; in[i] && in[i] != ':'; i++)
+               if (in[i] == '\\') out[o++] = in[++i]; 
+               else out[o++] = in[i];
+
+       out[o] = 0;
+       *rd = i;
+       return out;
+}
+
+static char * fb_to_db_full(void *ctx,const glite_jp_attrval_t *attr)
+{
+       
+       int     vsize = attr->binary ? attr->size * 4/3 + 6 : strlen(attr->value)+1,
+               len;
+
+       /* 4x: + \0 + ASUF + BS + %12d */
+       char    *db = malloc(19 + (attr->origin_detail ? 2*strlen(attr->origin_detail) : 0) + vsize);
+
+       if (attr->origin < 0 || attr->origin > GLITE_JP_ATTR_ORIG_FILE) {
+               free(db); return NULL; 
+       }
+       len = sprintf(db,"%c:%d:%c:",attr->binary ? 'B' : 'S',
+               attr->timestamp,orig_char[attr->origin]);
+
+       if (attr->origin_detail) len += escape_colon(attr->origin_detail,db+len);
+       db[len++] = ':';
+
+       if (attr->binary) {
+               vsize = base64_encode(attr->value,attr->size,db+len,vsize-1);
+               if (vsize < 0) { free(db); return NULL; }
+               db[len+vsize] = 0;
+       }
+       else strcpy(db+len,attr->value);
+
+       return db;
+}
+
+static char * fb_to_db_index(void *ctx,const glite_jp_attrval_t *attr,int len)
+{
+       char    *s;
+
+/* XXX: binary values not really handled. Though the formal semantics is not broken */
+       if (attr->binary) return strdup("XXX"); 
+
+       s = strdup(attr->value);
+       if (len < strlen(s)) s[len] = 0;
+       return s;
+}
+
+static int fb_from_db(void *ctx,const char *str,glite_jp_attrval_t *attr)
+{
+       int     p = 2;
+       char    *colon,*cp;
+
+       if (str[0] != 'B' && str[0] != 'S') return EINVAL;
+       attr->binary = str[0] == 'B';
+       cp = attr->value = strdup(str);
+       
+       colon = strchr(cp+p,':');
+       if (!colon) return EINVAL;
+
+       *colon++ = 0;
+       attr->timestamp = (time_t) atol(cp+p);
+       p = colon-cp;
+
+       for (attr->origin = GLITE_JP_ATTR_ORIG_ANY; orig_char[attr->origin] && orig_char[attr->origin] != cp[p]; attr->origin++);
+       if (!orig_char[attr->origin]) return EINVAL;
+
+       p += 2;
+       if (cp[p] == ':') attr->origin_detail = NULL;
+       else {
+               int     r;
+               attr->origin_detail = unescape_colon(cp+p,&r);
+               p += r;
+       }
+       if (cp[p++] != ':') return EINVAL;
+
+       if (attr->binary) {
+               attr->size = base64_decode(str+p,attr->value,strlen(str));
+               if (attr->size < 0) return EINVAL;
+       }
+       else strcpy(attr->value,str+p);
+
+       return 0;
+}
+
+static const char * fb_type_full(void *ctx,const char *attr)
+{
+       return "mediumblob";
+}
+
+static const char * fb_type_index(void *ctx,const char *attr,int len)
+{
+       static char tbuf[100];
+       sprintf(tbuf,"varchar(%d)",len);
+       return tbuf;
+}
+
+
+
+static glite_jp_tplug_data_t fallback_plugin = {
+       "",
+       NULL,
+       fb_cmp,
+       fb_to_db_full,
+       fb_to_db_index,
+       fb_from_db,
+       fb_type_full,
+       fb_type_index,
+};
+
+static glite_jp_tplug_data_t *get_plugin(glite_jp_context_t ctx,const char *aname)
+{
+       void    **cp = ctx->type_plugins;
+       char    *colon,*ns;
+
+       if (!cp) return &fallback_plugin;
+       glite_jp_clear_error(ctx);
+       ns = strdup(aname);
+       colon = strrchr(ns,':');
+       if (colon) *colon = 0; else *ns = 0;
+
+       while (*cp) {
+               glite_jp_tplug_data_t   *p = *cp;
+               if (!strcmp(ns,p->namespace)) {
+                       free(ns);
+                       return p;
+               }
+               cp++;
+       }
+       free(ns);
+       return &fallback_plugin;        /* XXX: is it always desirable? */
+}
+
+int glite_jp_attrval_cmp(glite_jp_context_t ctx,const glite_jp_attrval_t *a,const glite_jp_attrval_t *b,int *result)
+{
+       glite_jp_tplug_data_t   *ap = get_plugin(ctx,a->name);
+       glite_jp_error_t        err;
+
+       memset(&err,0,sizeof err);
+       err.source = __FUNCTION__;
+       glite_jp_clear_error(ctx);
+
+       if (strcmp(a->name,b->name)) {
+               err.code = EINVAL;
+               err.desc = "Can't compare different attributes";
+               return glite_jp_stack_error(ctx,&err);
+       }
+
+       return ap->cmp ? ap->cmp(ap->pctx,a,b,result) : fb_cmp(ap->pctx,a,b,result);
+}
+
+char *glite_jp_attrval_to_db_full(glite_jp_context_t ctx,const glite_jp_attrval_t *attr)
+{
+       glite_jp_tplug_data_t   *ap = get_plugin(ctx,attr->name);
+
+       glite_jp_clear_error(ctx);
+       return ap->to_db_full ? ap->to_db_full(ap->pctx,attr) : fb_to_db_full(ap->pctx,attr);
+}
+
+char *glite_jp_attrval_to_db_index(glite_jp_context_t ctx,const glite_jp_attrval_t *attr,int len)
+{
+       glite_jp_tplug_data_t   *ap = get_plugin(ctx,attr->name);
+
+       glite_jp_clear_error(ctx);
+       return ap->to_db_index ? ap->to_db_index(ap->pctx,attr,len) : fb_to_db_index(ap->pctx,attr,len);
+}
+
+
+int glite_jp_attrval_from_db(glite_jp_context_t ctx,const char *str,glite_jp_attrval_t *attr)
+{
+       glite_jp_tplug_data_t   *ap = get_plugin(ctx,attr->name);
+
+       glite_jp_clear_error(ctx);
+       return ap->from_db ? ap->from_db(ap->pctx,str,attr) : fb_from_db(ap->pctx,str,attr);
+}
+
+const char *glite_jp_attrval_db_type_full(glite_jp_context_t ctx,const char *attr)
+{
+       glite_jp_tplug_data_t   *ap = get_plugin(ctx,attr);
+
+       glite_jp_clear_error(ctx);
+       return ap->db_type_full ? ap->db_type_full(ap->pctx,attr) : fb_type_full(ap->pctx,attr);
+}
+
+const char *glite_jp_attrval_db_type_index(glite_jp_context_t ctx,const char *attr,int len)
+{
+       glite_jp_tplug_data_t   *ap = get_plugin(ctx,attr);
+
+       glite_jp_clear_error(ctx);
+       return ap->db_type_index ?  ap->db_type_index(ap->pctx,attr,len) : fb_type_index(ap->pctx,attr,len);
+}
+
+/* XXX: UNIX time, should be ISO blahblah */
+time_t glite_jp_attr2time(const char *a)
+{
+       long    t;
+
+       sscanf(a,"%ld",&t);
+       return t;
+}
+
+/* XXX: UNIX time, should be ISO blahblah */
+char * glite_jp_time2attr(time_t t)
+{
+       char    *r;
+
+       asprintf(&r,"%ld",(long) t);
+       return r;
+}
+
diff --git a/org.glite.lbjp-common.jp-interface/src/context.c b/org.glite.lbjp-common.jp-interface/src/context.c
new file mode 100644 (file)
index 0000000..62bd3c7
--- /dev/null
@@ -0,0 +1,145 @@
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "types.h"
+#include "context.h"
+
+int glite_jp_init_context(glite_jp_context_t *ctx)
+{
+       return (*ctx = calloc(1,sizeof **ctx)) != NULL;
+}
+
+void glite_jp_free_context(glite_jp_context_t ctx)
+{
+       glite_jp_clear_error(ctx);
+       free(ctx);
+}
+
+char *glite_jp_peer_name(glite_jp_context_t ctx)
+{
+       return strdup(ctx->peer ? ctx->peer : "unknown");
+}
+
+char *glite_jp_error_chain(glite_jp_context_t ctx)
+{
+       char    *ret = NULL,indent[300] = "";
+       int     len = 0,add;
+       char    buf[2000];
+
+       glite_jp_error_t *ep = ctx->error;
+
+       do {
+               add = snprintf(buf,sizeof buf,"%s%s: %s (%s)\n",
+                               indent,
+                               ep->source,
+                               strerror(ep->code),
+                               ep->desc ? ep->desc : "");
+               ret = realloc(ret,len + add + 1);
+               strncpy(ret + len,buf,add); ret[len += add] = 0;
+               strcat(indent,"  ");
+       } while ((ep = ep->reason));
+
+       return ret;
+}
+
+int glite_jp_stack_error(glite_jp_context_t ctx, const glite_jp_error_t *err)
+{
+       glite_jp_error_t        *reason = ctx->error;
+
+       ctx->error = calloc(1,sizeof *ctx->error);
+       ctx->error->code = err->code;
+       ctx->error->desc = err->desc ? strdup(err->desc) : NULL;
+       ctx->error->source = err->source ? strdup(err->source) : NULL;
+       ctx->error->reason = reason;
+
+       return err->code;
+}
+
+int glite_jp_clear_error(glite_jp_context_t ctx)
+{
+       glite_jp_error_t        *e = ctx->error, *r;
+
+       while (e) {
+               r = e->reason;
+               free((char *) e->source);
+               free((char *) e->desc);
+               free(e);
+               e = r;
+       }
+       ctx->error = NULL;
+       return 0;
+}
+
+
+void glite_jp_free_query_rec(glite_jp_query_rec_t *q)
+{
+       free(q->attr); 
+       free(q->value);
+       free(q->value2);
+       memset(q,0,sizeof *q);
+}
+
+int glite_jp_queryrec_copy(glite_jp_query_rec_t *dst, const glite_jp_query_rec_t *src)
+{
+       memcpy(dst,src,sizeof *src);
+       if (src->attr) dst->attr = strdup(src->attr);
+       if (src->value) dst->value = strdup(src->value);
+       if (src->value2) dst->value2 = strdup(src->value2);
+       return 0;
+}
+
+int glite_jp_run_deferred(glite_jp_context_t ctx)
+{
+       int     i,cnt,ret;
+
+       if (!ctx->deferred_func) return 0;
+
+       glite_jp_clear_error(ctx);
+       for (cnt=0;ctx->deferred_func[cnt];cnt++);
+       for (i=0; i<cnt; i++) {
+               if ((ret = (*ctx->deferred_func)(ctx,*ctx->deferred_arg))) {
+                       glite_jp_error_t        err;
+                       char    desc[100];
+
+                       sprintf(desc,"calling func #%d, %p",i,*ctx->deferred_func);
+                       err.code = ret;
+                       err.desc = desc;
+                       err.source = "glite_jp_run_deferred()";
+
+                       glite_jp_stack_error(ctx,&err);
+                       return ret;
+               }
+               else {
+                       memmove(ctx->deferred_func,ctx->deferred_func+1,
+                                       (cnt-i) * sizeof *ctx->deferred_func);
+                       memmove(ctx->deferred_arg,ctx->deferred_arg+1,
+                                       (cnt-i) * sizeof *ctx->deferred_arg);
+               }
+       }
+       free(ctx->deferred_func); ctx->deferred_func = NULL;
+       free(ctx->deferred_arg); ctx->deferred_arg = NULL;
+       return 0;
+}
+
+int glite_jp_add_deferred(
+               glite_jp_context_t ctx,
+               int (*func)(glite_jp_context_t, void *),
+               void *arg
+)
+{
+       int     (**v)(glite_jp_context_t, void *) = ctx->deferred_func;
+       int     i;
+
+       for (i=0; v && v[i]; i++);
+
+       ctx->deferred_func = realloc(ctx->deferred_func, (i+2) * sizeof *ctx->deferred_func);
+       ctx->deferred_func[i] = func;
+       ctx->deferred_func[i+1] = NULL;
+
+       ctx->deferred_arg = realloc(ctx->deferred_arg,(i+2) * sizeof *ctx->deferred_arg);
+       ctx->deferred_arg[i] = arg;
+       ctx->deferred_arg[i+1] = NULL;
+
+       return 0;
+}
diff --git a/org.glite.lbjp-common.jp-interface/src/indexdb.c b/org.glite.lbjp-common.jp-interface/src/indexdb.c
new file mode 100644 (file)
index 0000000..cc1fc77
--- /dev/null
@@ -0,0 +1,71 @@
+#ident "$Header:"
+
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#include <glite/jobid/strmd5.h>
+#include <glite/lbu/db.h>
+#include <glite/lbu/trio.h>
+
+#define GLITE_JP_INDEX_COMPILE 1
+
+#include "indexdb.h"
+
+char *glite_jp_indexdb_attr2id(const char *name) {
+       size_t i, len;
+       char *lname, *id;
+
+       len = strlen(name);
+       lname = malloc(len + 1);
+       for (i = 0; i < len + 1; i++) lname[i] = tolower(name[i]);
+       id = str2md5(lname);
+       free(lname);
+
+       return id;
+}
+
+
+int glite_jp_indexdb_attr2select_from_index(const char *name, int indexed __attribute__((unused)), char **column, char **full_value_column, char **table, char **where) {
+       char *id;
+
+       if (column) *column = strdup("value");
+       if (full_value_column) *full_value_column = strdup("full_value");
+       if (table) {
+               id = glite_jp_indexdb_attr2id(name);
+               asprintf(table, GLITE_JP_INDEXDB_TABLE_ATTR_PREFIX "%s", id);
+               free(id);
+       }
+       if (where) *where = strdup("");
+
+       return 0;
+}
+
+
+int glite_jp_indexdb_attr2select_from_db(const char *name, glite_lbu_DBContext dbctx, char **column, char **full_value_column, char **table, char **where) {
+       char *sql, *id;
+       glite_lbu_Statement stmt;
+       int ret;
+
+       if (table) {
+               trio_asprintf(&sql, "SELECT attrid FROM attrs WHERE name='%|Ss'", name);
+               ret = glite_lbu_ExecSQL(dbctx, sql, &stmt);
+               free(sql);
+               switch (ret) {
+               case -1: return glite_lbu_DBError(dbctx, NULL, NULL);
+               case 1: break;
+               default: return EINVAL;
+               }
+               if (glite_lbu_FetchRow(stmt, 1, NULL, &id) < 0) return glite_lbu_DBError(dbctx, NULL, NULL);
+               asprintf(table, GLITE_JP_INDEXDB_TABLE_ATTR_PREFIX "%s", id);
+               free(id);
+               glite_lbu_FreeStmt(&stmt);
+       }
+       if (column) *column = strdup("value");
+       if (full_value_column) *full_value_column = strdup("full_value");
+       if (where) *where = strdup("");
+
+       return 0;
+}
diff --git a/org.glite.lbjp-common.jp-interface/src/utils.c b/org.glite.lbjp-common.jp-interface/src/utils.c
new file mode 100644 (file)
index 0000000..0be3e8e
--- /dev/null
@@ -0,0 +1,63 @@
+#include <getopt.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <assert.h>
+#include <limits.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "glite/jobid/strmd5.h"
+#include "types.h"
+#include "context.h"
+#include "known_attr.h"
+#include "attr.h"
+
+/*
+#include "feed.h"
+#include "tags.h"
+*/
+
+#include "backend.h"
+
+
+typedef struct _rl_buffer_t {
+        char                    *buf;
+        size_t                  pos, size;
+        off_t                   offset;
+} rl_buffer_t;
+
+/*
+ * realloc the line to double size if needed
+ *
+ * \return 0 if failed, did nothing
+ * \return 1 if success
+ */
+int check_realloc_line(char **line, size_t *maxlen, size_t len) {
+        void *tmp;
+
+        if (len > *maxlen) {
+                *maxlen <<= 1;
+                tmp = realloc(*line, *maxlen);
+                if (!tmp) return 0;
+                *line = tmp;
+        }
+
+        return 1;
+}
+
+
+char* glite_jpps_get_namespace(const char* attr){
+        char* namespace = strdup(attr);
+        char* colon = strrchr(namespace, ':');
+        if (colon)
+                namespace[strrchr(namespace, ':') - namespace] = 0;
+        else
+                namespace[0] = 0;
+        return namespace;
+}
+
diff --git a/org.glite.lbjp-common.jp-interface/test/type_test.cpp b/org.glite.lbjp-common.jp-interface/test/type_test.cpp
new file mode 100644 (file)
index 0000000..33211bb
--- /dev/null
@@ -0,0 +1,200 @@
+#include <assert.h>
+#include <fstream>
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+#include <cppunit/CompilerOutputter.h>
+#include <cppunit/XmlOutputter.h>
+#include <cppunit/TestRunner.h>
+#include <cppunit/TestResult.h>
+#include <cppunit/TestResultCollector.h>
+
+#include "types.h"
+#include "attr.h"
+#include "context.h"
+#include "backend.h"
+
+
+class TypePluginTest: public  CppUnit::TestFixture
+{
+       CPPUNIT_TEST_SUITE(TypePluginTest);
+       CPPUNIT_TEST(simple);
+       CPPUNIT_TEST(binary);
+       CPPUNIT_TEST(origin);
+       CPPUNIT_TEST(origin2);
+       CPPUNIT_TEST(index);
+       CPPUNIT_TEST_SUITE_END();
+public:
+       void simple();
+       void binary();
+       void origin();
+       void origin2();
+       void index();
+};
+
+void TypePluginTest::simple()
+{      
+       glite_jp_context_t      ctx;
+
+       glite_jp_attrval_t      attr = {
+               "myattr",
+               "short string",
+               0,0,
+               GLITE_JP_ATTR_ORIG_USER,
+               NULL,
+               0
+       },attr2;
+
+       char    *db;
+
+       glite_jp_init_context(&ctx);
+       attr.timestamp = time(NULL);
+
+       db = glite_jp_attrval_to_db_full(ctx,&attr);
+
+       CPPUNIT_ASSERT_MESSAGE(std::string("glite_jp_attrval_to_db_full()"),db);
+       std::cerr << db << std::endl; 
+
+       glite_jp_attrval_from_db(ctx,db,&attr2);
+       CPPUNIT_ASSERT_MESSAGE(std::string("value"),!strcmp(attr.value,attr2.value));
+       CPPUNIT_ASSERT_MESSAGE(std::string("origin"),attr.origin == attr2.origin);
+       CPPUNIT_ASSERT_MESSAGE(std::string("timestamp"),attr.timestamp == attr2.timestamp);
+}
+
+void TypePluginTest::binary()
+{
+       glite_jp_context_t      ctx;
+
+       glite_jp_attrval_t      attr = {
+               "myattr",
+               NULL,
+               1,1000,
+               GLITE_JP_ATTR_ORIG_USER,
+               NULL,
+               0
+       },attr2;
+
+       char    *db;
+
+       glite_jp_init_context(&ctx);
+       attr.timestamp = time(NULL);
+       attr.value = (char *) malloc(attr.size);
+
+       db = glite_jp_attrval_to_db_full(ctx,&attr);
+
+       CPPUNIT_ASSERT_MESSAGE(std::string("glite_jp_attrval_to_db_full()"),db);
+       std::cerr << db << std::endl; 
+
+       glite_jp_attrval_from_db(ctx,db,&attr2);
+       CPPUNIT_ASSERT_MESSAGE(std::string("size"),attr.size == attr2.size);
+       CPPUNIT_ASSERT_MESSAGE(std::string("value"),!memcmp(attr.value,attr2.value,attr.size));
+}
+
+void TypePluginTest::origin()
+{
+       glite_jp_context_t      ctx;
+
+       glite_jp_attrval_t      attr = {
+               "myattr",
+               NULL,
+               0,0,
+               GLITE_JP_ATTR_ORIG_USER,
+               NULL,
+               0
+       },attr2;
+
+       char    *db;
+
+       glite_jp_init_context(&ctx);
+       attr.timestamp = time(NULL);
+       attr.value = "origin test";
+       attr.origin_detail = "simple origin";
+
+       db = glite_jp_attrval_to_db_full(ctx,&attr);
+
+       CPPUNIT_ASSERT_MESSAGE(std::string("glite_jp_attrval_to_db_full()"),db);
+       std::cerr << db << std::endl; 
+
+       glite_jp_attrval_from_db(ctx,db,&attr2);
+       CPPUNIT_ASSERT_MESSAGE(std::string("origin detail"),!strcmp(attr.origin_detail,attr2.origin_detail));
+}
+
+void TypePluginTest::origin2()
+{
+       glite_jp_context_t      ctx;
+
+       glite_jp_attrval_t      attr = {
+               "myattr",
+               NULL,
+               0,0,
+               GLITE_JP_ATTR_ORIG_USER,
+               NULL,
+               0
+       },attr2;
+
+       char    *db;
+
+       glite_jp_init_context(&ctx);
+       attr.timestamp = time(NULL);
+       attr.value = "origin:test";
+       attr.origin_detail = "ftp://some.server:1234/ugly \\file";
+
+       db = glite_jp_attrval_to_db_full(ctx,&attr);
+
+       CPPUNIT_ASSERT_MESSAGE(std::string("glite_jp_attrval_to_db_full()"),db);
+       std::cerr << db << std::endl; 
+
+       glite_jp_attrval_from_db(ctx,db,&attr2);
+       CPPUNIT_ASSERT_MESSAGE(std::string("origin detail"),!strcmp(attr.origin_detail,attr2.origin_detail));
+       CPPUNIT_ASSERT_MESSAGE(std::string("value"),!strcmp(attr.value,attr2.value));
+}
+
+void TypePluginTest::index()
+{
+       /* TODO: check monotonity */
+}
+
+CPPUNIT_TEST_SUITE_REGISTRATION(TypePluginTest);
+
+
+int main (int argc,const char *argv[])
+{
+       CppUnit::Test *suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest();
+
+       assert(argc == 2);
+       std::ofstream   xml(argv[1]);
+
+       CppUnit::TestResult controller;
+       CppUnit::TestResultCollector result;
+       controller.addListener( &result );
+
+       CppUnit::TestRunner runner;
+       runner.addTest(suite);
+       runner.run(controller);
+
+       CppUnit::XmlOutputter xout( &result, xml );
+       CppUnit::CompilerOutputter tout( &result, std::cout);
+       xout.write();
+       tout.write();
+
+       return result.wasSuccessful() ? 0 : 1 ;
+}
+
+
+
+
+/* fake to link */
+int glite_jppsbe_pread(
+        glite_jp_context_t ctx,
+        void *handle,
+        void *buf,
+        size_t nbytes,
+        off_t offset,
+        ssize_t *nbytes_ret
+)
+{
+       abort();
+}
+
+