- Job listing over HTML simplified (algorithm complexity reduced)
authorZdeněk Šustr <sustr4@cesnet.cz>
Thu, 31 May 2012 15:42:00 +0000 (15:42 +0000)
committerZdeněk Šustr <sustr4@cesnet.cz>
Thu, 31 May 2012 15:42:00 +0000 (15:42 +0000)
- HTML/text output production now in a single function

org.glite.lb.server/src/lb_html.c
org.glite.lb.server/src/lb_html.h
org.glite.lb.server/src/lb_proto.c
org.glite.lb.server/src/lb_text.c
org.glite.lb.server/src/lb_text.h

index acee5c9..78a4c1d 100644 (file)
@@ -48,84 +48,96 @@ int edg_wll_QueryToHTML(edg_wll_Context ctx UNUSED_VAR, edg_wll_Event *eventsOut
        return -1;
 }
 
+int jobstat_cmp (const void *a, const void *b) {
+       static int compr;
+       // This code should sort IDs by parent ID first, then by JobID.
+       compr = strcmp(((JobIdSorter*)a)->key, ((JobIdSorter*)b)->key);
+       if (compr) return compr;
+       if (!((JobIdSorter*)a)->parent_unparsed) return -1;
+       if (!((JobIdSorter*)b)->parent_unparsed) return 1;
+       return strcmp(((JobIdSorter*)a)->id_unparsed, ((JobIdSorter*)b)->id_unparsed);
+}
+
 /* construct Message-Body of Response-Line for edg_wll_UserJobs */
