- Plugins are appliet to attribute according to its namespace
authorJiří Filipovič <fila@ics.muni.cz>
Thu, 25 Jan 2007 11:08:13 +0000 (11:08 +0000)
committerJiří Filipovič <fila@ics.muni.cz>
Thu, 25 Jan 2007 11:08:13 +0000 (11:08 +0000)
- Tags plugin has been removed, its functionality has been moved into background
- The classad plugin has been added

12 files changed:
org.glite.jp.primary/Makefile
org.glite.jp.primary/interface/file_plugin.h
org.glite.jp.primary/src/attrs.c
org.glite.jp.primary/src/backend.h
org.glite.jp.primary/src/builtin_plugins.h
org.glite.jp.primary/src/classad_plugin.c [new file with mode: 0644]
org.glite.jp.primary/src/new_ftp_backend.c
org.glite.jp.primary/src/sandbox_plugin.c
org.glite.jp.primary/src/soap_ops.c
org.glite.jp.primary/src/tags.c
org.glite.jp.primary/src/tags.h
org.glite.jp.primary/src/tags_plugin.c [deleted file]

index d7427c1..8fd9074 100644 (file)
@@ -28,6 +28,15 @@ GLOBUS_LIBS:=-L${globus_prefix}/lib \
        -lglobus_common_${nothrflavour} \
        -lglobus_gssapi_gsi_${nothrflavour}
 
+ifneq (${classads_prefix},/usr)
+        classadslib := -L${classads_prefix}/lib -lclassad
+endif
+
+CLASSADPLUGIN_LIBS:= ${classadslib} -lstdc++ 
+
+CLASSADPLUGIN_LOBJS:= classad_plugin.lo
+
+
 GLOBUS_CFLAGS:=-I${globus_prefix}/include/${nothrflavour}
 
 DEBUG:=-g -O0  -DDEBUG
@@ -41,17 +50,13 @@ SOLINK:=libtool --mode=link ${CC} -module ${LDFLAGS} -rpath ${stagedir}/lib
 LINKXX:=libtool --mode=link ${CXX} ${LDFLAGS} 
 INSTALL:=libtool --mode=install install
 
-ifneq (${classads_prefix},/usr)
-       classadslib := -L${classads_prefix}/lib -lclassad
-endif
-
 daemon:=glite-jp-primarystoraged
 example:=jpps-test dag-deps
 ps_prefix:=jpps_
 is_prefix:=jpis_
 sample_jobs:=sample_job_aborted  sample_job_cleared  sample_job_tagged_done  sample_job_waiting
 
-plugins:=glite-jp-tags.la glite-jp-ftpdauth.la glite-jp-sandbox.la
+plugins:=glite-jp-tags.la glite-jp-ftpdauth.la glite-jp-classad.la glite-jp-sandbox.la
 
 HDRS_I=file_plugin.h
 HDRS_S=builtin_plugins.h backend.h feed.h
@@ -104,7 +109,6 @@ jpps-test: ${TEST_OBJS}
 dag-deps: ${DAG_OBJS}
        ${LINKXX} -o $@ ${DAG_OBJS} ${classadslib} ${GSOAPLIB}
 
-
 JobProvenancePS.xh: %.xh: %.wsdl JobProvenanceTypes.wsdl typemap.dat
        cp  ${stagedir}/interface/JobProvenanceTypes.wsdl .
        ${gsoap_bin_prefix}/wsdl2h  -t ${top_srcdir}/src/typemap.dat -c -o $@ $<
@@ -115,6 +119,8 @@ JobProvenanceIS.xh: %.xh: %.wsdl JobProvenanceTypes.wsdl typemap.dat
        ${gsoap_bin_prefix}/wsdl2h  -t ${top_srcdir}/src/typemap.dat -c -o $@ $<
        rm -f JobProvenanceTypes.wsdl
 
+glite-jp-classad.la: ${CLASSADPLUGIN_LOBJS}
+       ${SOLINK} -o $@ ${CLASSADPLUGIN_LOBJS} ${CLASSADPLUGIN_LIBS}
 
 ${ps_prefix}Client.c ${ps_prefix}ClientLib.c  \
 ${ps_prefix}Server.c ${ps_prefix}ServerLib.c  \
@@ -200,12 +206,12 @@ simple_server.o soap_ops.o jpps-test.o: ${ps_prefix}H.h
 glite-jp-sandbox.la: sandbox_plugin.lo
        ${SOLINK} -o $@ sandbox_plugin.lo ${LIBTARLIB}
 
-glite-jp-tags.la: tags_plugin.lo
-       ${SOLINK} -o $@ tags_plugin.lo
-
 glite-jp-ftpdauth.la: ftpd_auth.lo mysql.lo
        ${SOLINK} -o $@ ftpd_auth.lo mysql.lo ${COMMONLIB} ${TRIOLIB} ${MYSQLIB}
 
+#glite-jp-classad.lo: classad_plugin.c
+#      ${LTCOMPILE} -DPLUGIN_DEBUG -o $@ -c $<
+
 %.lo: %.c
        ${LTCOMPILE} -o $@ -c $<
 