-int edg_wll_UserInfoToHTML(edg_wll_Context ctx UNUSED_VAR, edg_wlc_JobId *jobsOut, edg_wll_JobStat *statsOut, char **message)
+int edg_wll_UserInfoToHTML(edg_wll_Context ctx UNUSED_VAR, edg_wlc_JobId *jobsOut, edg_wll_JobStat *statsOut, char **message, int text)
 {
-       //TODO remove quadratic complexity one day...
+        char *pomA = NULL, *pomB, *pomC;
+       int i, total = 0, bufsize, written = 0, linlen, wassub = 0, lineoverhead;
+       JobIdSorter *order;
+       
 
-        char *pomA = NULL, *pomB;
-        int i = 0, j;
+        while (jobsOut && jobsOut[total]) total++;
 
-        /* head */
-        pomB = strdup("");
+       order=(JobIdSorter*)malloc(sizeof(JobIdSorter) * total);
 
-        while (jobsOut && jobsOut[i]) {
-                char    *chid = edg_wlc_JobIdUnparse(jobsOut[i]);
+       for (i = 0; i < total; i++) {
+               order[i].id_unparsed = edg_wlc_JobIdUnparse(jobsOut[i]);
+               order[i].parent_unparsed = edg_wlc_JobIdUnparse(statsOut[i].parent_job);
+               order[i].key = order[i].parent_unparsed ? order[i].parent_unparsed : order[i].id_unparsed;
+               order[i].order = i;
+       } 
 
-               if (! statsOut){
-                        asprintf(&pomA,"%s\t\t <li><a href=\"%s\">%s</a></li>\r\n",
-                                pomB, chid,chid);
-                        free(pomB);
-                        pomB = pomA;
-               }
-               else if ((statsOut[i].jobtype != EDG_WLL_STAT_FILE_TRANSFER_COLLECTION 
-                       && statsOut[i].jobtype != EDG_WLL_STAT_FILE_TRANSFER 
-                       && ! statsOut[i].parent_job )
-                       || ((statsOut[i].jobtype == EDG_WLL_STAT_FILE_TRANSFER_COLLECTION 
-                       || statsOut[i].jobtype == EDG_WLL_STAT_FILE_TRANSFER) 
-                       && ! statsOut[i].ft_compute_job)
-                       ){
-                       asprintf(&pomA,"%s\t\t <li><a href=\"%s\">%s</a></li>\r\n",
-                               pomB, chid,chid);
-                       free(pomB);
-                       pomB = pomA;
-                       if (statsOut[i].jobtype == EDG_WLL_STAT_COLLECTION){
-                               asprintf(&pomA,"%s\t\t <ul>\r\n", pomB);
-                                free(pomB);
-                                pomB = pomA;
-                               j = 0;
-                               while (jobsOut[j]) {
-                                       char *chid_parent = edg_wlc_JobIdUnparse(statsOut[j].parent_job);
-                                       if (chid_parent && (strcmp(chid, chid_parent) == 0)){
-                                               char *chid_children = edg_wlc_JobIdUnparse(jobsOut[j]);
-                                               asprintf(&pomA,"%s\t\t <li><a href=\"%s\">%s</a></li>\r\n",
-                                                       pomB, chid_children,chid_children);
-                                               free(chid_children);
-                                               free(pomB);
-                                               pomB = pomA;
-                                       }
-                                       free(chid_parent);
-                                       j++;
-                               }
-                               asprintf(&pomA,"%s\t\t </ul>\r\n", pomB);
-                                free(pomB);
-                                pomB = pomA;
-                       }
-                       free(chid);
+       if (text) {
+               linlen = asprintf(&pomA,"User_jobs=");
+               asprintf(&pomC, "User_subject=%s\n", ctx->peerName ? ctx->peerName: "<anonymous>");
+               lineoverhead = 2;
+       }
+       else {          
+               qsort(order, total, sizeof(JobIdSorter), jobstat_cmp); 
+       
+               linlen = asprintf(&pomA, "<HTML>\n<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n<TITLE>User Jobs</TITLE>\n<BODY>\n"
+                       "<h2><B>User Jobs</B></h2>\nTotal of %d<P><UL>\n",total);
+
+               asprintf(&pomC, "</UL>User subject: %s<p>\n"
+                       "</BODY>\n</HTML>",
+                       ctx->peerName?ctx->peerName: "&lt;anonymous&gt;" );
+
+               lineoverhead = 35;//Good idea to change this value if the table row format changes, but not 100-% necessary. Loop will realloc if necessary.
+       }
+
+       bufsize = (strlen(order[0].id_unparsed)*2+lineoverhead)*total + linlen + strlen(pomC);
+       pomB = (char*)malloc(sizeof(char) * bufsize);
+
+       strcpy(pomB + written, pomA);
+       written=linlen;
+       free(pomA);
+
+        /* head */
+       for (i = 0; i < total; i++) {
+               if (text) linlen = asprintf(&pomA,"%s%s", order[i].id_unparsed, i + 1 == total ? "\n" : ",");
+               else {
+                       linlen = asprintf(&pomA, "%s<li><a href=\"%s\">%s</a></li>\n",
+                               order[i].parent_unparsed ? (wassub++ ? "" : "<ul>") : (wassub ? "</UL>" : ""),
+                               order[i].id_unparsed,
+                               order[i].id_unparsed );
+                       if (!order[i].parent_unparsed) wassub = 0;
                }
 
-                i++;
-        }
+               while (written+linlen >= bufsize) {
+                       bufsize = (bufsize + 5) * 1.2;
+                       pomB = realloc(pomB, sizeof(char) * bufsize);
+               }
 
-       char *ret;
-       asprintf(&ret, "<html>\r\n\t<body>\r\n");
-       pomA = ret;
-       if (pomB[0]){
-               asprintf(&ret, "%s<h2><B>User jobs</B></h2>\r\n"
-                       "<ul>%s</ul>",
-                       pomA, pomB
-               );
+               strcpy(pomB + written, pomA);
+               written = written + linlen;
                free(pomA);
-               free(pomB);
        }
-       pomA = ret;
-       asprintf(&ret, "%sUser subject: %s<p>"
-               "\t</body>\r\n</html>",
-               pomA, ctx->peerName?ctx->peerName: "&lt;anonymous&gt;"
-       );
-       free(pomA);
 
-        *message = ret;
+       if (written+strlen(pomC)+strlen("</UL>") >= bufsize) {
+               pomB = realloc(pomB, bufsize + strlen(pomC) + strlen("</UL>"));
+       }
+
+       if (wassub) { strcpy(pomB + written, "</UL>"); written = written + strlen("</UL>"); }
+       strcpy(pomB + written, pomC);
+       free(pomC);
+
+       for (i = 0; i < total; i++) {
+               free(order[i].id_unparsed);
+               free(order[i].parent_unparsed);
+       } 
+       free(order);
+
+        *message = pomB;
 
         return 0;
 }
index 675059d..de054a1 100644 (file)
@@ -25,10 +25,16 @@ limitations under the License.
 #include "glite/lb/jobstat.h"
 #include "lb_proto.h"
 
+typedef struct {
+       char *id_unparsed;
+       char *parent_unparsed;
+       char *key;
+       int order; } JobIdSorter;
+
 int edg_wll_QueryToHTML(edg_wll_Context,edg_wll_Event *,char **);
 int edg_wll_GeneralJobStatusToHTML(edg_wll_Context, edg_wll_JobStat, char **);
 int edg_wll_CreamJobStatusToHTML(edg_wll_Context, edg_wll_JobStat, char **);
-int edg_wll_UserInfoToHTML(edg_wll_Context, edg_wlc_JobId *, edg_wll_JobStat *, char **);
+int edg_wll_UserInfoToHTML(edg_wll_Context, edg_wlc_JobId *, edg_wll_JobStat *, char **, int text);
 int edg_wll_UserNotifsToHTML(edg_wll_Context ctx, char **notifids, char **message, http_admin_option option, int adm);
 int edg_wll_NotificationToHTML(edg_wll_Context ctx, notifInfo *ni, char **message);
 char *edg_wll_ErrorToHTML(edg_wll_Context,int);
index b1181ba..3c63140 100644 (file)
@@ -722,15 +722,8 @@ edg_wll_ErrorCode edg_wll_Proto(edg_wll_Context ctx,
                        flags = (requestPTR[1]=='?') ? edg_wll_string_to_stat_flags(requestPTR + 2) : 0;
 
                        switch (edg_wll_UserJobsServer(ctx, EDG_WLL_STAT_CHILDREN, &jobsOut, &statesOut)) {
-                               case 0: if (text){
-                                               edg_wll_UserInfoToText(ctx, jobsOut, &message);
-                                               edg_wll_ServerStatisticsIncrement(ctx, SERVER_STATS_TEXT_VIEWS);
-                                       }
-                                       else if (html){
-                                               edg_wll_UserInfoToHTML(ctx, jobsOut, statesOut, &message);
-                                               edg_wll_ServerStatisticsIncrement(ctx, SERVER_STATS_HTML_VIEWS);
-                                       }
-                                       else ret = HTTP_OK;
+                               case 0: edg_wll_UserInfoToHTML(ctx, jobsOut, statesOut, &message, text);
+                                       edg_wll_ServerStatisticsIncrement(ctx, text ? SERVER_STATS_TEXT_VIEWS : SERVER_STATS_HTML_VIEWS);
                                        break;
                                case ENOENT: ret = HTTP_NOTFOUND; break;
                                case EPERM: ret = HTTP_UNAUTH; break;
index 75fd249..31d6536 100644 (file)
@@ -121,41 +121,6 @@ int edg_wll_QueryToText(edg_wll_Context ctx UNUSED_VAR, edg_wll_Event *eventsOut
         free(a); a=NULL; \
 }
 
-
-int edg_wll_UserInfoToText(edg_wll_Context ctx, edg_wlc_JobId *jobsOut, char **message)
-{
-        char *a = NULL, *b;
-        int i = 0;
-        b = strdup("");
-
-        while (jobsOut[i]){
-                char *chid = edg_wlc_JobIdUnparse(jobsOut[i]);
-
-                if (i == 0)
-                        asprintf(&a, "%s%s", b, chid);
-                else
-                        asprintf(&a, "%s,%s", b, chid);
-
-                free(chid);
-                free(b);
-                b = a;
-                i++;
-        }
-
-       if (a){
-               asprintf(&a, "User_jobs=%s\n", b);
-               free(b);
-               b = a;
-       }
-       b = a;
-
-       asprintf(&a, "%sUser_subject=%s\n", b, ctx->peerName ? ctx->peerName: "<anonymous>");
-
-        *message = a;
-
-        return 0;
-}
-
 int edg_wll_UserNotifsToText(edg_wll_Context ctx, char **notifids, char **message){
        char *a = NULL, *b;
         int i = 0;
index c6d5da6..c5647f2 100644 (file)
@@ -25,7 +25,6 @@ limitations under the License.
 
 int edg_wll_QueryToText(edg_wll_Context,edg_wll_Event *,char **);
 int edg_wll_JobStatusToText(edg_wll_Context, edg_wll_JobStat, char **);
-int edg_wll_UserInfoToText(edg_wll_Context, edg_wlc_JobId *, char **);
 int edg_wll_UserNotifsToText(edg_wll_Context ctx, char **notifids, char **message);
 int edg_wll_NotificationToText(edg_wll_Context ctx, notifInfo *ni, char **message);
 int edg_wll_ConfigurationToText(edg_wll_Context ctx, int admin, char **message);