index 98ed498..dba7303 100644 (file)
@@ -28,6 +28,7 @@ typedef struct _glite_jpps_fplug_op_t {
 /** 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
@@ -36,7 +37,7 @@ typedef struct _glite_jpps_fplug_op_t {
 \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);
+       int     (*attr)(void *fpctx,void *handle,const char *ns, const char *attr,glite_jp_attrval_t **attrval);
 
 /** File type specific operation. 
 \param[in] fpctx       Plugin context.
index 7099dd1..db859d8 100644 (file)
 #include "builtin_plugins.h"
 
 static struct {
-       char    *class,*uri;
-       glite_jpps_fplug_data_t **plugins;
-       int     nplugins;
-} *known_classes;
-
-static int tags_index;
-
+       char *namespace;
+       glite_jpps_fplug_data_t **plugins;
+        int     nplugins;
+
+} *known_namespaces;
+
+static char* 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;
+}
 
-static void scan_classes(glite_jp_context_t ctx)
+static void scan_namespaces(glite_jp_context_t ctx)
 {
-       int     i,j,k;
-       glite_jpps_fplug_data_t *pd;
+        int     i,j,k;
+        glite_jpps_fplug_data_t *pd;
 
        if (!ctx->plugins) return;
+        
        for (i=0; ctx->plugins[i]; i++) {
-               pd = ctx->plugins[i];
-
-               for (j=0; pd->classes[j]; j++) {
-                       for (k=0; known_classes && known_classes[k].class
-                                       && strcmp(pd->classes[j],known_classes[k].class);
-                               k++);
-                       if (known_classes && known_classes[k].class) {
-                               known_classes[k].plugins = realloc(known_classes[k].plugins,
-                                               (known_classes[k].nplugins + 2) * sizeof(glite_jpps_fplug_data_t *));
-                               known_classes[k].plugins[known_classes[k].nplugins++] = pd;
-                               known_classes[k].plugins[known_classes[k].nplugins] = NULL;
-                       }
-                       else {
-                               known_classes = realloc(known_classes,(k+2) * sizeof *known_classes);
-                               known_classes[k].class = pd->classes[j];
-                               known_classes[k].uri = pd->uris[j];
-                               known_classes[k].plugins = malloc(2 * sizeof(glite_jpps_fplug_data_t *));
-                               known_classes[k].plugins[0] = pd;
-                               known_classes[k].plugins[1] = NULL;
-                               known_classes[k].nplugins = 1;
-                               memset(known_classes+k+1,0,sizeof *known_classes);
-                               if (!strcmp(known_classes[k].uri,GLITE_JP_FILETYPE_TAGS)) tags_index = k;
-                       }
+                pd = ctx->plugins[i];
+               
+               if (pd->namespaces){
+                       for (j=0; pd->namespaces[j]; j++) {
+                               for (k=0; known_namespaces && known_namespaces[k].namespace
+                                                      && strcmp(pd->namespaces[j],known_namespaces[k].namespace); k++) {};
+                       
+                               if (known_namespaces && known_namespaces[k].namespace) {
+                                       printf("Adding new plugin into namespace %s\n", known_namespaces[k].namespace);
+                                       known_namespaces[k].plugins = realloc(known_namespaces[k].plugins,
+                                                       (known_namespaces[k].nplugins + 2) * sizeof(glite_jpps_fplug_data_t *));
+                                       known_namespaces[k].plugins[known_namespaces[k].nplugins++] = pd;
+                                       known_namespaces[k].plugins[known_namespaces[k].nplugins] = NULL;
+                                       known_namespaces[k].namespace = pd->namespaces[j];
+                               }
+                               else {
+                                       printf("Adding new namespace %s\n", pd->namespaces[j]);
+                                       known_namespaces = realloc(known_namespaces,(k+2) * sizeof *known_namespaces);
+                                       known_namespaces[k].plugins = malloc(2 * sizeof(glite_jpps_fplug_data_t *));
+                                       known_namespaces[k].plugins[0] = pd;
+                                       known_namespaces[k].plugins[1] = NULL;
+                                       known_namespaces[k].nplugins = 1;
+                                       known_namespaces[k].namespace = pd->namespaces[j];
+                                       memset(known_namespaces+k+1,0,sizeof *known_namespaces);
+                                       }
+                       }
                }
-       }
+        }
 }
 
 static int merge_attrvals(glite_jp_attrval_t **out,int nout,const glite_jp_attrval_t *in)
@@ -68,17 +80,37 @@ static int merge_attrvals(glite_jp_attrval_t **out,int nout,const glite_jp_attrv
        return nout+nin;
 }
 
+void process_files(glite_jp_context_t ctx, const char *job, glite_jp_attrval_t** out, int* nout, const char* attr, const glite_jpps_fplug_data_t* plugin, const char* class, const char* uri, const char *ns){
+       void *ph, *beh; 
+       char** names = NULL;
+        int nnames = glite_jppsbe_get_names(ctx, job, class, &names);
+       int n;
+        for (n = 0; n < nnames; n++)
+               if (! glite_jppsbe_open_file(ctx,job,class, names[n], O_RDONLY, &beh)) {
+                       if (!plugin->ops.open(plugin->fpctx,beh,uri,&ph)) {
+                               glite_jp_attrval_t* myattr;
+                               // XXX: ignore errors
+                               if (!plugin->ops.attr(plugin->fpctx,ph,ns,attr,&myattr)) {
+                                       int k;
+                                       for (k=0; myattr[k].name; k++) {
+                                               myattr[k].origin = GLITE_JP_ATTR_ORIG_FILE;
+                                               trio_asprintf(&myattr[k].origin_detail,"%s %s", uri, names[n] ? names[n] : "");
+                                       }
+                                       *nout = merge_attrvals(out,*nout,myattr);
+                                       free(myattr);
+                               }
+                               plugin->ops.close(plugin->fpctx, ph);
+                               }
+                       glite_jppsbe_close_file(ctx,beh);
+               }
+}
+
 glite_jpps_get_attrs(glite_jp_context_t ctx,const char *job,char **attr,int nattr,glite_jp_attrval_t **attrs_out)
 {
        glite_jp_attrval_t      *meta = NULL,*out = NULL;
         char const     **other = NULL;
        int     i,j,nmeta,nother,err = 0,nout = 0;
 
-       struct { int    class_idx;
-                char   *name;
-       } *files = NULL;
-       int     nfiles = 0;
-
        nmeta = nother = 0;
        glite_jp_clear_error(ctx);
 
@@ -102,85 +134,32 @@ glite_jpps_get_attrs(glite_jp_context_t ctx,const char *job,char **attr,int natt
 /* retrieve the metadata */
        if (meta && (err = glite_jppsbe_get_job_metadata(ctx,job,meta))) goto cleanup;
 
-       if (!known_classes) scan_classes(ctx);
-
-/* build a list of available files for this job */
-       files = malloc(sizeof *files);
-       files->class_idx = tags_index;
-       files->name = NULL;
-       nfiles = 1;
-
-       for (i=0; known_classes[i].class; i++) {
-               char    **names = NULL;
-               int     nnames = 
-                       glite_jppsbe_get_names(ctx,job,known_classes[i].class,&names);
-               if (nnames < 0) continue; /* XXX: error ignored */
-
-               if (nnames > 0) {
-                       files = realloc(files,(nfiles+nnames+1) * sizeof *files);
-                       for (j=0; j<nnames; j++) {
-                               files[nfiles].class_idx = i;
-                               files[nfiles++].name = names[j];
+       if (!known_namespaces) scan_namespaces(ctx);
+
+/* loop over the attributes */
+       int k, l, m;
+       void* beh;
+       for (i = 0; i < nother; i++){
+               if (! glite_jppsbe_read_tag(ctx, job, other[i], &out))
+                       nout++;
+               for (j = 0; known_namespaces[j].namespace; j++) {
+                       void* ph;
+                       char* attr_namespace = get_namespace(other[i]);
+                       if (strcmp(attr_namespace, known_namespaces[j].namespace) == 0){
+                               for (k = 0; known_namespaces[j].plugins[k]; k++)
+                                       for (l = 0; known_namespaces[j].plugins[k]->classes[l]; l++)
+                                               process_files(ctx, job, &out, &nout, other[i], known_namespaces[j].plugins[k]
+                                                       , known_namespaces[j].plugins[k]->classes[l]
+                                                       , known_namespaces[j].plugins[k]->uris[l]
+                                                       , known_namespaces[j].namespace);
+                               break;
                        }
-               }
-               free(names);
-       }
-
-/* loop over the files */
-       for (i=0; i<nfiles; i++) {
-               void    *beh;
-               int     ci;
-
-               /* XXX: ignore error */
-               if (!glite_jppsbe_open_file(ctx,job,
-                       known_classes[ci = files[i].class_idx].class,
-                       files[i].name,O_RDONLY,&beh))
-               {
-                       for (j=0; j<known_classes[ci].nplugins; j++) {
-                               void    *ph;
-
-                               glite_jpps_fplug_data_t *p = 
-                                       known_classes[ci].plugins[j];
-                               /* XXX: ignore error */
-                               if (!p->ops.open(p->fpctx,beh,known_classes[ci].uri,&ph)) {
-
-                                       for (j=0; j<nother; j++) {
-                                               glite_jp_attrval_t      *myattr;
-                                               /* XXX: ignore errors */
-                                               if (!p->ops.attr(p->fpctx,ph,other[j],&myattr)) {
-                                                       int     k;
-                                                       for (k=0; myattr[k].name; k++) {
-                                                               myattr[k].origin = GLITE_JP_ATTR_ORIG_FILE;
-                                                               trio_asprintf(&myattr[k].origin_detail,"%s %s",
-                                                                               known_classes[ci].uri,
-                                                                               files[i].name ? files[i].name : "");
-                                                       }
-                                                       nout = merge_attrvals(&out,nout,myattr);
-                                                       free(myattr);
-                                               }
-
-                                       }
-                                       p->ops.close(p->fpctx,ph);
-                               }
-                               else {
-                                       char    *e;
-                                       fprintf(stderr,"[%d] %s: %s\n",getpid(),known_classes[ci].class,
-                                                       e = glite_jp_error_chain(ctx));
-                                       free(e);
-                               }
-                       }
-
-                       glite_jppsbe_close_file(ctx,beh);
-               }
-               else {
-                       char    *e;
-                       fprintf(stderr,"[%d] %s: %s\n",getpid(),known_classes[ci].class,
-                                       e = glite_jp_error_chain(ctx));
-                       free(e);
+                       free(attr_namespace);
                }
        }
 
        nout = merge_attrvals(&out,nout,meta);
+
        free(meta); meta = NULL;
 
        if (nout) {
@@ -201,8 +180,6 @@ cleanup:
 
        free(other);
 
-       if (files) for (i=0; i<nfiles; i++) free(files[i].name);
-       free(files);
-       
        return err;
 }
+
index e3ec8a0..91e2ad2 100644 (file)
@@ -2,6 +2,7 @@
 #define __GLITE_JP_BACKEND
 
 #include <sys/types.h>
+#include <sys/stat.h>
 #include <unistd.h>
 
 #include "feed.h"
@@ -74,6 +75,12 @@ int glite_jppsbe_close_file(
        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,
index 3b2c201..70d900b 100644 (file)
@@ -1,7 +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_ISB  "urn:org.glite.jp.primary:isb"
-#define GLITE_JP_FILETYPE_OSB  "urn:org.glite.jp.primary:osb"
+#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.jp.primary/src/classad_plugin.c b/org.glite.jp.primary/src/classad_plugin.c
new file mode 100644 (file)
index 0000000..b8baad7
--- /dev/null
@@ -0,0 +1,202 @@
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <cclassad.h>
+#include <errno.h>
+
+#include "glite/lb/context.h"
+#include "glite/lb/jobstat.h"
+#include "glite/lb/events.h"
+#include "glite/lb/events_parse.h"
+#include "glite/lb/trio.h"
+#include "glite/jp/types.h"
+#include "glite/jp/context.h"
+#include "glite/jp/file_plugin.h"
+#include "glite/jp/builtin_plugins.h"
+#include "glite/jp/backend.h"
+#include "glite/jp/attr.h"
+#include "glite/jp/known_attr.h"
+
+//#define INITIAL_NUMBER_EVENTS 100
+//#define INITIAL_NUMBER_STATES EDG_WLL_NUMBER_OF_STATCODES
+//#define LB_PLUGIN_NAMESPACE "urn:org.glite.lb"
+
+//extern int processEvent(intJobStat *, edg_wll_Event *, int, int, char **);
+
+#include "glite/jp/builtin_plugins.h"
+
+typedef struct _classad_handle{
+       char* data;
+       struct cclassad* ad;
+       time_t timestamp;
+} classad_handle;
+
+static int classad_query(void *fpctx, void *handle, const char *ns, const char *attr, glite_jp_attrval_t **attrval);
+static int classad_open(void *fpctx, void *bhandle, const char *uri, void **handle);
+static int classad_open_str(void *fpctx, const char *str, const char *uri, const char *ns, void **handle);
+static int classad_close(void *fpctx, void *handle);
+
+int init(glite_jp_context_t ctx, glite_jpps_fplug_data_t *data) {
+       data->fpctx = ctx;
+
+       data->uris = calloc(2,sizeof *data->uris);
+       data->uris[0] = strdup(GLITE_JP_FILETYPE_CLASSAD);
+
+       data->classes = calloc(2,sizeof *data->classes);
+       data->classes[0] = strdup("classad");
+
+       data->namespaces = calloc(2, sizeof *data->namespaces);
+       data->namespaces[0] = strdup(GLITE_JP_JDL_NS);
+
+       data->ops.open  = classad_open;
+       data->ops.close = classad_close;
+       data->ops.attr  = classad_query;
+       data->ops.open_str = classad_open_str;
+
+#ifdef PLUGIN_DEBUG
+        fprintf(stderr,"classad_plugin: init OK\n");
+#endif
+       
+       return 0;
+}
+
+
+void done(glite_jp_context_t ctx, glite_jpps_fplug_data_t *data) {
+       free(data->uris[0]);
+       free(data->classes[0]);
+       free(data->uris);
+       free(data->classes);
+       memset(data, 0, sizeof(*data));
+}
+
+
+static int classad_open(void *fpctx, void *bhandle, const char *uri, void **handle) {
+       glite_jp_context_t  ctx = (glite_jp_context_t) fpctx;
+       glite_jp_error_t    err;
+       classad_handle*     h;
+       void*               fh;
+       int                 retval = 0;
+
+       glite_jp_clear_error(ctx);
+       h = calloc(1, sizeof(classad_handle));
+       h->data = NULL;
+       struct stat fattr;
+       glite_jppsbe_file_attrs(ctx, bhandle, &fattr);
+       h->timestamp = fattr.st_mtime;
+
+       // read the classad file
+       char buf[1024];
+       size_t nbytes;
+       off_t offset = 0;
+
+       do{
+               if (! (retval = glite_jppsbe_pread(ctx, bhandle, buf, sizeof buf, offset, &nbytes))){
+                       h->data = realloc(h->data, offset + nbytes);
+                       memcpy(h->data + offset, buf, nbytes);
+                       offset += nbytes;
+               }
+               else
+                       goto fail;
+       }while(nbytes);
+
+       h->ad = cclassad_create(h->data);
+
+#ifdef PLUGIN_DEBUG
+        fprintf(stderr,"classad_plugin: opened\n");
+#endif
+
+       *handle = h;    
+
+       return 0;
+
+fail:
+       err.code = EIO;
+       err.desc = NULL;
+       err.source = __FUNCTION__;
+       glite_jp_stack_error(ctx,&err);
+
+       return retval;
+}
+
+static int classad_open_str(void *fpctx,const char *str,const char *uri,const char *ns,void **handle){
+        classad_handle*     h;
+       
+       h = calloc(1, sizeof(classad_handle));
+        h->data = strdup(str);
+       h->ad = cclassad_create(h->data);
+       h->timestamp = 0;
+
+#ifdef PLUGIN_DEBUG
+        fprintf(stderr,"classad_plugin: opened\n");
+#endif
+
+        *handle = h;
+
+        return 0;
+
+}
+
+static int classad_close(void *fpctx,void *handle) {
+       classad_handle *h = (classad_handle *) handle;
+
+       cclassad_delete(h->ad);
+       free(h->data);
+       free(h);
+
+#ifdef PLUGIN_DEBUG
+       fprintf(stderr,"classad plugin: close OK\n");
+#endif
+       return 0;
+}
+
+
+static int classad_query(void *fpctx,void *handle, const char* ns, const char *attr,glite_jp_attrval_t **attrval) {
+       glite_jp_context_t      ctx = (glite_jp_context_t) fpctx;
+       glite_jp_error_t        err;
+       glite_jp_attrval_t      *av = NULL;
+       classad_handle*         h = (classad_handle*)handle;
+
+        glite_jp_clear_error(ctx); 
+        memset(&err,0,sizeof err);
+        err.source = __FUNCTION__;
+
+       char *str = NULL;
+
+       if (! h->ad){
+               err.code = ENOENT;
+                err.desc = strdup("Classad plugin: No classad string, cannot get attr!");
+               *attrval = NULL;
+               printf("Exiting classat_query...\n");
+                return glite_jp_stack_error(ctx,&err);
+       }
+
+       if (cclassad_evaluate_to_string(h->ad, strrchr(attr, ':')+1, &str)) {
+               //struct stat fattr;
+               /*XXX ignore error */
+               //glite_jppsbe_file_attrs(ctx, h->bhandle, &fattr);
+               av = calloc(2, sizeof(glite_jp_attrval_t));
+                av[0].name = strdup(attr);
+                av[0].value = strdup(str);
+               av[0].size = -1;
+                av[0].timestamp = h->timestamp;
+               av[0].origin = GLITE_JP_ATTR_ORIG_FILE;
+        }
+       else{
+               printf("Classad plugin: bad attr!\n");
+       }
+        
+        if (str) free(str);
+
+       *attrval = av;
+
+       if (av)
+               return 0;
+       else{
+               err.code = ENOENT;
+                err.desc = attr;
+               return glite_jp_stack_error(ctx,&err);
+       }
+}
index 27da176..ccdb005 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "feed.h"
 #include "tags.h"
+#include "tags2.h"
 #include "backend.h"
 #include "db.h"
 
@@ -1005,6 +1006,24 @@ error_out:
        }
 }
 
+int glite_jppsbe_file_attrs(glite_jp_context_t ctx, void *handle, struct stat *buf){
+       glite_jp_error_t err;
+
+        assert(handle != NULL);
+
+        glite_jp_clear_error(ctx);
+        memset(&err,0,sizeof err);
+        err.source = __FUNCTION__;
+
+       if (! fstat(((fhandle)handle)->fd, buf)) {
+               err.code = errno;
+               err.desc = "Error calling fstat";
+               return -1;
+       }
+
+       return 0;
+}
+
 int glite_jppsbe_pread(
        glite_jp_context_t ctx,
        void *handle,
@@ -2311,6 +2330,86 @@ cleanup:
        return err.code;
 }
 
+int glite_jppsbe_append_tag(
+       void *fpctx,
+       char *jobid,
+       glite_jp_attrval_t *attr
+)
+{
+       void                    *file_be;
+       glite_jp_error_t        err;
+        glite_jp_context_t      ctx = fpctx;
+       memset(&err,0,sizeof err);
+        err.source = __FUNCTION__;
+
+       if (glite_jppsbe_open_file(ctx,jobid,"tags",NULL,
+                                                O_RDWR|O_CREAT,&file_be)
+                        // XXX: tags need reading to check magic number
+        ) {
+               err.code = EIO;
+               err.desc = "cannot open tags file";
+               return glite_jp_stack_error(ctx,&err);
+        }
+
+       if (tag_append(ctx,file_be,attr))
+        {
+               err.code = EIO;
+                err.desc = "cannot append tag";
+                return glite_jp_stack_error(ctx,&err);
+        }
+
+       if (glite_jppsbe_close_file(ctx,file_be))
+       {
+               err.code = EIO;
+                err.desc = "cannot close tags file";
+               return glite_jp_stack_error(ctx,&err);
+        }
+       
+       return 0;
+}
+
+
+int glite_jppsbe_read_tag(
+       void *fpctx,
+       const char *jobid,
+       const char *attr,
+       glite_jp_attrval_t **attrval
+)
+{
+        glite_jp_error_t        err;
+        glite_jp_context_t      ctx = fpctx;
+       struct tags_handle      *h;
+
+       memset(&err,0,sizeof err);
+        err.source = __FUNCTION__;
+       h = malloc(sizeof (*h));
+       h->tags = NULL;
+       h->n = 0;
+
+       if (glite_jppsbe_open_file(ctx,jobid,"tags",NULL,
+                                                O_RDONLY,&(h->bhandle))
+                        // XXX: tags need reading to check magic number
+        ) {
+                err.code = EIO;
+                err.desc = "cannot open tags file";
+                return glite_jp_stack_error(ctx,&err);
+        }
+
+       if (tag_attr(ctx,h,attr,attrval)){
+               err.code = EIO;
+                err.desc = "cannot read tag";
+                return glite_jp_stack_error(ctx,&err);         
+       }
+
+       if (glite_jppsbe_close_file(ctx,h->bhandle))
+        {
+                err.code = EIO;
+                err.desc = "cannot close tags file";
+                return glite_jp_stack_error(ctx,&err);
+        }
+       
+       return 0;
+}
 
 
 
index 7e57bcd..b13afe7 100644 (file)
@@ -36,7 +36,7 @@ static struct {
 //static int sandbox_append(void *,void *,int,...);
 static int sandbox_open(void *,void *,const char *uri,void **);
 static int sandbox_close(void *,void *);
-static int sandbox_attr(void *,void *,const char *,glite_jp_attrval_t **);
+static int sandbox_attr(void *,void *,const char*,const char *,glite_jp_attrval_t **);
 
 
 int init(glite_jp_context_t ctx, glite_jpps_fplug_data_t *data)
@@ -50,6 +50,10 @@ int init(glite_jp_context_t ctx, glite_jpps_fplug_data_t *data)
        data->classes = calloc(2,sizeof *data->classes);
        data->classes[0] = strdup("sandbox");
 
+       data->namespaces = calloc(3, sizeof *data->namespaces);
+        data->namespaces[0] = strdup(GLITE_JP_ISB_NS);
+       data->namespaces[1] = strdup(GLITE_JP_OSB_NS);
+
        data->ops.open = sandbox_open;
        data->ops.close = sandbox_close;
        data->ops.attr = sandbox_attr;
@@ -140,7 +144,7 @@ static int sandbox_close(void *fpctx,void *handle)
 }
 
 
-static int sandbox_attr(void *fpctx,void *handle,const char *attr,glite_jp_attrval_t **attrval)
+static int sandbox_attr(void *fpctx,void *handle,const char *ns,const char *attr,glite_jp_attrval_t **attrval)
 {
        glite_jp_error_t        err;
        glite_jp_context_t      ctx = fpctx;
index d933311..40b9cea 100644 (file)
@@ -194,7 +194,6 @@ SOAP_FMAC5 int SOAP_FMAC6 __jpsrv__RecordTag(
 {
        CONTEXT_FROM_SOAP(soap,ctx);
        void    *file_be,*file_p;
-       glite_jpps_fplug_data_t **pd = NULL;
        glite_jp_attrval_t      attr[2], meta[2];
 
 
@@ -227,42 +226,30 @@ SOAP_FMAC5 int SOAP_FMAC6 __jpsrv__RecordTag(
        attr[0].origin_detail = NULL;   /* XXX */
        attr[1].name = NULL;
 
-       /* XXX: we assume just one plugin and also that TAGS plugin handles
-        * just one uri/class */
+        /*if (glite_jppsbe_open_file(ctx,in->jobid,"tags",NULL,
+                                                O_RDWR|O_CREAT,&file_be)
+                        // XXX: tags need reading to check magic number
+        ) {
+                err2fault(ctx,soap);
+                return SOAP_FAULT;
+        }
 
-       if (glite_jpps_fplug_lookup(ctx,GLITE_JP_FILETYPE_TAGS,&pd)
-               || glite_jppsbe_open_file(ctx,in->jobid,pd[0]->classes[0],NULL,
-                                               O_RDWR|O_CREAT,&file_be)
-                       /* XXX: tags need reading to check magic number */
-       ) {
-               free(pd);
-               err2fault(ctx,soap);
-               return SOAP_FAULT;
-       }
-
-       /* XXX: assuming tag plugin handles just one type */
-       if (pd[0]->ops.open(pd[0]->fpctx,file_be,GLITE_JP_FILETYPE_TAGS,&file_p)
-               || pd[0]->ops.generic(pd[0]->fpctx,file_p,GLITE_JP_FPLUG_TAGS_APPEND,attr))
+       if (glite_jppsbe_close_file(ctx,file_be))
        {
                err2fault(ctx,soap);
-               if (file_p) pd[0]->ops.close(pd[0]->fpctx,file_p);
-               glite_jppsbe_close_file(ctx,file_be);
-               free(pd);
                return SOAP_FAULT;
-       }
+       }*/
+       glite_jppsbe_append_tag(ctx,in->jobid,attr);
 
-       if (pd[0]->ops.close(pd[0]->fpctx,file_p)
-               || glite_jppsbe_close_file(ctx,file_be))
+        /*if (tag_append(ctx,file_be,attr))
        {
-               err2fault(ctx,soap);
-               free(pd);
-               return SOAP_FAULT;
-       }
+                err2fault(ctx,soap);
+                return SOAP_FAULT;
+        }*/
 
        /* XXX: ignore errors but don't fail silenty */
        glite_jpps_match_attr(ctx,in->jobid,attr);
 
-       free(pd);
        return SOAP_OK;
 err:
        glite_jp_attrval_free(meta,0);
index 1f11b4d..764eb2d 100644 (file)
@@ -231,3 +231,221 @@ error_out:
        free(tags);
        return glite_jp_stack_error(ctx,&err);
 }
+
+int tag_append(void *fpctx,void *bhandle,glite_jp_attrval_t * tag)
+{
+        va_list ap;
+        char    *hdr,*rec;
+        glite_jp_context_t      ctx = fpctx;
+        uint32_t                magic,hlen,rlen,rlen_n;
+        size_t                  r;
+        glite_jp_error_t        err;
+
+        memset(&err,0,sizeof err);
+        err.source = __FUNCTION__;
+        glite_jp_clear_error(ctx);
+
+        printf("tagappend: %s,%s\n",tag->name,tag->value);
+
+        //assert(oper == GLITE_JP_FPLUG_TAGS_APPEND);
+
+        if (glite_jppsbe_pread(ctx,bhandle,&magic,sizeof magic,0,&r)) {
+                err.code = EIO;
+                err.desc = "reading magic number";
+                return glite_jp_stack_error(ctx,&err);
+        }
+
+        if (r == 0) {
+                magic = htonl(TAGS_MAGIC);
+                if (glite_jppsbe_pwrite(ctx,bhandle,&magic,sizeof magic,0)) {
+                        err.code = EIO;
+                        err.desc = "writing magic number";
+                        return glite_jp_stack_error(ctx,&err);
+                }
+        }
+        else if (r != sizeof magic) {
+                err.code = EIO;
+                err.desc = "can't read magic number";
+                return glite_jp_stack_error(ctx,&err);
+        }
+        else if (magic != htonl(TAGS_MAGIC)) {
+                err.code = EINVAL;
+                err.desc = "invalid magic number";
+                return glite_jp_stack_error(ctx,&err);
+        }
+
+/* XXX: origin is always USER, not recorded */
+        trio_asprintf(&hdr,"%ld %c",
+                        tag->timestamp,tag->binary ? 'B' : 'S');
+
+        rlen = strlen(tag->name) + strlen(hdr) + 2 /* \0 after name and after hdr */ +
+                (r = tag->binary ? tag->size : (tag->value ? strlen(tag->value) : 0));
+
+        rlen_n = htonl(rlen);
+
+        rec = malloc(rlen + sizeof rlen_n);
+        *((uint32_t *) rec) = rlen_n;
+        strcpy(rec + sizeof rlen_n,tag->name);
+        strcpy(rec + (hlen = sizeof rlen_n + strlen(tag->name) + 1),hdr);
+
+        if (r) memcpy(rec + hlen + strlen(hdr) + 1,tag->value,r);
+        free(hdr);
+
+/* record format:
+ * - 4B length, net byte order
+ * - attr name, \0
+ * - %ld %c \0 (timestamp, B/S)
+ * - value
+ */
+        if (glite_jppsbe_append(ctx,bhandle,rec,rlen + sizeof rlen_n)) {
+                err.code = EIO;
+                err.desc = "writing tag record";
+                free(rec);
+                return glite_jp_stack_error(ctx,&err);
+        }
+
+        /* XXX: should add tag also to handle->tags, but it is never used
+         * currently */
+
+        return 0;
+}
+
+int tag_attr(void *fpctx,void *handle,const char *attr,glite_jp_attrval_t **attrval)
+{
+        struct tags_handle      *h = handle;
+        glite_jp_error_t        err;
+        glite_jp_context_t      ctx = fpctx;
+        glite_jp_attrval_t      *out = NULL;
+        int     i,nout = 0;
+
+        memset(&err,0,sizeof err);
+        err.source = __FUNCTION__;
+
+        if (!h->tags) tagsread(fpctx,handle);
+
+        if (!h->tags) {
+                err.code = ENOENT;
+                err.desc = "no tags for this job";
+                return glite_jp_stack_error(ctx,&err);
+        }
+
+        for (i=0; i<h->n; i++) if (!strcmp(h->tags[i].name,attr)) {
+                out = realloc(out,(nout+2) * sizeof *out);
+                glite_jp_attrval_copy(out+nout,h->tags+i);
+                nout++;
+                memset(out+nout,0,sizeof *out);
+        }
+
+        if (nout) {
+                *attrval = out;
+                return 0;
+        }
+        else {
+                err.code = ENOENT;
+                err.desc = "no value for this tag";
+                return glite_jp_stack_error(ctx,&err);
+        }
+}
+
+static int tagsread(void *fpctx,struct tags_handle *h)
+{
+        glite_jp_context_t      ctx = fpctx;
+        uint32_t                magic,rlen;
+        glite_jp_error_t        err;
+        int                     r;
+        size_t                  off = sizeof rlen;
+        glite_jp_attrval_t      *tp;
+        char                    *rp;
+
+        memset(&err,0,sizeof err);
+        err.source = __FUNCTION__;
+
+        glite_jp_clear_error(ctx);
+
+// read magic number
+        if (glite_jppsbe_pread(ctx,h->bhandle,&magic,sizeof magic,0,&r)) {
+                err.code = EIO;
+                err.desc = "reading magic number";
+                return glite_jp_stack_error(ctx,&err);
+        }
+
+        if (r != sizeof magic) {
+                err.code = EIO;
+                err.desc = "can't read magic number";
+                return glite_jp_stack_error(ctx,&err);
+        }
+        else if (magic != htonl(TAGS_MAGIC)) {
+                err.code = EINVAL;
+                err.desc = "invalid magic number";
+                return glite_jp_stack_error(ctx,&err);
+        }
+
+
+        while (1) {
+                char    *rec,type;
+                int     rd;
+
+       // read record header
+                if (glite_jppsbe_pread(ctx,h->bhandle,&rlen,sizeof rlen,off,&r)) {
+                        err.code = EIO;
+                        err.desc = "reading record header";
+                        return glite_jp_stack_error(ctx,&err);
+                }
+                if (r == 0) break;
+
+                if (r != sizeof rlen) {
+                        err.code = EIO;
+                        err.desc = "can't read record header";
+                        return glite_jp_stack_error(ctx,&err);
+                }
+
+                off += r;
+                rec = malloc(rlen = ntohl(rlen));
+
+        // read whole record body thoroughly
+                for (rd=0; rd<rlen; rd+=r) // XXX: will loop on 0 bytes read
+                        if (glite_jppsbe_pread(ctx,h->bhandle,rec+rd,rlen-rd,off+rd,&r)) {
+                                err.code = EIO;
+                                err.desc = "reading record body";
+                                free(rec);
+                                return glite_jp_stack_error(ctx,&err);
+                        }
+
+                off += rlen;
+
+        // parse the record
+                h->tags = realloc(h->tags,(h->n+2) * sizeof *h->tags);
+                tp = h->tags+h->n++;
+                memset(tp,0,sizeof *tp);
+
+                tp->name = strdup(rec);
+                rp = rec + strlen(rec) + 1;
+
+                sscanf(rp,"%ld %c",&tp->timestamp,&type);
+                rp += strlen(rp) + 1;
+                switch (type) {
+                        int     i;
+
+                        case 'B': tp->binary = 1; break;
+                        case 'S': tp->binary = 0; break;
+                        default: free(rec);
+                                 for (i=0; i<h->n; i++)
+                                         glite_jp_attrval_free(h->tags+i,0);
+                                 free(h->tags);
+                                 h->tags = NULL;
+                                 h->n = 0;
+
+                                 err.code = EINVAL;
+                                 err.desc = "invalid attr type (B/S)";
+                                 return glite_jp_stack_error(ctx,&err);
+                }
+                tp->value = malloc((r=rlen - (rp - rec)) + 1);
+                memcpy(tp->value,rp,r);
+                if (!tp->binary) tp->value[r] = 0;
+                tp->origin = GLITE_JP_ATTR_ORIG_USER;
+
+                free(rec);
+        }
+        return 0;
+}
+
index 3aade74..c616122 100644 (file)
@@ -1 +1,9 @@
+struct tags_handle {
+        void    *bhandle;
+        int     n;
+        glite_jp_attrval_t      *tags;
+};
+
+int tag_append(void *fpctx,void *bhandle,glite_jp_attrval_t * tag);
 int glite_jpps_tag_append(glite_jp_context_t,void *,const char *, const char *);
+int tag_attr(void *fpctx,void *handle,const char *attr,glite_jp_attrval_t **attrval);
diff --git a/org.glite.jp.primary/src/tags_plugin.c b/org.glite.jp.primary/src/tags_plugin.c
deleted file mode 100644 (file)
index 953ace9..0000000
+++ /dev/null
@@ -1,298 +0,0 @@
-#include <stdlib.h>
-#include <assert.h>
-#include <stdarg.h>
-#include <string.h>
-#include <errno.h>
-#include <stdint.h>
-
-#include <glite/jp/types.h>
-
-#include "file_plugin.h"
-#include "builtin_plugins.h"
-#include "backend.h"
-
-static int tagappend(void *,void *,int,...);
-static int tagopen(void *,void *,const char *uri,void **);
-static int tagclose(void *,void *);
-static int tagattr(void *,void *,const char *,glite_jp_attrval_t **);
-
-struct tags_handle {
-       void    *bhandle;
-       int     n;
-       glite_jp_attrval_t      *tags;
-};
-
-static int tagsread(void *,struct tags_handle *);
-
-#define TAGS_MAGIC 0x74c016f2  /* two middle digits encode version, i.e. 01 */
-
-static int tagdummy()
-{
-       puts("tagdummy()");
-       return -1;
-}
-
-int init(glite_jp_context_t ctx, glite_jpps_fplug_data_t *data)
-{
-       data->fpctx = ctx;
-
-       data->uris = calloc(2,sizeof *data->uris);
-       data->uris[0] = strdup(GLITE_JP_FILETYPE_TAGS);
-
-       data->classes = calloc(2,sizeof *data->classes);
-       data->classes[0] = strdup("tags");
-
-       data->ops.open = tagopen;
-       data->ops.close = tagclose;
-       data->ops.attr = tagattr;
-       data->ops.generic = tagappend;
-       
-       printf("tags_plugin: URI: \"%s\"; magic number: 0x%08lx\n",GLITE_JP_FILETYPE_TAGS,TAGS_MAGIC);
-       return 0;
-}
-
-static int tagopen(void *fpctx,void *bhandle,const char *uri,void **handle)
-{
-       struct tags_handle *h = calloc(1,sizeof *h);
-       h->n = 0;
-       h->bhandle = bhandle;
-
-       *handle = h;
-
-       return 0;
-}
-
-static int tagclose(void *fpctx,void *handle)
-{
-       int     i;
-       struct tags_handle *h = handle;
-
-       for (i=0; i<h->n; i++) glite_jp_attrval_free(h->tags+i,0);
-       free(h->tags);
-       free(h);
-
-       return 0;
-}
-
-static int tagappend(void *fpctx,void *handle,int oper,...)
-{
-       glite_jp_attrval_t      *tag;
-       va_list ap;
-       char    *hdr,*rec;
-       glite_jp_context_t      ctx = fpctx;
-       struct tags_handle      *h = handle;
-       uint32_t                magic,hlen,rlen,rlen_n;
-       size_t                  r;
-       glite_jp_error_t        err;
-
-       memset(&err,0,sizeof err);
-       err.source = __FUNCTION__;
-       glite_jp_clear_error(ctx);
-
-       va_start(ap,oper);
-       tag = va_arg(ap,glite_jp_attrval_t *);
-       va_end(ap);
-
-       printf("tagappend: %s,%s\n",tag->name,tag->value);
-
-       assert(oper == GLITE_JP_FPLUG_TAGS_APPEND);
-
-       if (glite_jppsbe_pread(ctx,h->bhandle,&magic,sizeof magic,0,&r)) {
-               err.code = EIO;
-               err.desc = "reading magic number";
-               return glite_jp_stack_error(ctx,&err);
-       }
-
-       if (r == 0) {
-               magic = htonl(TAGS_MAGIC);
-               if (glite_jppsbe_pwrite(ctx,h->bhandle,&magic,sizeof magic,0)) {
-                       err.code = EIO;
-                       err.desc = "writing magic number";
-                       return glite_jp_stack_error(ctx,&err);
-               }
-       }
-       else if (r != sizeof magic) {
-               err.code = EIO;
-               err.desc = "can't read magic number";
-               return glite_jp_stack_error(ctx,&err);
-       }
-       else if (magic != htonl(TAGS_MAGIC)) {
-               err.code = EINVAL;
-               err.desc = "invalid magic number";
-               return glite_jp_stack_error(ctx,&err);
-       }
-
-/* XXX: origin is always USER, not recorded */
-       trio_asprintf(&hdr,"%ld %c",
-                       tag->timestamp,tag->binary ? 'B' : 'S');
-
-       rlen = strlen(tag->name) + strlen(hdr) + 2 /* \0 after name and after hdr */ +
-               (r = tag->binary ? tag->size : (tag->value ? strlen(tag->value) : 0));
-
-       rlen_n = htonl(rlen);
-
-       rec = malloc(rlen + sizeof rlen_n);
-       *((uint32_t *) rec) = rlen_n;
-       strcpy(rec + sizeof rlen_n,tag->name);
-       strcpy(rec + (hlen = sizeof rlen_n + strlen(tag->name) + 1),hdr);
-
-       if (r) memcpy(rec + hlen + strlen(hdr) + 1,tag->value,r);
-       free(hdr);
-
-/* record format:
- * - 4B length, net byte order
- * - attr name, \0
- * - %ld %c \0 (timestamp, B/S)
- * - value
- */
-       if (glite_jppsbe_append(ctx,h->bhandle,rec,rlen + sizeof rlen_n)) {
-               err.code = EIO;
-               err.desc = "writing tag record";
-               free(rec);
-               return glite_jp_stack_error(ctx,&err);
-       }
-
-       /* XXX: should add tag also to handle->tags, but it is never used 
-        * currently */
-       
-       return 0;
-}
-
-static int tagattr(void *fpctx,void *handle,const char *attr,glite_jp_attrval_t **attrval)
-{
-       struct tags_handle      *h = handle;
-       glite_jp_error_t        err;
-       glite_jp_context_t      ctx = fpctx;
-       glite_jp_attrval_t      *out = NULL;
-       int     i,nout = 0;
-
-       memset(&err,0,sizeof err);
-       err.source = __FUNCTION__;
-
-       if (!h->tags) tagsread(fpctx,handle);
-
-       if (!h->tags) {
-               err.code = ENOENT;
-               err.desc = "no tags for this job";
-               return glite_jp_stack_error(ctx,&err);
-       }
-
-       for (i=0; i<h->n; i++) if (!strcmp(h->tags[i].name,attr)) {
-               out = realloc(out,(nout+2) * sizeof *out);
-               glite_jp_attrval_copy(out+nout,h->tags+i);
-               nout++;
-               memset(out+nout,0,sizeof *out);
-       }
-
-       if (nout) {
-               *attrval = out;
-               return 0;
-       }
-       else {
-               err.code = ENOENT;
-               err.desc = "no value for this tag";
-               return glite_jp_stack_error(ctx,&err);
-       }
-}
-
-static int tagsread(void *fpctx,struct tags_handle *h)
-{
-       glite_jp_context_t      ctx = fpctx;
-       uint32_t                magic,rlen;
-       glite_jp_error_t        err;
-       int                     r;
-       size_t                  off = sizeof rlen;
-       glite_jp_attrval_t      *tp;
-       char                    *rp;
-
-       memset(&err,0,sizeof err);
-       err.source = __FUNCTION__;
-       
-       glite_jp_clear_error(ctx);
-
-/* read magic number */
-       if (glite_jppsbe_pread(ctx,h->bhandle,&magic,sizeof magic,0,&r)) {
-               err.code = EIO;
-               err.desc = "reading magic number";
-               return glite_jp_stack_error(ctx,&err);
-       }
-
-       if (r != sizeof magic) {
-               err.code = EIO;
-               err.desc = "can't read magic number";
-               return glite_jp_stack_error(ctx,&err);
-       }
-       else if (magic != htonl(TAGS_MAGIC)) {
-               err.code = EINVAL;
-               err.desc = "invalid magic number";
-               return glite_jp_stack_error(ctx,&err);
-       }
-
-
-       while (1) {
-               char    *rec,type;
-               int     rd;
-
-       /* read record header */
-               if (glite_jppsbe_pread(ctx,h->bhandle,&rlen,sizeof rlen,off,&r)) {
-                       err.code = EIO;
-                       err.desc = "reading record header";
-                       return glite_jp_stack_error(ctx,&err);
-               }
-               if (r == 0) break;
-
-               if (r != sizeof rlen) {
-                       err.code = EIO;
-                       err.desc = "can't read record header";
-                       return glite_jp_stack_error(ctx,&err);
-               }
-
-               off += r;
-               rec = malloc(rlen = ntohl(rlen));
-
-       /* read whole record body thoroughly */
-               for (rd=0; rd<rlen; rd+=r) /* XXX: will loop on 0 bytes read */
-                       if (glite_jppsbe_pread(ctx,h->bhandle,rec+rd,rlen-rd,off+rd,&r)) {
-                               err.code = EIO;
-                               err.desc = "reading record body";
-                               free(rec);
-                               return glite_jp_stack_error(ctx,&err);
-                       }
-
-               off += rlen;
-
-       /* parse the record */
-               h->tags = realloc(h->tags,(h->n+2) * sizeof *h->tags);
-               tp = h->tags+h->n++;
-               memset(tp,0,sizeof *tp);
-
-               tp->name = strdup(rec);
-               rp = rec + strlen(rec) + 1;
-
-               sscanf(rp,"%ld %c",&tp->timestamp,&type);
-               rp += strlen(rp) + 1;
-               switch (type) {
-                       int     i;
-
-                       case 'B': tp->binary = 1; break;
-                       case 'S': tp->binary = 0; break;
-                       default: free(rec);
-                                for (i=0; i<h->n; i++)
-                                        glite_jp_attrval_free(h->tags+i,0);
-                                free(h->tags);
-                                h->tags = NULL;
-                                h->n = 0;
-
-                                err.code = EINVAL;
-                                err.desc = "invalid attr type (B/S)";
-                                return glite_jp_stack_error(ctx,&err);
-               }
-               tp->value = malloc((r=rlen - (rp - rec)) + 1);
-               memcpy(tp->value,rp,r);
-               if (!tp->binary) tp->value[r] = 0;
-               tp->origin = GLITE_JP_ATTR_ORIG_USER;
-
-               free(rec);
-       }
-       return 0;
-}