00001 #define DEBUG 0
00002
00003
00004
00005 #define TESTMODE 0
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "jsoc_main.h"
00027 #include "drms.h"
00028 #include "drms_names.h"
00029 #include "db.h"
00030 #include "json.h"
00031 #include "printk.h"
00032 #include "qDecoder.h"
00033 #include "jsmn.h"
00034 #include <sys/types.h>
00035 #include <sys/stat.h>
00036 #include <unistd.h>
00037 #include <time.h>
00038 #include <sys/file.h>
00039 #include <regex.h>
00040 #include <openssl/md5.h>
00041
00042 #define kDefRegexp "JSOC_[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]_[0-9]+(_IN)?"
00043
00044 #define DUP_EXPORT_WINDOW 24 // hours
00045
00046
00047 #define kLockFile "/home/jsoc/exports/tmp/lock.txt"
00048 #define kLogFileSumm "/home/jsoc/exports/logs/fetch_log"
00049 #define kLogFileExpSuInt "/home/jsoc/exports/logs/fetchlogExpSuInt.txt"
00050 #define kLogFileExpSuExt "/home/jsoc/exports/logs/fetchlogExpSuExt.txt"
00051 #define kLogFileExpReqInt "/home/jsoc/exports/logs/fetchlogExpReqInt.txt"
00052 #define kLogFileExpReqExt "/home/jsoc/exports/logs/fetchlogExpReqExt.txt"
00053 #define kLogFileExpStatInt "/home/jsoc/exports/logs/fetchlogExpStatInt.txt"
00054 #define kLogFileExpStatExt "/home/jsoc/exports/logs/fetchlogExpStatExt.txt"
00055
00056 #define MAX_COMPRESSING_EXPORT_SIZE 1000000 // 1000GB
00057 #define MAX_STRAIGHT_EXPORT_SIZE 100000 // 100GB
00058 #define MAX_UNCOMPRESSING_EXPORT_SIZE 10000 // 10GB
00059
00060 #define kExportSeries "jsoc.export"
00061 #define kExportSeriesNew "jsoc.export_new"
00062 #define kExportUser "jsoc.export_user"
00063
00064 #define kArgOp "op"
00065 #define kArgRequestid "requestid"
00066 #define kArgDs "ds"
00067 #define kArgSunum "sunum"
00068 #define kArgSeg "seg"
00069 #define kArgProcess "process"
00070 #define kArgFormat "format"
00071 #define kArgFormatvar "formatvar"
00072 #define kArgMethod "method"
00073 #define kArgProtocol "protocol"
00074 #define kArgFilenamefmt "filenamefmt"
00075 #define kArgRequestor "requestor"
00076 #define kArgNotify "notify"
00077 #define kArgShipto "shipto"
00078 #define kArgRequestorid "requestorid"
00079 #define kArgFile "file"
00080 #define kArgTestmode "t"
00081 #define kArgPassthrough "p"
00082 #define kOpSeriesList "series_list" // show_series
00083 #define kOpSeriesStruct "series_struct" // jsoc_info, series structure, ike show_info -l -s
00084 #define kOpRsSummary "rs_summary" // jsoc_info, recordset summary, like show_info -c
00085 #define kOpRsList "rs_list" // jsoc_info, recordset list, like show_info key=... seg=... etc.
00086 #define kOpRsImage "rs_image" // not used yet
00087 #define kOpExpRequest "exp_request" // jsoc_fetch, initiate export request
00088 #define kOpExpRepeat "exp_repeat" // jsoc_fetch, initiate export repeat
00089 #define kOpExpStatus "exp_status" // jsoc_fetch, get status of pending export
00090 #define kOpExpSu "exp_su" // jsoc_fetch, export SUs from list of sunums
00091 #define kOpExpKinds "exp_kinds" // not used yet
00092 #define kOpExpHistory "exp_history" // not used yet
00093 #define kUserHandle "userhandle" // user provided unique session handle
00094 #define kArgSizeRatio "sizeratio"
00095 #define kArgDontGenWebPage "W"
00096 #define kArgCgiInstance "instid"
00097
00098 #define kOptProtocolAsIs "as-is" // Protocol option value for no change to fits files
00099 #define kOptProtocolSuAsIs "su-as-is" // Protocol option value for requesting as-is FITS paths for the exp_su operation
00100
00101 #define kNotSpecified "Not Specified"
00102
00103 #define kNoAsyncReq "NOASYNCREQUEST"
00104
00105 int dojson, dotxt, dohtml, doxml;
00106
00107 HContainer_t *gLogs = NULL;
00108
00109 ModuleArgs_t module_args[] =
00110 {
00111 {ARG_STRING, kArgOp, kNotSpecified, "<Operation>"},
00112 {ARG_STRING, kArgDs, kNotSpecified, "<record_set query>"},
00113 {ARG_STRING, kArgSeg, kNotSpecified, "<record_set segment list>"},
00114 {ARG_INTS, kArgSunum, "-1", "<sunum list for SU exports>"},
00115 {ARG_STRING, kArgRequestid, kNotSpecified, "JSOC export request identifier"},
00116 {ARG_STRING, kArgProcess, kNotSpecified, "string containing program and arguments"},
00117 {ARG_STRING, kArgRequestor, kNotSpecified, "name of requestor"},
00118 {ARG_STRING, kArgNotify, kNotSpecified, "email address of requestor"},
00119 {ARG_STRING, kArgShipto, kNotSpecified, "mail address of requestor"},
00120 {ARG_STRING, kArgProtocol, kOptProtocolAsIs, "exported file protocol"},
00121 {ARG_STRING, kArgFilenamefmt, "{seriesname}.{recnum:%d}.{segment}", "exported file filename format"},
00122 {ARG_STRING, kArgFormat, "json", "return content type"},
00123 {ARG_STRING, kArgFormatvar, kNotSpecified, "return json in object format"},
00124 {ARG_STRING, kArgMethod, "url", "return method"},
00125 {ARG_STRING, kArgFile, kNotSpecified, "uploaded file contents"},
00126 {ARG_STRING, kUserHandle, kNotSpecified, "User specified unique session ID"},
00127 {ARG_INT, kArgCgiInstance, "-1", "CGI instance ID"},
00128 {ARG_FLOAT, kArgSizeRatio, "1.0", "For cut-out requests, this is the ratio between the number of cut-out pixels to the number of original-image pixels."},
00129 {ARG_FLAG, kArgTestmode, NULL, "if set, then creates new requests with status 12 (not 2)"},
00130 {ARG_FLAG, kArgPassthrough, NULL, "if set, then inserts an X into the request ID to denote that the request originated from an external user, but was executed on the internal database."},
00131 {ARG_FLAG, kArgDontGenWebPage, NULL, "if set, print to stdout HTML headers."},
00132 {ARG_FLAG, "h", "0", "help - show usage"},
00133 {ARG_STRING, "QUERY_STRING", kNotSpecified, "AJAX query from the web"},
00134 {ARG_STRING, "REMOTE_ADDR", "0.0.0.0", "Remote IP address"},
00135 {ARG_STRING, "SERVER_NAME", "ServerName", "JSOC Server Name"},
00136 {ARG_END}
00137 };
00138
00139 char *module_name = "jsoc_fetch";
00140
00141 int nice_intro ()
00142 {
00143 int usage = cmdparams_get_int (&cmdparams, "h", NULL);
00144 if (usage)
00145 {
00146 printf ("Usage:\njsoc_info {-h} "
00147 " details are:\n"
00148 "op=<command> tell which ajax function to execute\n"
00149 "ds=<recordset query> as <series>{[record specifier]} - required\n"
00150 "seg=<list of segment names to append to dataset spec\n"
00151 "requestid=JSOC export request identifier\n"
00152 "process=string containing program and arguments\n"
00153 "requestor=name of requestor\n"
00154 "notify=email address of requestor\n"
00155 "shipto=mail address of requestor\n"
00156 "protocol=exported file protocol\n"
00157 "filenamefmt=exported file filename format\n"
00158 "format=return content type\n"
00159 "method=return method\n"
00160 "userhandle=unique session id\n"
00161 "h=help - show usage\n"
00162 "QUERY_STRING=AJAX query from the web"
00163 );
00164 return(1);
00165 }
00166 return (0);
00167 }
00168
00169 char *json_text_to_string(char *in)
00170 {
00171 char *o, *new = (char *)malloc(strlen(in)+1);
00172 char *i;
00173 for (i=in, o=new; *i; )
00174 {
00175 if (*i == '\\')
00176 {
00177 i++;
00178 if (*i == '/' || *i == '"' || *i == '\\' )
00179 { *o++ = *i++; continue;}
00180 else if (*i == 'b')
00181 { *o++ = '\b'; i++; continue;}
00182 else if (*i == 'f')
00183 { *o++ = '\f'; i++; continue;}
00184 else if (*i == 'r')
00185 { *o++ = '\r'; i++; continue;}
00186 else if (*i == 't')
00187 { *o++ = '\t'; i++; continue;}
00188 else if (*i == 'n')
00189 { *o++ = '\n'; i++; continue;}
00190
00191 }
00192 *o++ = *i++;
00193 }
00194 *o = '\0';
00195 return(new);
00196 }
00197
00198 char *string_to_json(char *in)
00199 {
00200 char *new;
00201 new = json_escape(in);
00202 return(new);
00203 }
00204
00205 manage_userhandle(int register_handle, const char *handle)
00206 {
00207 if (register_handle)
00208 {
00209 }
00210 else if (handle && *handle)
00211 {
00212 }
00213 }
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 int quick_export_rs( json_t *jroot, DRMS_RecordSet_t *rs, int online, long long size)
00229 {
00230 char numval[200];
00231 char query[DRMS_MAXQUERYLEN];
00232 char record[DRMS_MAXQUERYLEN];
00233 char segpath[DRMS_MAXPATHLEN];
00234 int i;
00235 int count = 0;
00236 int rcount = rs->n;
00237 json_t *data;
00238 DRMS_Record_t *rec;
00239 data = json_new_array();
00240 count = 0;
00241 for (i=0; i < rcount; i++)
00242 {
00243 DRMS_Segment_t *seg;
00244 HIterator_t *hit = NULL;
00245 rec = rs->records[i];
00246 drms_sprint_rec_query(query, rec);
00247 while (seg = drms_record_nextseg(rec, &hit, 1))
00248 {
00249 DRMS_Record_t *segrec;
00250 json_t *recobj = json_new_object();
00251 char *jsonstr;
00252 segrec = seg->record;
00253 count += 1;
00254 strcpy(record, query);
00255 strcat(record, "{");
00256 strcat(record, seg->info->name);
00257 strcat(record, "}");
00258 drms_record_directory(segrec, segpath, online);
00259 drms_segment_filename(seg, segpath);
00260 jsonstr = string_to_json(record);
00261 json_insert_pair_into_object(recobj, "record", json_new_string(jsonstr));
00262 free(jsonstr);
00263 jsonstr = string_to_json(segpath);
00264 json_insert_pair_into_object(recobj, "filename", json_new_string(jsonstr));
00265 free(jsonstr);
00266 json_insert_child(data, recobj);
00267 }
00268 free(hit);
00269 }
00270 if (jroot)
00271 {
00272 sprintf(numval, "%d", rcount);
00273 json_insert_pair_into_object(jroot, "rcount", json_new_number(numval));
00274 sprintf(numval, "%d", count);
00275 json_insert_pair_into_object(jroot, "count", json_new_number(numval));
00276 sprintf(numval, "%d", (int)size);
00277 json_insert_pair_into_object(jroot, "size", json_new_number(numval));
00278 json_insert_pair_into_object(jroot, "dir", json_new_string(""));
00279 json_insert_pair_into_object(jroot, "data", data);
00280 }
00281 else
00282 {
00283 json_t *recobj = data->child;
00284 printf("rcount=%d\n", rcount);
00285 printf("count=%d\n", count);
00286 printf("size=%lld\n", size);
00287 printf("dir=/\n");
00288 printf("# DATA\n");
00289 while (recobj)
00290 {
00291 char *ascii_query, *ascii_path;
00292 json_t *record = recobj->child;
00293 json_t *filename = record->next;
00294 json_t *recquery = record->child;
00295 json_t *pathname = filename->child;
00296 ascii_query = json_text_to_string(recquery->text);
00297 ascii_path = json_text_to_string(pathname->text);
00298 printf("%s\t%s\n",ascii_query, ascii_path);
00299 free(ascii_query);
00300 free(ascii_path);
00301 recobj = recobj->next;
00302 }
00303 }
00304 return(count);
00305 }
00306
00307 TIME timenow()
00308 {
00309
00310
00311 TIME now = CURRENT_SYSTEM_TIME;
00312 return(now);
00313 }
00314
00315 static void CleanUp(int64_t **psunumarr, SUM_info_t ***infostructs, char **webarglist, char ***series, char ***paths, char ***susize, int arrsize, const char *userhandle)
00316 {
00317 int iarr;
00318
00319 if (psunumarr && *psunumarr)
00320 {
00321 free(*psunumarr);
00322 *psunumarr = NULL;
00323 }
00324
00325 if (infostructs && *infostructs)
00326 {
00327 free(*infostructs);
00328 *infostructs = NULL;
00329 }
00330
00331 if (webarglist && *webarglist)
00332 {
00333 free(*webarglist);
00334 *webarglist = NULL;
00335 }
00336
00337 if (series && *series)
00338 {
00339 for (iarr = 0; iarr < arrsize; iarr++)
00340 {
00341 if ((*series)[iarr])
00342 {
00343 free((*series)[iarr]);
00344 (*series)[iarr] = NULL;
00345 }
00346 }
00347
00348 free(*series);
00349 *series = NULL;
00350 }
00351
00352 if (paths && *paths)
00353 {
00354 for (iarr = 0; iarr < arrsize; iarr++)
00355 {
00356 if ((*paths)[iarr])
00357 {
00358 free((*paths)[iarr]);
00359 (*paths)[iarr] = NULL;
00360 }
00361 }
00362
00363 free(*paths);
00364 *paths = NULL;
00365 }
00366
00367 if (susize && *susize)
00368 {
00369 for (iarr = 0; iarr < arrsize; iarr++)
00370 {
00371 if ((*susize)[iarr])
00372 {
00373 free((*susize)[iarr]);
00374 (*susize)[iarr] = 0;
00375 }
00376 }
00377
00378 free(*susize);
00379 *susize = NULL;
00380 }
00381
00382 if (userhandle && *userhandle)
00383 manage_userhandle(0, userhandle);
00384
00385 hcon_destroy(&gLogs);
00386 }
00387
00388
00389
00390
00391
00392
00393
00394
00395 #define JSONDIE(msg) {die(dojson,msg,"","4",&sunumarr,&infostructs,&webarglist,&series,&paths,&susize,arrsize,userhandle);return(1);}
00396 #define JSONDIE2(msg,info) {die(dojson,msg,info,"4",&sunumarr,&infostructs,&webarglist,&series,&paths,&susize,arrsize,userhandle);return(1);}
00397 #define JSONDIE3(msg,info) {die(dojson,msg,info,"6",&sunumarr,&infostructs,&webarglist,&series,&paths,&susize,arrsize,userhandle);return(1);}
00398
00399 int fileupload = 0;
00400 static int gGenWebPage = 1;
00401
00402 int die(int dojson, char *msg, char *info, char *stat, int64_t **psunumarr, SUM_info_t ***infostructs, char **webarglist,
00403 char ***series, char ***paths, char ***susize, int arrsize, const char *userhandle)
00404 {
00405 char *msgjson;
00406 char *json;
00407 char message[10000];
00408 json_t *jroot = json_new_object();
00409 if (DEBUG) fprintf(stderr,"%s%s\n",msg,info);
00410 strcpy(message,msg);
00411 strcat(message,info);
00412 if (dojson)
00413 {
00414 msgjson = string_to_json(message);
00415 json_insert_pair_into_object(jroot, "status", json_new_number(stat));
00416 json_insert_pair_into_object(jroot, "error", json_new_string(msgjson));
00417 json_tree_to_string(jroot,&json);
00418
00419 if (gGenWebPage)
00420 {
00421 if (fileupload)
00422 printf("Content-type: text/html\n\n");
00423 else
00424 printf("Content-type: application/json\n\n");
00425 }
00426
00427 printf("%s\n",json);
00428 }
00429 else
00430 {
00431 if (gGenWebPage)
00432 {
00433 printf("Content-type: text/plain\n\n");
00434 }
00435
00436 printf("status=%s\nerror=%s\n", stat, message);
00437 }
00438 fflush(stdout);
00439
00440 CleanUp(psunumarr, infostructs, webarglist, series, paths, susize, arrsize, userhandle);
00441
00442 return(1);
00443 }
00444
00445 static int JsonCommitFn(DRMS_Record_t **exprec,
00446 int ro,
00447 int dojson,
00448 char *msg,
00449 char *info,
00450 char *stat,
00451 int64_t **psunumarr,
00452 SUM_info_t ***infostructs,
00453 char **webarglist,
00454 char ***series,
00455 char ***paths,
00456 char ***susize,
00457 int arrsize,
00458 const char *userhandle)
00459 {
00460 int rv = 1;
00461
00462
00463 die(dojson, msg, "", "4", psunumarr, infostructs, webarglist, series, paths, susize, arrsize, userhandle);
00464
00465 if (exprec && *exprec)
00466 {
00467 if (ro)
00468 {
00469 drms_close_record(*exprec, DRMS_FREE_RECORD);
00470 }
00471 else
00472 {
00473 if (drms_setkey_int(*exprec, "Status", 4))
00474 {
00475 drms_close_record(*exprec, DRMS_FREE_RECORD);
00476 rv = 1;
00477 }
00478 else
00479 {
00480
00481 drms_setkey_string(*exprec, "errmsg", msg);
00482 drms_close_record(*exprec, DRMS_INSERT_RECORD);
00483 rv = 0;
00484 }
00485 }
00486
00487 *exprec = NULL;
00488 }
00489
00490 return rv;
00491 }
00492
00493 #define JSONCOMMIT(msg,rec,ro) {return JsonCommitFn(rec, ro, dojson, msg, "", "4", &sunumarr, &infostructs, &webarglist, &series, &paths, &susize, arrsize, userhandle);};
00494
00495
00496 static int send_file(DRMS_Record_t *rec, int segno, char *pathret, int size)
00497 {
00498 DRMS_Segment_t *seg = drms_segment_lookupnum(rec, 0);
00499 char path[DRMS_MAXPATHLEN];
00500 char sudir[DRMS_MAXPATHLEN];
00501 FILE *fp;
00502 int b;
00503
00504 drms_record_directory(rec,sudir,0);
00505 strcpy(path, "/web/jsoc/htdocs");
00506 strncat(path, sudir, DRMS_MAXPATHLEN);
00507 strncat(path, "/", DRMS_MAXPATHLEN);
00508 strncat(path, seg->filename, DRMS_MAXPATHLEN);
00509
00510 if (pathret)
00511 {
00512 snprintf(pathret, size, "%s", path);
00513 }
00514
00515
00516 fp = fopen(path, "r");
00517 if (!fp)
00518 return 1;
00519 switch (seg->info->protocol)
00520 {
00521 case DRMS_FITS:
00522 printf("Content-Type: application/fits\n\n");
00523 break;
00524 default:
00525 printf("Content-Type: application/binary\n\n");
00526
00527
00528
00529
00530 }
00531 while ((b = fgetc(fp))!= EOF)
00532 fputc(b, stdout);
00533 fclose(fp);
00534 fflush(stdout);
00535 return(0);
00536 }
00537
00538
00539 char *illegalArg(char *arg)
00540 {
00541 int n_singles = 0;
00542 char *p;
00543 if (index(arg, ';'))
00544 return("';' not allowed");
00545 for (p=arg; *p; p++)
00546 if (*p == '\'')
00547 {
00548 n_singles++;
00549 *p = '"';
00550 }
00551 if (n_singles & 1)
00552 return("Unbalanced \"'\" not allowed.");
00553 return(NULL);
00554 }
00555
00556 static int SetWebArg(Q_ENTRY *req, const char *key, char **arglist, size_t *size)
00557 {
00558 char *value = NULL;
00559 char buf[1024];
00560 if (req)
00561 {
00562 value = (char *)qEntryGetStr(req, key);
00563 if (value)
00564 {
00565 char *arg_bad = illegalArg(value);
00566 if (arg_bad)
00567 {
00568
00569
00570
00571
00572 die(dojson, "Illegal text in arg: ", arg_bad, "4", NULL, NULL, arglist, NULL, NULL, NULL, 0, NULL);
00573 return(1);
00574 }
00575
00576 if (!cmdparams_set(&cmdparams, key, value))
00577 {
00578
00579
00580
00581
00582 die(dojson, "CommandLine Error", "", "4", NULL, NULL, arglist, NULL, NULL, NULL, 0, NULL);
00583 return(1);
00584 }
00585
00586
00587
00588 snprintf(buf, sizeof(buf), "%s='%s' ", key, value);
00589 *arglist = base_strcatalloc(*arglist, buf, size);
00590 }
00591 }
00592 return(0);
00593 }
00594
00595 static int SetWebFileArg(Q_ENTRY *req, const char *key, char **arglist, size_t *size)
00596 {
00597 int len;
00598 char keyname[100], length[20];
00599 SetWebArg(req, key, arglist, size);
00600 sprintf(keyname, "%s.length", key);
00601 len = qEntryGetInt(req, keyname);
00602 sprintf(length, "%d", len);
00603 cmdparams_set(&cmdparams, keyname, length);
00604 sprintf(keyname, "%s.filename", key);
00605 SetWebArg(req, keyname, arglist, size);
00606 sprintf(keyname, "%s.contenttype", key);
00607 SetWebArg(req, keyname, arglist, size);
00608 return(0);
00609 }
00610
00611
00612 static int AcquireLock(int fd)
00613 {
00614 int ret = -1;
00615 int natt = 0;
00616
00617 while ((ret = lockf(fd, F_TLOCK, 0)) != 0 && natt < 10)
00618 {
00619
00620 sleep(1);
00621 natt++;
00622 }
00623
00624 return (ret == 0);
00625 }
00626
00627 static void ReleaseLock(int fd)
00628 {
00629 lockf(fd, F_ULOCK, 0);
00630 }
00631
00632 static void FreeLogs(void *val)
00633 {
00634 FILE **pfptr = (FILE **)val;
00635
00636 if (pfptr && *pfptr)
00637 {
00638 fflush(*pfptr);
00639 fchmod(fileno(*pfptr), S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
00640 fclose(*pfptr);
00641 *pfptr = NULL;
00642 }
00643 }
00644
00645 static void LocalTime(char *buf, int sz)
00646 {
00647 time_t sounnecessarilycomplicated;
00648 struct tm *ltime = NULL;
00649
00650 time(&sounnecessarilycomplicated);
00651 ltime = localtime(&sounnecessarilycomplicated);
00652
00653 *buf = '\0';
00654 if (ltime)
00655 {
00656 snprintf(buf, sz, "%s", asctime(ltime));
00657 }
00658 }
00659
00660 static void WriteLog(const char *logpath, const char *format, ...)
00661 {
00662 FILE *fptr = NULL;
00663 FILE **pfptr = NULL;
00664 int lockfd;
00665 struct stat stbuf;
00666 int mustchmodlck = 0;
00667 int mustchmodlog = 0;
00668
00669 if (stat(kLockFile, &stbuf) != 0)
00670 {
00671
00672
00673 return;
00674 }
00675 else
00676 {
00677 if ((stbuf.st_mode & (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) != (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH))
00678 mustchmodlck = 1;
00679 }
00680
00681 if (stat(logpath, &stbuf) == 0)
00682 {
00683 if ((stbuf.st_mode & (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) != (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH))
00684 {
00685 mustchmodlog = 1;
00686 }
00687 }
00688 else
00689 {
00690
00691 char *dname = NULL;
00692 char *path = strdup(logpath);
00693
00694 if (path)
00695 {
00696 dname = dirname(path);
00697 if (dname)
00698 {
00699 if (stat(dname, &stbuf) != 0)
00700 {
00701
00702 return;
00703 }
00704 }
00705 else
00706 {
00707 return;
00708 }
00709
00710 free(path);
00711 }
00712 else
00713 {
00714 fprintf(stderr, "Out of memory.\n");
00715 return;
00716 }
00717 }
00718
00719 if (!gLogs)
00720 {
00721 gLogs = hcon_create(sizeof(FILE *), 128, (void(*)(const void *value))FreeLogs, NULL, NULL, NULL, 0);
00722
00723 if (gLogs)
00724 {
00725
00726 hcon_insert(gLogs, kLogFileSumm, &fptr);
00727 hcon_insert(gLogs, kLogFileExpSuInt, &fptr);
00728 hcon_insert(gLogs, kLogFileExpSuExt, &fptr);
00729 hcon_insert(gLogs, kLogFileExpReqInt, &fptr);
00730 hcon_insert(gLogs, kLogFileExpReqExt, &fptr);
00731 hcon_insert(gLogs, kLogFileExpStatInt, &fptr);
00732 hcon_insert(gLogs, kLogFileExpStatExt, &fptr);
00733 }
00734 else
00735 {
00736 fprintf(stderr, "Out of memory.\n");
00737 return;
00738 }
00739 }
00740
00741 pfptr = hcon_lookup(gLogs, logpath);
00742
00743 if (pfptr)
00744 {
00745
00746 lockfd = open(kLockFile, O_WRONLY | O_CREAT, S_IRWXU | S_IRWXG);
00747 if (lockfd >= 0)
00748 {
00749 if (AcquireLock(lockfd))
00750 {
00751 if (!*pfptr)
00752 {
00753 *pfptr = fopen(logpath, "a");
00754 }
00755
00756 if (*pfptr)
00757 {
00758
00759 va_list ap;
00760
00761 va_start(ap, format);
00762 vfprintf(*pfptr, format, ap);
00763 va_end(ap);
00764
00765 if (mustchmodlog)
00766 {
00767 fchmod(fileno(*pfptr), S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
00768 }
00769 }
00770 else
00771 {
00772 fprintf(stderr, "Unable to open log file for writing: %s.\n", logpath);
00773 }
00774
00775 ReleaseLock(lockfd);
00776 }
00777 else
00778 {
00779 fprintf(stderr, "Unable to acquire lock on %s.\n", kLockFile);
00780 }
00781
00782 if (mustchmodlck)
00783 {
00784 fchmod(lockfd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
00785 }
00786 close(lockfd);
00787 }
00788 else
00789 {
00790 fprintf(stderr, "Unable to open lock file for writing: %s.\n", kLockFile);
00791 }
00792 }
00793 else
00794 {
00795 fprintf(stderr, "Invalid log-file path %s.\n", logpath);
00796 }
00797 }
00798
00799 void json_insert_runtime(json_t *jroot, double StartTime)
00800 {
00801 char runtime[100];
00802 double EndTime;
00803 struct timeval thistv;
00804 gettimeofday(&thistv, NULL);
00805 EndTime = thistv.tv_sec + thistv.tv_usec/1000000.0;
00806 sprintf(runtime,"%0.3f",EndTime - StartTime);
00807 json_insert_pair_into_object(jroot, "runtime", json_new_number(runtime));
00808 }
00809
00810
00811 static void report_summary(const char *host,
00812 double StartTime,
00813 const char *remote_IP,
00814 const char *op,
00815 const char *ds,
00816 int n,
00817 int internal,
00818 int status)
00819 {
00820 double EndTime;
00821 struct timeval thistv;
00822 char *logfile = NULL;
00823 char localnowtxt[128];
00824
00825 gettimeofday(&thistv, NULL);
00826 EndTime = thistv.tv_sec + thistv.tv_usec/1000000.0;
00827
00828 logfile = kLogFileSumm;
00829
00830 LocalTime(localnowtxt, sizeof(localnowtxt));
00831
00832 WriteLog(logfile, "*****%s\n", localnowtxt);
00833 WriteLog(logfile, "host='%s'\t",host);
00834 WriteLog(logfile, "lag=%0.3f\t",EndTime - StartTime);
00835 WriteLog(logfile, "IP='%s'\t",remote_IP);
00836 WriteLog(logfile, "op='%s'\t",op);
00837 WriteLog(logfile, "ds='%s'\t",ds);
00838 WriteLog(logfile, "n=%d\t",n);
00839 WriteLog(logfile, "status=%d\n",status);
00840 }
00841
00842 static void LogReqInfo(const char *fname,
00843 long long instanceID,
00844 int fileupload,
00845 const char *op,
00846 const char *dsin,
00847 const char *requestid,
00848 const char *dbhost,
00849 int from_web,
00850 const char *webarglist,
00851 TIME fetch_time)
00852 {
00853
00854
00855
00856
00857 char nowtxt[100];
00858 char localnowtxt[128];
00859
00860 sprint_ut(nowtxt, fetch_time);
00861 LocalTime(localnowtxt, sizeof(localnowtxt));
00862
00863 WriteLog(fname, "**********************\n");
00864 WriteLog(fname, "%s\n CGI Instance=%lld\n PID=%d\n %s\n op=%s\n in=%s\n RequestID=%s\n DBHOST=%s\n REMOTE_ADDR=%s\n", localnowtxt, instanceID, getpid(), nowtxt, op, dsin, requestid, dbhost, getenv("REMOTE_ADDR"));
00865 if (fileupload)
00866 {
00867 char *file = (char *)cmdparams_get_str (&cmdparams, kArgFile, NULL);
00868 int filesize = cmdparams_get_int (&cmdparams, kArgFile".length", NULL);
00869 char *filename = (char *)cmdparams_get_str (&cmdparams, kArgFile".filename", NULL);
00870 WriteLog(fname," UploadFile: size=%d, name=%s, contents=%s\n",filesize,filename,file);
00871 }
00872
00873
00874 if (from_web && strlen(webarglist) > 0)
00875 {
00876 int rlsize = strlen(webarglist) * 2;
00877 char *rlbuf = malloc(rlsize);
00878 memset(rlbuf, 0, rlsize);
00879 const char *pwa = webarglist;
00880 char *prl = rlbuf;
00881
00882
00883
00884
00885 while (*pwa && (prl - rlbuf < rlsize - 1))
00886 {
00887 if (*pwa == '%')
00888 {
00889 *prl = '%';
00890 prl++;
00891 }
00892
00893 *prl = *pwa;
00894 pwa++;
00895 prl++;
00896 }
00897
00898 *prl = '\0';
00899
00900 WriteLog(fname, "** HTTP POST arguments:\n");
00901 WriteLog(fname, rlbuf);
00902 WriteLog(fname, "\n");
00903 free(rlbuf);
00904 }
00905
00906 WriteLog(fname, "**********************\n");
00907 }
00908
00909 static int sunumComp(const void *val1, const void *val2)
00910 {
00911 long long sunum1;
00912 long long sunum2;
00913
00914 if (val1)
00915 {
00916 sunum1 = *((long long *)val1);
00917 }
00918 else
00919 {
00920 sunum1 = -1;
00921 }
00922
00923 if (val2)
00924 {
00925 sunum2 = *((long long *)val2);
00926 }
00927 else
00928 {
00929 sunum2 = -1;
00930 }
00931
00932 return (sunum1 < sunum2) ? -1 : (sunum1 > sunum2 ? 1 : 0);
00933 }
00934
00935 int JFMin(int val, int maxVal)
00936 {
00937 if (val > maxVal)
00938 {
00939 return maxVal;
00940 }
00941 else
00942 {
00943 return val;
00944 }
00945 }
00946
00947
00948 int dieRoll(int range)
00949 {
00950 int randVal;
00951
00952 srand(time(NULL));
00953 randVal = rand();
00954
00955
00956
00957
00958
00959
00960
00961
00962 return JFMin((int)floor(((double)randVal / RAND_MAX) * range) + 1, range);
00963 }
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983 static char *GetExistReqID(DRMS_Env_t *env, const char *md5, int window, TIME *timeToCompletion, int *expSize)
00984 {
00985 char *id = NULL;
00986 char cmd[DRMS_MAXQUERYLEN];
00987 DB_Text_Result_t *tres = NULL;
00988 DB_Text_Result_t *tresInner = NULL;
00989 int istat;
00990 char *end = NULL;
00991 long long status;
00992 long long sunum;
00993 SUM_info_t *infostruct = NULL;
00994
00995 istat = DRMS_SUCCESS;
00996
00997 *timeToCompletion = DRMS_MISSING_TIME;
00998 *expSize = 0;
00999
01000
01001 snprintf(cmd, sizeof(cmd), "DELETE FROM jsoc.export_md5 WHERE exporttime + interval '%d hours' <= statement_timestamp()", window);
01002 if (drms_dms(drms_env->session, NULL, cmd))
01003 {
01004 fprintf(stderr, "Failure deleting expired recent export md5s: %s.\n", cmd);
01005 istat = DRMS_ERROR_BADDBQUERY;
01006 }
01007
01008
01009 if (istat == DRMS_SUCCESS)
01010 {
01011 snprintf(cmd, sizeof(cmd), "SELECT requestid FROM jsoc.export_md5 WHERE md5 = '%s'", md5);
01012
01013 if ((tres = drms_query_txt(drms_env->session, cmd)) != NULL)
01014 {
01015 if (tres->num_rows == 1)
01016 {
01017 if (tres->num_cols == 1)
01018 {
01019 id = strdup(tres->field[0][0]);
01020
01021
01022
01023
01024 snprintf(cmd, sizeof(cmd), "SELECT status, esttime, size, sunum FROM jsoc.export T2 WHERE recnum = (SELECT max(recnum) AS recnum FROM jsoc.export T1 WHERE T1.requestid = '%s')", id);
01025
01026 if ((tresInner = drms_query_txt(drms_env->session, cmd)) == NULL)
01027 {
01028 fprintf(stderr, "Failure obtaining estimated completion time and size: %s.\n", cmd);
01029 istat = DRMS_ERROR_BADDBQUERY;
01030 }
01031 else
01032 {
01033 if (tresInner->num_rows == 1 && tresInner->num_cols == 4)
01034 {
01035 status = strtoll(tresInner->field[0][0], &end, 10);
01036
01037 if (end != tresInner->field[0][0] && (status == 0 || status == 1 || status == 2 || status == 12))
01038 {
01039
01040 sunum = strtoll(tresInner->field[0][3], &end, 10);
01041
01042 if (end != tresInner->field[0][3] && sunum >= 0 && sunum != LLONG_MAX)
01043 {
01044
01045
01046
01047
01048 status = drms_getsuinfo(env, &sunum, 1, &infostruct);
01049
01050 if (status == DRMS_SUCCESS && infostruct)
01051 {
01052 if (*(infostruct->online_loc) != '\0' && *(infostruct->online_status) == 'Y')
01053 {
01054
01055 *timeToCompletion = strtod(tresInner->field[0][1], &end);
01056
01057 if (end == tresInner->field[0][1] || *timeToCompletion == HUGE_VAL || *timeToCompletion == -HUGE_VAL)
01058 {
01059 *timeToCompletion = DRMS_MISSING_TIME;
01060 }
01061
01062 *expSize = strtoll(tresInner->field[0][2], &end, 10);
01063
01064 if (end == tresInner->field[0][2] || *expSize < INT_MIN || *expSize > INT_MAX)
01065 {
01066 *expSize = DRMS_MISSING_INT;
01067 }
01068 }
01069 }
01070 else
01071 {
01072
01073
01074 }
01075
01076 if (infostruct)
01077 {
01078 free(infostruct);
01079 infostruct = NULL;
01080 }
01081 }
01082 }
01083 else
01084 {
01085
01086 istat = DRMS_ERROR_BADDBQUERY;
01087 }
01088 }
01089 else
01090 {
01091
01092
01093 istat = DRMS_ERROR_BADDBQUERY;
01094 }
01095
01096 if (tresInner)
01097 {
01098 db_free_text_result(tresInner);
01099 tresInner = NULL;
01100 }
01101 }
01102
01103 if (istat != DRMS_SUCCESS)
01104 {
01105 if (id)
01106 {
01107 free(id);
01108 id = NULL;
01109 }
01110 }
01111 }
01112 else
01113 {
01114 istat = DRMS_ERROR_BADDBQUERY;
01115 }
01116
01117 if (istat != DRMS_SUCCESS)
01118 {
01119
01120
01121
01122 snprintf(cmd, sizeof(cmd), "DELETE FROM jsoc.export_md5 WHERE md5 = '%s'", md5);
01123 if (drms_dms(drms_env->session, NULL, cmd))
01124 {
01125 fprintf(stderr, "Failure deleting invalid recent export md5: %s.\n", cmd);
01126 }
01127 }
01128 }
01129 else if (tres->num_rows != 0)
01130 {
01131
01132 istat = DRMS_ERROR_BADDBQUERY;
01133 }
01134 else
01135 {
01136
01137
01138
01139 }
01140
01141 db_free_text_result(tres);
01142 tres = NULL;
01143 }
01144 else
01145 {
01146 istat = DRMS_ERROR_BADDBQUERY;
01147 }
01148
01149 if (istat == DRMS_ERROR_BADDBQUERY)
01150 {
01151 fprintf(stderr, "Unexpected result returned from DB query: %s.\n", cmd);
01152 }
01153 }
01154
01155 return id;
01156 }
01157
01158 static int CheckEmailAddress(const char *logfile, const char *requestor, const char *notify, char *dieStr, int sz)
01159 {
01160
01161 int rv = 0;
01162 char realAddress[512] = {0};
01163
01164 if (strcmp(requestor, kNotSpecified) != 0 && strncasecmp(notify, "solarmail", 9) == 0)
01165 {
01166 snprintf(realAddress, sizeof(realAddress), "%s@spd.aas.org", requestor);
01167 }
01168 else
01169 {
01170 if (strcmp(notify, kNotSpecified) != 0)
01171 {
01172 snprintf(realAddress, sizeof(realAddress), "%s", notify);
01173 }
01174 }
01175
01176
01177 if (*realAddress == '\0')
01178 {
01179
01180 snprintf(dieStr, sz, "Email address for notification was not specfied. It is required.");
01181 rv = 1;
01182 }
01183
01184
01185 char caCmd[PATH_MAX];
01186 char caMsg[1024];
01187 FILE *caFptr = NULL;
01188 int res;
01189
01190
01191
01192
01193 snprintf(caCmd, sizeof(caCmd), "unset REQUEST_METHOD; unset QUERY_STRING; %s %s/checkAddress.py address=%s'&'checkonly=1'&'addresstab=jsoc.export_addresses'&'domaintab=jsoc.export_addressdomains'&'dbuser=apache", BIN_PY, SCRIPTS_EXPORT, realAddress);
01194 WriteLog(logfile, "Calling checkAddress.py: %s\n", caCmd);
01195 caFptr = popen(caCmd, "r");
01196
01197 if (caFptr)
01198 {
01199
01200 jsmn_parser parser;
01201 jsmntok_t *tokens = NULL;
01202 size_t szjstokens = 512;
01203 char rbuf[512];
01204 size_t nbytes;
01205 size_t ntot = 0;
01206 size_t szjson = 1024;
01207 char *json = NULL;
01208 int itok;
01209 int itchar;
01210 char *tok = NULL;
01211 size_t szTok;
01212 int statusTok = -1;
01213 int msgTok = -1;
01214 char *endptr = NULL;
01215 long long caStatus;
01216 char *caMsg = NULL;
01217 char tChar[2];
01218
01219 json = calloc(1, szjson);
01220
01221 if (json)
01222 {
01223 while ((nbytes = fread(rbuf, sizeof(char), sizeof(rbuf) - 1, caFptr)) > 0)
01224 {
01225 rbuf[nbytes] = '\0';
01226 ntot += nbytes;
01227 json = base_strcatalloc(json, rbuf, &szjson);
01228 }
01229
01230 tokens = calloc(1, sizeof(jsmntok_t) * szjstokens);
01231
01232 if (tokens)
01233 {
01234 jsmn_init(&parser);
01235 res = jsmn_parse(&parser, json, tokens, szjstokens);
01236
01237 if (res == JSMN_ERROR_NOMEM || res == JSMN_ERROR_INVAL || res == JSMN_ERROR_PART)
01238 {
01239
01240
01241 pclose(caFptr);
01242 caFptr = NULL;
01243
01244 snprintf(dieStr, sz, "Unexpected response from checkAddress.py.");
01245 rv = 1;
01246 }
01247 else if (res != JSMN_SUCCESS)
01248 {
01249
01250 pclose(caFptr);
01251 caFptr = NULL;
01252
01253 snprintf(dieStr, sz, "Failure parsing JSON.");
01254 rv = 1;
01255 }
01256
01257
01258
01259
01260
01261
01262
01263
01264 for (itok = 1; itok <= tokens[0].size; itok++)
01265 {
01266 szTok = 128;
01267
01268 tok = calloc(1, szTok);
01269
01270 if (!tok)
01271 {
01272 pclose(caFptr);
01273 caFptr = NULL;
01274
01275 snprintf(dieStr, sz, "Out of memory.");
01276 rv = 1;
01277 }
01278
01279 tChar[1] = '\0';
01280 for (itchar = tokens[itok].start; itchar < tokens[itok].end; itchar++)
01281 {
01282 tChar[0] = json[itchar];
01283 tok = base_strcatalloc(tok, (char *)&tChar, &szTok);
01284 }
01285
01286 if (*tok)
01287 {
01288 if (statusTok != -1)
01289 {
01290
01291 caStatus = strtoll(tok, &endptr, 10);
01292 if (tok == endptr)
01293 {
01294
01295 pclose(caFptr);
01296 caFptr = NULL;
01297
01298 snprintf(dieStr, sz, "Bad status code returned from checkAddress.py.");
01299 rv = 1;
01300 }
01301
01302 statusTok = -1;
01303 }
01304
01305 if (msgTok != -1)
01306 {
01307
01308 caMsg = strdup(tok);
01309 msgTok = -1;
01310 }
01311
01312 if (strcasecmp(tok, "status") == 0)
01313 {
01314 statusTok = itok + 1;
01315 }
01316 else if (strcasecmp(tok, "msg") == 0)
01317 {
01318 msgTok = itok + 1;
01319 }
01320 }
01321
01322 free(tok);
01323 }
01324
01325 free(tokens);
01326 tokens = NULL;
01327 }
01328
01329 free(json);
01330 json = NULL;
01331 }
01332
01333 WriteLog(logfile, "checkAddress.py returned status: %lld\n", caStatus);
01334 if (caStatus != 2)
01335 {
01336
01337 if (caMsg)
01338 {
01339
01340 snprintf(dieStr, sz, "Cannot process your request. %s", caMsg);
01341 rv = 3;
01342 }
01343 else
01344 {
01345
01346 snprintf(dieStr, sz, "Cannot process your request. Your notification email address has not been registered.");
01347 rv = 3;
01348 }
01349 }
01350
01351 if (caMsg)
01352 {
01353 free(caMsg);
01354 caMsg = NULL;
01355 }
01356
01357 pclose(caFptr);
01358 caFptr = NULL;
01359 }
01360 else
01361 {
01362
01363 snprintf(dieStr, sz, "Unable to call checkAddress.py.");
01364 rv = 1;
01365 }
01366
01367 return rv;
01368 }
01369
01370
01371 int DoIt(void)
01372 {
01373
01374 const char *op;
01375 const char *dsin;
01376 const char *seglist;
01377 const char *requestid = NULL;
01378 const char *process;
01379 const char *requestor;
01380 int requestorid;
01381 const char *notify;
01382 const char *format;
01383 const char *formatvar;
01384 const char *shipto;
01385 const char *method;
01386 const char *protocol;
01387 const char *filenamefmt;
01388 const char *userhandle;
01389 float sizeRatio;
01390 const char *Server;
01391 const char *Remote_Address;
01392 char dbhost[DRMS_MAXHOSTNAME];
01393 int testmode = 0;
01394 int passthrough = 0;
01395 int genWebPage = 1;
01396 char *errorreply;
01397 int64_t *sunumarr = NULL;
01398 int nsunums;
01399 long long size;
01400 int rcount = 0;
01401 int rcountlimit = 0;
01402 TIME reqtime;
01403 TIME esttime;
01404 TIME fetch_time = timenow();
01405 double waittime;
01406 char *web_query;
01407 int from_web,status;
01408 int dodataobj=1, dojson=1, dotxt=0, dohtml=0, doxml=0;
01409 DRMS_RecordSet_t *exports;
01410 DRMS_Record_t *exprec = NULL;
01411 char new_requestid[200];
01412 char status_query[1000];
01413 char *export_series;
01414 char msgbuf[128];
01415 SUM_info_t **infostructs = NULL;
01416 char *webarglist = NULL;
01417 size_t webarglistsz;
01418 struct timeval thistv;
01419 double StartTime;
01420 long long instanceID = -1;
01421
01422
01423
01424 char **paths = NULL;
01425 char **series = NULL;
01426 char *sustatus = NULL;
01427 char **susize = NULL;
01428 int arrsize = -1;
01429
01430 int postorget = 0;
01431 int insertexprec = 1;
01432
01433 if (getenv("REQUEST_METHOD"))
01434 {
01435 postorget = (strcasecmp(getenv("REQUEST_METHOD"), "POST") == 0 ||
01436 strcasecmp(getenv("REQUEST_METHOD"), "GET") == 0);
01437 }
01438
01439 if (nice_intro ()) return (0);
01440
01441 gettimeofday(&thistv, NULL);
01442 StartTime = thistv.tv_sec + thistv.tv_usec/1000000.0;
01443 web_query = strdup (cmdparams_get_str (&cmdparams, "QUERY_STRING", NULL));
01444 from_web = (strcmp (web_query, kNotSpecified) != 0) || postorget;
01445
01446 if (from_web)
01447 {
01448
01449 char *qs = getenv("QUERY_STRING");
01450 if (qs)
01451 {
01452 WriteLog(kLogFileExpReqExt, "QUERY_STRING is %s.\n", qs);
01453 }
01454
01455 Q_ENTRY *req = NULL;
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472 if (!getenv("QUERY_STRING"))
01473 {
01474
01475 if (!postorget)
01476 {
01477
01478 setenv("QUERY_STRING", web_query, 1);
01479
01480
01481 setenv("REQUEST_METHOD", "GET", 1);
01482 }
01483 }
01484
01485
01486
01487
01488
01489
01490 webarglistsz = 2048;
01491 webarglist = (char *)malloc(webarglistsz);
01492 *webarglist = '\0';
01493
01494 req = qCgiRequestParseQueries(NULL, NULL);
01495 if (req)
01496 {
01497
01498 SetWebArg(req, kArgOp, &webarglist, &webarglistsz);
01499 SetWebArg(req, kArgRequestid, &webarglist, &webarglistsz);
01500 SetWebArg(req, kArgDs, &webarglist, &webarglistsz);
01501 SetWebArg(req, kArgSunum, &webarglist, &webarglistsz);
01502 SetWebArg(req, kArgSeg, &webarglist, &webarglistsz);
01503 SetWebArg(req, kArgProcess, &webarglist, &webarglistsz);
01504 SetWebArg(req, kArgFormat, &webarglist, &webarglistsz);
01505 SetWebArg(req, kArgFormatvar, &webarglist, &webarglistsz);
01506 SetWebArg(req, kArgMethod, &webarglist, &webarglistsz);
01507 SetWebArg(req, kArgProtocol, &webarglist, &webarglistsz);
01508 SetWebArg(req, kArgFilenamefmt, &webarglist, &webarglistsz);
01509 SetWebArg(req, kArgRequestor, &webarglist, &webarglistsz);
01510 SetWebArg(req, kArgNotify, &webarglist, &webarglistsz);
01511 SetWebArg(req, kArgShipto, &webarglist, &webarglistsz);
01512 SetWebArg(req, kArgRequestorid, &webarglist, &webarglistsz);
01513 SetWebArg(req, kUserHandle, &webarglist, &webarglistsz);
01514 SetWebArg(req, kArgCgiInstance, &webarglist, &webarglistsz);
01515 SetWebArg(req, kArgSizeRatio, &webarglist, &webarglistsz);
01516 if (strncmp(cmdparams_get_str (&cmdparams, kArgDs, NULL),"*file*", 6) == 0);
01517 SetWebFileArg(req, kArgFile, &webarglist, &webarglistsz);
01518 SetWebArg(req, kArgTestmode, &webarglist, &webarglistsz);
01519 SetWebArg(req, kArgPassthrough, &webarglist, &webarglistsz);
01520 SetWebArg(req, kArgDontGenWebPage, &webarglist, &webarglistsz);
01521
01522 qEntryFree(req);
01523 }
01524 }
01525 free(web_query);
01526
01527
01528 op = cmdparams_get_str (&cmdparams, kArgOp, NULL);
01529 requestid = cmdparams_get_str (&cmdparams, kArgRequestid, NULL);
01530 dsin = cmdparams_get_str (&cmdparams, kArgDs, NULL);
01531 userhandle = cmdparams_get_str (&cmdparams, kUserHandle, NULL);
01532 sizeRatio = cmdparams_get_float(&cmdparams, kArgSizeRatio, NULL);
01533 Remote_Address = cmdparams_get_str(&cmdparams, "REMOTE_ADDR", NULL);
01534 Server = cmdparams_get_str(&cmdparams, "SERVER_NAME", NULL);
01535 instanceID = cmdparams_get_int(&cmdparams, kArgCgiInstance, NULL);
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545 nsunums = cmdparams_get_int64arr(&cmdparams, kArgSunum, &sunumarr, &status);
01546
01547 if (status != CMDPARAMS_SUCCESS)
01548 {
01549 snprintf(msgbuf, sizeof(msgbuf),
01550 "Invalid argument on entry, '%s=%s'.\n", kArgSunum, cmdparams_get_str(&cmdparams, kArgSunum, NULL));
01551 JSONDIE(msgbuf);
01552 }
01553
01554 seglist = cmdparams_get_str (&cmdparams, kArgSeg, NULL);
01555 process = cmdparams_get_str (&cmdparams, kArgProcess, NULL);
01556 format = cmdparams_get_str (&cmdparams, kArgFormat, NULL);
01557 formatvar = cmdparams_get_str (&cmdparams, kArgFormatvar, NULL);
01558 method = cmdparams_get_str (&cmdparams, kArgMethod, NULL);
01559 protocol = cmdparams_get_str (&cmdparams, kArgProtocol, NULL);
01560 filenamefmt = cmdparams_get_str (&cmdparams, kArgFilenamefmt, NULL);
01561 requestor = cmdparams_get_str (&cmdparams, kArgRequestor, NULL);
01562 notify = cmdparams_get_str (&cmdparams, kArgNotify, NULL);
01563 shipto = cmdparams_get_str (&cmdparams, kArgShipto, NULL);
01564 requestorid = cmdparams_get_int (&cmdparams, kArgRequestorid, NULL);
01565
01566 if (strlen(drms_env->session->db_handle->dbhost) > 0)
01567 {
01568 snprintf(dbhost, sizeof(dbhost), drms_env->session->db_handle->dbhost);
01569 }
01570 else
01571 {
01572 *dbhost = '\0';
01573 }
01574
01575 if (strcmp(userhandle, kNotSpecified) != 0)
01576 manage_userhandle(1, userhandle);
01577 else
01578 userhandle = "";
01579
01580 testmode = (TESTMODE || cmdparams_isflagset(&cmdparams, kArgTestmode));
01581 passthrough = cmdparams_isflagset(&cmdparams, kArgPassthrough);
01582 genWebPage = (cmdparams_isflagset(&cmdparams, kArgDontGenWebPage) == 0);
01583 gGenWebPage = genWebPage;
01584
01585 dodataobj = strcmp(formatvar, "dataobj") == 0;
01586 dojson = strcmp(format, "json") == 0;
01587 dotxt = strcmp(format, "txt") == 0;
01588 dohtml = strcmp(format, "html") == 0;
01589 doxml = strcmp(format, "xml") == 0;
01590
01591
01592
01593 if (strncmp(process, "n=", 2) == 0)
01594 {
01595 rcountlimit = atoi(process+2);
01596 }
01597
01598
01599
01600
01601 export_series = kExportSeries;
01602
01603
01604
01605
01606 long long *sunums = NULL;
01607 int expsucount;
01608 const char *lfname = NULL;
01609 int fileupload = strncmp(dsin, "*file*", 6) == 0;
01610 int internal = (strcmp(dbhost, "hmidb") == 0);
01611
01612
01613 if (strcmp(op, kOpExpSu) == 0)
01614 {
01615 long long sunum;
01616 int isunum;
01617 const char *seriesKey = NULL;
01618 int count;
01619 int status=0;
01620 int sums_status = 0;
01621 int all_online;
01622
01623 if (internal)
01624 {
01625 lfname = kLogFileExpSuInt;
01626 }
01627 else
01628 {
01629 lfname = kLogFileExpSuExt;
01630 }
01631
01632
01633 export_series = kExportSeriesNew;
01634
01635 size=0;
01636 all_online = 1;
01637 count = 0;
01638
01639 if (!sunumarr || sunumarr[0] < 0)
01640 {
01641
01642 if (!cmdparams_set(&cmdparams, kArgSunum, dsin))
01643 {
01644 snprintf(msgbuf, sizeof(msgbuf),
01645 "Invalid argument in exp_su, '%s=%s'.\n", kArgDs, dsin);
01646 JSONDIE(msgbuf);
01647 }
01648
01649 nsunums = cmdparams_get_int64arr(&cmdparams, kArgSunum, &sunumarr, &status);
01650
01651 if (status != CMDPARAMS_SUCCESS)
01652 {
01653 snprintf(msgbuf, sizeof(msgbuf),
01654 "Invalid argument in exp_su, '%s=%s'.\n", kArgDs, dsin);
01655 JSONDIE(msgbuf);
01656 }
01657 }
01658
01659 if (!sunumarr || sunumarr[0] < 0)
01660 {
01661 JSONDIE("There are no SUs in sunum or ds params");
01662 }
01663
01664
01665 size_t bufSz = 256;
01666 char *sunumListStr = calloc(bufSz, sizeof(char));
01667 char sunumStrBuf[32];
01668
01669 if (sunumListStr)
01670 {
01671 for (isunum = 0; isunum < nsunums; isunum++)
01672 {
01673 sunum = sunumarr[isunum];
01674
01675 if (isunum < nsunums - 1)
01676 {
01677 snprintf(sunumStrBuf, sizeof(sunumStrBuf), "%lld,", sunum);
01678 }
01679 else
01680 {
01681 snprintf(sunumStrBuf, sizeof(sunumStrBuf), "%lld", sunum);
01682 }
01683
01684 sunumListStr = base_strcatalloc(sunumListStr, sunumStrBuf, &bufSz);
01685 }
01686
01687 LogReqInfo(lfname, instanceID, fileupload, op, sunumListStr, requestid, dbhost, from_web, webarglist, fetch_time);
01688
01689 free(sunumListStr);
01690 sunumListStr = NULL;
01691 }
01692 else
01693 {
01694
01695 LogReqInfo(lfname, instanceID, fileupload, op, dsin, requestid, dbhost, from_web, webarglist, fetch_time);
01696 }
01697
01698
01699 infostructs = (SUM_info_t **)malloc(sizeof(SUM_info_t *) * nsunums);
01700 status = drms_getsuinfo(drms_env, (long long *)sunumarr, nsunums, infostructs);
01701
01702 if (status != DRMS_SUCCESS)
01703 {
01704 snprintf(msgbuf, sizeof(msgbuf),
01705 "drms_getsuinfo(): failure calling talking with SUMS, error code %d.\n", status);
01706 printkerr(msgbuf);
01707 sums_status = 1;
01708 }
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725 const int NUM_ARGS = 16;
01726 char stmnt[256];
01727 char *argin[NUM_ARGS];
01728 DB_Type_t intype[NUM_ARGS];
01729 int nExe;
01730 int iArg;
01731 int iExe;
01732 char nbuf[32];
01733 HContainer_t *seriesSunums = NULL;
01734 HContainer_t *seriesMinBadTimes = NULL;
01735 HContainer_t *seriesMaxBadTimes = NULL;
01736 HContainer_t *seriesAcceptRates = NULL;
01737 HContainer_t *filterOut = NULL;
01738 LinkedList_t *sunumList = NULL;
01739 HIterator_t *hit = NULL;
01740 void *iterGet = NULL;
01741 void *hlookupGet = NULL;
01742 DB_Binary_Result_t *bres = NULL;
01743 DB_Binary_Result_t **pBres = NULL;
01744 int iBres;
01745 DB_Text_Result_t *tres = NULL;
01746 int irow;
01747 ListNode_t *node = NULL;
01748 char *tmpDup = NULL;
01749 TIME minBadTime;
01750 TIME maxBadTime;
01751 int acceptRate;
01752 long long *sunumArrSorted = NULL;
01753 char *timeCol = NULL;
01754 int dontFilter;
01755 char timeValStr[256];
01756 char *endptr = NULL;
01757 int doFetchBlock = 0;
01758 int istat = DRMS_SUCCESS;
01759
01760 seriesSunums = hcon_create(sizeof(LinkedList_t *), DRMS_MAXSERIESNAMELEN, (void (*)(const void *value))list_llfree, NULL, NULL, NULL, 0);
01761 seriesMinBadTimes = hcon_create(sizeof(TIME), DRMS_MAXSERIESNAMELEN, NULL, NULL, NULL, NULL, 0);
01762 seriesMaxBadTimes = hcon_create(sizeof(TIME), DRMS_MAXSERIESNAMELEN, NULL, NULL, NULL, NULL, 0);
01763 seriesAcceptRates = hcon_create(sizeof(int), DRMS_MAXSERIESNAMELEN, NULL, NULL, NULL, NULL, 0);
01764 filterOut = hcon_create(sizeof(int), sizeof(nbuf), NULL, NULL, NULL, NULL, 0);
01765
01766 if (!seriesSunums || !seriesMinBadTimes || !seriesMaxBadTimes || !filterOut)
01767 {
01768 istat = DRMS_ERROR_OUTOFMEMORY;
01769 }
01770
01771 if (istat == DRMS_SUCCESS)
01772 {
01773
01774 if (drms_query_tabexists(drms_env->session, "su_production", "fetchblock", &istat))
01775 {
01776 doFetchBlock = 1;
01777 }
01778 }
01779
01780 if (istat == DRMS_SUCCESS && doFetchBlock)
01781 {
01782 for (isunum = 0; isunum < nsunums; isunum++)
01783 {
01784 sunum = sunumarr[isunum];
01785 seriesKey = infostructs[isunum]->owning_series;
01786
01787 dontFilter = 0;
01788
01789
01790
01791
01792
01793
01794
01795 if (!hcon_member_lower(seriesSunums, seriesKey))
01796 {
01797 tmpDup = strdup(seriesKey);
01798 if (!tmpDup)
01799 {
01800 istat = DRMS_ERROR_OUTOFMEMORY;
01801 break;
01802 }
01803
01804 strtolower(tmpDup);
01805 snprintf(stmnt, sizeof(stmnt), "SELECT mindate, maxdate, acceptrate FROM su_production.fetchblock WHERE lower(seriesname) = '%s'", tmpDup);
01806 free(tmpDup);
01807
01808
01809 if ((tres = drms_query_txt(drms_env->session, stmnt)) == NULL)
01810 {
01811 fprintf(stderr, "Failed to query su_production.fetchblock.\n");
01812 istat = DRMS_ERROR_QUERYFAILED;
01813 break;
01814 }
01815 else
01816 {
01817 if (tres->num_cols != 3 || tres->num_rows > 1)
01818 {
01819 fprintf(stderr, "Unexpected query result.\n");
01820 istat = DRMS_ERROR_BADQUERYRESULT;
01821 break;
01822 }
01823 else
01824 {
01825 if (tres->num_rows == 0)
01826 {
01827
01828 dontFilter = 1;
01829 }
01830 else
01831 {
01832 snprintf(timeValStr, sizeof(timeValStr), "%s", tres->field[0][0]);
01833 minBadTime = sscan_time(timeValStr);
01834
01835 snprintf(timeValStr, sizeof(timeValStr), "%s", tres->field[0][1]);
01836 maxBadTime = sscan_time(timeValStr);
01837
01838 acceptRate = strtoll(tres->field[0][2], &endptr, 0);
01839 if (acceptRate == 0 && endptr == tres->field[0][2])
01840 {
01841 acceptRate = 0;
01842 }
01843 }
01844 }
01845 }
01846
01847 db_free_text_result(tres);
01848
01849
01850 sunumList = list_llcreate(sizeof(long long), NULL);
01851 if (!sunumList)
01852 {
01853 istat = DRMS_ERROR_OUTOFMEMORY;
01854 break;
01855 }
01856
01857 hcon_insert_lower(seriesSunums, seriesKey, &sunumList);
01858
01859 if (dontFilter)
01860 {
01861 continue;
01862 }
01863
01864 hcon_insert_lower(seriesMinBadTimes, seriesKey, &minBadTime);
01865 hcon_insert_lower(seriesMaxBadTimes, seriesKey, &maxBadTime);
01866 hcon_insert_lower(seriesAcceptRates, seriesKey, &acceptRate);
01867 list_llinserttail(sunumList, &sunum);
01868 }
01869
01870 hlookupGet = hcon_lookup_lower(seriesSunums, seriesKey);
01871 if (!hlookupGet)
01872 {
01873 istat = DRMS_ERROR_DATASTRUCT;
01874 break;
01875 }
01876
01877 sunumList = *(LinkedList_t **)hlookupGet;
01878
01879 if (list_llgetnitems(sunumList) > 0)
01880 {
01881
01882 list_llinserttail(sunumList, &sunum);
01883 }
01884 else
01885 {
01886
01887 }
01888 }
01889 }
01890
01891
01892 if (istat == DRMS_SUCCESS && doFetchBlock)
01893 {
01894 int nSeriesSunums = 0;
01895 size_t stsz;
01896 char *sql = NULL;
01897 TIME timeVal = 0;
01898 int zeroVal = 0;
01899 DRMS_Record_t *template = NULL;
01900 DRMS_Keyword_t *pkey = NULL;
01901 int nPKeys;
01902 int iKey;
01903
01904 hit = hiter_create(seriesSunums);
01905 if (!hit)
01906 {
01907 istat = DRMS_ERROR_OUTOFMEMORY;
01908 }
01909 else
01910 {
01911
01912 while ((iterGet = hiter_extgetnext(hit, &seriesKey)) != NULL && istat == DRMS_SUCCESS)
01913 {
01914 sunumList = *(LinkedList_t **)iterGet;
01915
01916
01917 if ((nSeriesSunums = list_llgetnitems(sunumList)) == 0)
01918 {
01919 continue;
01920 }
01921
01922 sunumArrSorted = calloc(nSeriesSunums, sizeof(long long));
01923
01924 if (!sunumArrSorted)
01925 {
01926 istat = DRMS_ERROR_OUTOFMEMORY;
01927 break;
01928 }
01929
01930
01931 isunum = 0;
01932 list_llreset(sunumList);
01933 while ((node = list_llnext(sunumList)) != NULL)
01934 {
01935 if (!node->data)
01936 {
01937 istat = DRMS_ERROR_DATASTRUCT;
01938 if (sunumArrSorted)
01939 {
01940 free(sunumArrSorted);
01941 sunumArrSorted = NULL;
01942 }
01943 break;
01944 }
01945
01946 sunumArrSorted[isunum++] = *(long long *)node->data;
01947 }
01948
01949 if (istat == DRMS_SUCCESS)
01950 {
01951 qsort(sunumArrSorted, nSeriesSunums, sizeof(long long), sunumComp);
01952
01953
01954
01955 template = drms_template_record(drms_env, seriesKey, &istat);
01956 if (istat != DRMS_SUCCESS || !template)
01957 {
01958 istat = DRMS_ERROR_UNKNOWNSERIES;
01959 if (sunumArrSorted)
01960 {
01961 free(sunumArrSorted);
01962 sunumArrSorted = NULL;
01963 }
01964 break;
01965 }
01966
01967
01968 timeCol = NULL;
01969 iKey = 0;
01970 nPKeys = template->seriesinfo->pidx_num;
01971
01972 while (iKey < nPKeys)
01973 {
01974 pkey = template->seriesinfo->pidx_keywords[iKey];
01975
01976 if (drms_keyword_isindex(pkey))
01977 {
01978
01979 pkey = drms_keyword_slotfromindex(pkey);
01980 }
01981
01982 if (drms_keyword_gettype(pkey) == DRMS_TYPE_TIME)
01983 {
01984
01985 timeCol = pkey->info->name;
01986 break;
01987 }
01988
01989 iKey++;
01990 }
01991 }
01992
01993 if (istat == DRMS_SUCCESS)
01994 {
01995
01996
01997 if (!timeCol)
01998 {
01999 if (sunumArrSorted)
02000 {
02001 free(sunumArrSorted);
02002 sunumArrSorted = NULL;
02003 }
02004 continue;
02005 }
02006 }
02007
02008 if (istat == DRMS_SUCCESS)
02009 {
02010
02011 nExe = nSeriesSunums / NUM_ARGS;
02012
02013 if (nExe > 0)
02014 {
02015 for (iArg = 0; iArg < NUM_ARGS; iArg++)
02016 {
02017 argin[iArg] = calloc(nExe, sizeof(db_int8_t));
02018 intype[iArg] = DB_INT8;
02019 }
02020
02021 iArg = 0;
02022 iExe = 0;
02023 isunum = 0;
02024
02025 while (isunum < nExe * NUM_ARGS)
02026 {
02027 sunum = sunumArrSorted[isunum];
02028
02029 if (iArg == NUM_ARGS)
02030 {
02031 iArg = 0;
02032 iExe++;
02033 }
02034
02035 memcpy(argin[iArg] + iExe * db_sizeof(intype[iArg]), &sunum, db_sizeof(intype[iArg]));
02036 iArg++;
02037 isunum++;
02038 }
02039
02040 stsz = 512;
02041 sql = calloc(stsz, sizeof(char));
02042
02043 if (sql)
02044 {
02045 sql = base_strcatalloc(sql, "SELECT sunum, min(", &stsz);
02046 sql = base_strcatalloc(sql, timeCol, &stsz);
02047 sql = base_strcatalloc(sql, ") AS mindate FROM ", &stsz);
02048 sql = base_strcatalloc(sql, seriesKey, &stsz);
02049 sql = base_strcatalloc(sql, " WHERE sunum IN (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) GROUP BY sunum", &stsz);
02050
02051 pBres = drms_query_bin_ntuple(drms_env->session, sql, nExe, NUM_ARGS, intype, (void **)argin);
02052
02053 for (iArg = 0; iArg < NUM_ARGS; iArg++)
02054 {
02055 if (argin[iArg])
02056 {
02057 free(argin[iArg]);
02058 argin[iArg] = NULL;
02059 }
02060 }
02061
02062 if (pBres)
02063 {
02064 for (iBres = 0; iBres < nExe; iBres++)
02065 {
02066 bres = pBres[iBres];
02067
02068 if (bres)
02069 {
02070
02071
02072
02073
02074 for (irow = 0; irow < bres->num_rows; irow++)
02075 {
02076 sunum = db_binary_field_getlonglong(bres, irow, 0);
02077 timeVal = db_binary_field_getdouble(bres, irow, 1);
02078
02079
02080 if ((hlookupGet = hcon_lookup_lower(seriesMinBadTimes, seriesKey)) != NULL)
02081 {
02082 minBadTime = *((TIME *)hlookupGet);
02083 }
02084 else
02085 {
02086 minBadTime = -1;
02087 }
02088
02089 if ((hlookupGet = hcon_lookup_lower(seriesMaxBadTimes, seriesKey)) != NULL)
02090 {
02091 maxBadTime = *((TIME *)hlookupGet);
02092 }
02093 else
02094 {
02095 maxBadTime = -1;
02096 }
02097
02098 if (minBadTime >= 0 && maxBadTime < 0)
02099 {
02100 maxBadTime = INFINITY;
02101 }
02102
02103 if (timeVal > minBadTime && timeVal < maxBadTime)
02104 {
02105 snprintf(nbuf, sizeof(nbuf), "%lld", sunum);
02106 if ((hlookupGet = hcon_lookup_lower(seriesAcceptRates, seriesKey)) != NULL)
02107 {
02108 acceptRate = *((int *)hlookupGet);
02109 hcon_insert(filterOut, nbuf, &acceptRate);
02110 }
02111 else
02112 {
02113 hcon_insert(filterOut, nbuf, &zeroVal);
02114 }
02115 }
02116 }
02117 }
02118 }
02119
02120 db_free_binary_result_tuple(&pBres, nExe);
02121 pBres = NULL;
02122 }
02123
02124 free(sql);
02125 sql = NULL;
02126 }
02127 }
02128 }
02129
02130 if (istat == DRMS_SUCCESS)
02131 {
02132 if (nSeriesSunums % NUM_ARGS != 0)
02133 {
02134
02135
02136 stsz = 512;
02137 sql = calloc(stsz, sizeof(char));
02138
02139 if (sql)
02140 {
02141 sql = base_strcatalloc(sql, "SELECT sunum, min(", &stsz);
02142 sql = base_strcatalloc(sql, timeCol, &stsz);
02143 sql = base_strcatalloc(sql, ") AS mindate FROM ", &stsz);
02144 sql = base_strcatalloc(sql, seriesKey, &stsz);
02145 sql = base_strcatalloc(sql, " WHERE sunum IN (", &stsz);
02146
02147 isunum = NUM_ARGS * nExe;
02148 while (isunum < nSeriesSunums)
02149 {
02150 sunum = sunumArrSorted[isunum];
02151
02152 snprintf(nbuf, sizeof(nbuf), "%lld", sunum);
02153 sql = base_strcatalloc(sql, nbuf, &stsz);
02154 if (isunum < nSeriesSunums - 1)
02155 {
02156 sql = base_strcatalloc(sql, ", ", &stsz);
02157 }
02158
02159 isunum++;
02160 }
02161
02162 sql = base_strcatalloc(sql, ") GROUP BY sunum", &stsz);
02163
02164
02165 if ((bres = drms_query_bin(drms_env->session, sql)) == NULL)
02166 {
02167 fprintf(stderr, "Failed to obtain the earliest date of the data the SUS for series %s.\n", seriesKey);
02168 istat = DRMS_ERROR_QUERYFAILED;
02169 }
02170 else
02171 {
02172 if (bres->num_cols != 2)
02173 {
02174 fprintf(stderr, "Unexpected query result.\n");
02175 istat = DRMS_ERROR_BADQUERYRESULT;
02176 }
02177 else
02178 {
02179
02180
02181
02182 for (irow = 0; irow < bres->num_rows; irow++)
02183 {
02184 sunum = db_binary_field_getlonglong(bres, irow, 0);
02185 timeVal = db_binary_field_getdouble(bres, irow, 1);
02186
02187
02188 if ((hlookupGet = hcon_lookup_lower(seriesMinBadTimes, seriesKey)) != NULL)
02189 {
02190 minBadTime = *((TIME *)hlookupGet);
02191 }
02192 else
02193 {
02194 minBadTime = -1;
02195 }
02196
02197 if ((hlookupGet = hcon_lookup_lower(seriesMaxBadTimes, seriesKey)) != NULL)
02198 {
02199 maxBadTime = *((TIME *)hlookupGet);
02200 }
02201 else
02202 {
02203 maxBadTime = -1;
02204 }
02205
02206 if (minBadTime >= 0 && maxBadTime < 0)
02207 {
02208 maxBadTime = INFINITY;
02209 }
02210
02211 if (timeVal > minBadTime && timeVal < maxBadTime)
02212 {
02213 snprintf(nbuf, sizeof(nbuf), "%lld", sunum);
02214 if ((hlookupGet = hcon_lookup_lower(seriesAcceptRates, seriesKey)) != NULL)
02215 {
02216 acceptRate = *((int *)hlookupGet);
02217 hcon_insert(filterOut, nbuf, &acceptRate);
02218 }
02219 else
02220 {
02221 hcon_insert(filterOut, nbuf, &zeroVal);
02222 }
02223 }
02224 }
02225 }
02226 }
02227
02228 db_free_binary_result(bres);
02229 bres = NULL;
02230 free(sql);
02231 sql = NULL;
02232 }
02233 else
02234 {
02235 istat = DRMS_ERROR_OUTOFMEMORY;
02236 }
02237 }
02238
02239 if (sunumArrSorted)
02240 {
02241 free(sunumArrSorted);
02242 sunumArrSorted = NULL;
02243 }
02244 }
02245 }
02246
02247 hiter_destroy(&hit);
02248 }
02249 }
02250
02251 status = istat;
02252
02253
02254
02255 if (seriesSunums)
02256 {
02257 hcon_destroy(&seriesSunums);
02258 }
02259
02260 if (seriesMinBadTimes)
02261 {
02262 hcon_destroy(&seriesMinBadTimes);
02263 }
02264
02265 if (seriesMaxBadTimes)
02266 {
02267 hcon_destroy(&seriesMaxBadTimes);
02268 }
02269
02270 if (seriesAcceptRates)
02271 {
02272 hcon_destroy(&seriesAcceptRates);
02273 }
02274
02275
02276 char onlinestat[128];
02277 long long dirsize;
02278 char supath[DRMS_MAXPATHLEN];
02279 char yabuff[64];
02280 int roll;
02281 int reject;
02282
02283
02284 sunums = calloc(nsunums, sizeof(long long));
02285 if (!sunums)
02286 {
02287 JSONDIE("Not enough memory to allocate SUNUM array for exp_su request.");
02288 }
02289
02290 paths = calloc(nsunums, sizeof(char *));
02291 if (!paths)
02292 {
02293 JSONDIE("Not enough memory to allocate paths array for exp_su request.");
02294 }
02295
02296 series = calloc(nsunums, sizeof(char *));
02297 if (!series)
02298 {
02299 JSONDIE("Not enough memory to allocate series array for exp_su request.");
02300 }
02301
02302
02303 sustatus = calloc(nsunums, sizeof(char));
02304 if (!sustatus)
02305 {
02306 JSONDIE("Not enough memory to allocate sustatus array for exp_su request.");
02307 }
02308
02309 susize = calloc(nsunums, sizeof(char *));
02310 if (!susize)
02311 {
02312 JSONDIE("Not enough memory to allocate susize array for exp_su request.");
02313 }
02314
02315 arrsize = nsunums;
02316
02317 for (isunum = 0; isunum < nsunums; isunum++)
02318 {
02319 SUM_info_t *sinfo;
02320 TIME expire = 0;
02321
02322 dirsize = 0;
02323 memset(onlinestat, 0, sizeof(onlinestat));
02324 snprintf(supath, sizeof(supath), "NA");
02325
02326 sunum = sunumarr[isunum];
02327
02328 sinfo = infostructs[isunum];
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340 reject = 0;
02341 snprintf(nbuf, sizeof(nbuf), "%lld", sunum);
02342 if ((hlookupGet = hcon_lookup(filterOut, nbuf)) != NULL)
02343 {
02344 acceptRate = *((int *)hlookupGet);
02345 roll = dieRoll(100);
02346
02347
02348 if (roll > acceptRate)
02349 {
02350 reject = 1;
02351 *(sinfo->online_loc) = '\0';
02352 }
02353 }
02354
02355 if (*(sinfo->online_loc) == '\0')
02356 {
02357 if (!reject)
02358 {
02359 *onlinestat = 'I';
02360 }
02361 else
02362 {
02363 *onlinestat = 'N';
02364 }
02365
02366 sunums[count] = sunum;
02367 paths[count] = strdup("NA");
02368 series[count] = strdup("NA");
02369 sustatus[count] = onlinestat[0];
02370 susize[count] = strdup("0");
02371 count++;
02372 }
02373 else
02374 {
02375 size += (long long)sinfo->bytes;
02376 dirsize = (long long)sinfo->bytes;
02377
02378 if (strcmp(sinfo->online_status,"Y")==0)
02379 {
02380 int y,m,d,hr,mn;
02381 char sutime[50];
02382 sscanf(sinfo->effective_date,"%4d%2d%2d%2d%2d", &y,&m,&d,&hr,&mn);
02383 sprintf(sutime, "%4d.%02d.%02d_%02d:%02d", y,m,d,hr,mn);
02384 expire = (sscan_time(sutime) - fetch_time)/86400.0;
02385 snprintf(supath, sizeof(supath), "%s", sinfo->online_loc);
02386 *onlinestat = 'Y';
02387 }
02388 if (strcmp(sinfo->online_status,"N")==0 || expire < 3)
02389 {
02390 if (strcmp(sinfo->archive_status, "N") == 0)
02391 {
02392 *onlinestat = 'X';
02393 }
02394 else
02395 {
02396 *onlinestat = 'N';
02397
02398 all_online = 0;
02399 }
02400 }
02401
02402 sunums[count] = sunum;
02403 paths[count] = strdup(supath);
02404 series[count] = strdup(sinfo->owning_series);
02405 sustatus[count] = onlinestat[0];
02406 snprintf(yabuff, sizeof(yabuff), "%lld", dirsize);
02407 susize[count] = strdup(yabuff);
02408
02409 count += 1;
02410 }
02411
02412 free(sinfo);
02413 sinfo = NULL;
02414 }
02415
02416 if (filterOut)
02417 {
02418 hcon_destroy(&filterOut);
02419 }
02420
02421 expsucount = count;
02422
02423 if (count==0)
02424 JSONDIE("There are no files in this RecordSet");
02425
02426
02427
02428
02429
02430
02431
02432
02433
02434
02435 if (sums_status == 1 && !dodataobj)
02436 {
02437
02438 JSONDIE("SUMS is down.");
02439 }
02440
02441 if (strcmp(method,"url_quick")==0 && (strcmp(protocol,kOptProtocolAsIs)==0 || strcmp(protocol,kOptProtocolSuAsIs)==0) && (all_online || dodataobj))
02442 {
02443 if (dojson)
02444 {
02445 int i;
02446 char *json;
02447 char *strval;
02448 char numval[50];
02449 json_t *jroot = json_new_object();
02450 json_t *data;
02451 if (dodataobj)
02452 data = json_new_object();
02453 else
02454 data = json_new_array();
02455
02456 for (i=0; i < count; i++)
02457 {
02458 json_t *suobj = json_new_object();
02459 char *jsonstr;
02460 char numval[40];
02461 char *sunumstr = NULL;
02462 sprintf(numval,"%lld",sunums[i]);
02463 sunumstr = string_to_json(numval);
02464 json_insert_pair_into_object(suobj, "sunum", json_new_string(sunumstr));
02465 jsonstr = string_to_json(series[i]);
02466 json_insert_pair_into_object(suobj, "series", json_new_string(jsonstr));
02467 free(jsonstr);
02468 jsonstr = string_to_json(paths[i]);
02469 json_insert_pair_into_object(suobj, "path", json_new_string(jsonstr));
02470 free(jsonstr);
02471 numval[0] = sustatus[i];
02472 numval[1] = '\0';
02473
02474 json_insert_pair_into_object(suobj, "sustatus", json_new_string(numval));
02475 json_insert_pair_into_object(suobj, "susize", json_new_string(susize[i]));
02476 if (dodataobj)
02477 {
02478 json_t *suLabel = json_new_string(sunumstr);
02479 json_insert_child(suLabel,suobj);
02480 json_insert_child(data, suLabel);
02481 }
02482 else
02483 json_insert_child(data, suobj);
02484 if (sunumstr)
02485 free(sunumstr);
02486 }
02487
02488 sprintf(numval, "%d", count);
02489 json_insert_pair_into_object(jroot, "count", json_new_number(numval));
02490 sprintf(numval, "%lld", size);
02491 json_insert_pair_into_object(jroot, "size", json_new_number(numval));
02492 json_insert_pair_into_object(jroot, "dir", json_new_string(""));
02493 json_insert_pair_into_object(jroot, "data", data);
02494 json_insert_pair_into_object(jroot, kArgRequestid, json_new_string(""));
02495 strval = string_to_json((char *)method);
02496 json_insert_pair_into_object(jroot, kArgMethod, json_new_string(strval));
02497 free(strval);
02498 strval = string_to_json((char *)protocol);
02499 json_insert_pair_into_object(jroot, kArgProtocol, json_new_string(strval));
02500 free(strval);
02501 json_insert_pair_into_object(jroot, "wait", json_new_number("0"));
02502
02503 char sums_status_str[256];
02504 sprintf(sums_status_str, "%d", sums_status);
02505 json_insert_pair_into_object(jroot, "status", json_new_number(sums_status_str));
02506 json_tree_to_string(jroot,&json);
02507 if (genWebPage)
02508 {
02509 printf("Content-type: application/json\n\n");
02510 }
02511 printf("%s\n",json);
02512 fflush(stdout);
02513 free(json);
02514
02515
02516 json_free_value(&jroot);
02517 }
02518 else
02519 {
02520 int i;
02521 if (genWebPage)
02522 {
02523 printf("Content-type: text/plain\n\n");
02524 }
02525 printf("# JSOC Quick Data Export of as-is files.\n");
02526 printf("status=0\n");
02527 printf("requestid=\"%s\"\n", kNotSpecified);
02528 printf("method=%s\n", method);
02529 printf("protocol=%s\n", protocol);
02530 printf("wait=0\n");
02531 printf("count=%d\n", count);
02532 printf("size=%lld\n", size);
02533 printf("dir=/\n");
02534 printf("# DATA\n");
02535 for (i=0; i<count; i++)
02536 printf("%lld\t%s\t%s\t%c\t%s\n",sunums[i],series[i],paths[i], sustatus[i], susize[i]);
02537 }
02538
02539 report_summary(Server, StartTime, Remote_Address, op, dsin, 0, internal, 0);
02540 if (!dodataobj || (sums_status == 1 || all_online))
02541 {
02542
02543
02544 if (sustatus)
02545 {
02546 free(sustatus);
02547 sustatus = NULL;
02548 }
02549
02550 if (sunums)
02551 {
02552 free(sunums);
02553 sunums = NULL;
02554 }
02555
02556 CleanUp(&sunumarr, &infostructs, &webarglist, &series, &paths, &susize, arrsize, userhandle);
02557 return(0);
02558 }
02559 else if (strcmp(requestid, kNoAsyncReq) == 0)
02560 {
02561 if (sustatus)
02562 {
02563 free(sustatus);
02564 sustatus = NULL;
02565 }
02566
02567 if (sunums)
02568 {
02569 free(sunums);
02570 sunums = NULL;
02571 }
02572
02573 CleanUp(&sunumarr, &infostructs, &webarglist, &series, &paths, &susize, arrsize, userhandle);
02574 return 0;
02575 }
02576 }
02577
02578
02579
02580 if (strcmp(requestid, kNoAsyncReq) == 0)
02581 {
02582 JSONDIE("User denies required full export");
02583 }
02584
02585
02586
02587 char jsocFetchPath[PATH_MAX];
02588 char reqidGenPath[PATH_MAX];
02589 char *binPath = NULL;
02590
02591 memset(jsocFetchPath, '\0', sizeof(jsocFetchPath));
02592
02593
02594 if (readlink("/proc/self/exe", jsocFetchPath, sizeof(jsocFetchPath)) == -1)
02595 {
02596 JSONDIE("Cannot obtain jsoc_fetch path.\n");
02597 }
02598 else
02599 {
02600 binPath = dirname(jsocFetchPath);
02601 snprintf(reqidGenPath, sizeof(reqidGenPath), "%s/GetJsocRequestID", binPath);
02602 }
02603
02604 FILE *fp = popen(reqidGenPath, "r");
02605
02606 if (fp)
02607 {
02608 if (fscanf(fp, "%s", new_requestid) != 1)
02609 {
02610 pclose(fp);
02611 JSONDIE("Cant get new RequestID");
02612 }
02613
02614 pclose(fp);
02615 }
02616 else
02617 {
02618 JSONDIE("Cant get new RequestID");
02619 }
02620
02621 strcat(new_requestid, "_SU");
02622 requestid = new_requestid;
02623
02624
02625 if (1)
02626 {
02627 char exportlogfile[1000];
02628 char timebuf[50];
02629 FILE *exportlog;
02630 sprintf(exportlogfile, "/home/jsoc/exports/tmp/%s.reqlog", requestid);
02631 exportlog = fopen(exportlogfile, "a");
02632 sprint_ut(timebuf, fetch_time);
02633 fprintf(exportlog,"XXXX New SU request started at %s\n", timebuf);
02634 fprintf(exportlog,"REMOTE_ADDR=%s\nHTTP_REFERER=%s\nREQUEST_METHOD=%s\nQUERY_STRING=%s\n",
02635 getenv("REMOTE_ADDR"), getenv("HTTP_REFERER"), getenv("REQUEST_METHOD"), getenv("QUERY_STRING"));
02636 fclose(exportlog);
02637 }
02638
02639
02640
02641
02642 if (strcmp(requestor, kNotSpecified) != 0)
02643 {
02644 #ifdef SHOULD_BE_HERE
02645 check for requestor to be valid remote DRMS site
02646 #else // for now
02647 requestorid = 0;
02648 #endif
02649 }
02650 else
02651 requestorid = 0;
02652
02653 if ( !requestid || !*requestid || strcmp(requestid, "none") == 0)
02654 JSONDIE("Must have valid requestID - internal error.");
02655
02656 if (strcmp(dsin, kNotSpecified) == 0 && (!sunumarr || sunumarr[0] < 0))
02657 JSONDIE("Must have valid Recordset or SU set");
02658
02659
02660 char *dataSetCol = NULL;
02661 size_t szDataSetCol = 512;
02662 char numBuf[64];
02663 char *processingCol = "n=0|no_op";
02664
02665 dataSetCol = calloc(1, szDataSetCol);
02666 if (!dataSetCol)
02667 {
02668 JSONDIE("Out of memory creating Processing string.");
02669 }
02670
02671 dataSetCol = base_strcatalloc(dataSetCol, "sunums=", &szDataSetCol);
02672
02673
02674
02675
02676
02677
02678 for (isunum = 0; isunum < nsunums; isunum++)
02679 {
02680 if (isunum > 0)
02681 {
02682 dataSetCol = base_strcatalloc(dataSetCol, ",", &szDataSetCol);
02683 }
02684
02685 snprintf(numBuf, sizeof(numBuf), "%lld", ((long long signed int *)sunumarr)[isunum]);
02686 dataSetCol = base_strcatalloc(dataSetCol, numBuf, &szDataSetCol);
02687 }
02688
02689
02690
02691
02692
02693 exprec = drms_create_record(drms_env, export_series, DRMS_PERMANENT, &status);
02694 if (!exprec)
02695 JSONDIE("Cant create new export control record");
02696 drms_setkey_string(exprec, "RequestID", requestid);
02697 drms_setkey_string(exprec, "DataSet", dataSetCol);
02698 drms_setkey_string(exprec, "Processing", processingCol);
02699 drms_setkey_string(exprec, "Protocol", protocol);
02700 drms_setkey_string(exprec, "FilenameFmt", filenamefmt);
02701 drms_setkey_string(exprec, "Method", method);
02702 drms_setkey_string(exprec, "Format", format);
02703 drms_setkey_time(exprec, "ReqTime", fetch_time);
02704 drms_setkey_time(exprec, "EstTime", fetch_time+10);
02705 drms_setkey_longlong(exprec, "Size", (int)size);
02706 drms_setkey_int(exprec, "Status", (testmode ? 12 : 2));
02707 drms_setkey_int(exprec, "Requestor", requestorid);
02708
02709 if (dataSetCol)
02710 {
02711 free(dataSetCol);
02712 dataSetCol = NULL;
02713 }
02714
02715 }
02716
02717
02718 else if (strcmp(op,kOpExpRequest) == 0)
02719 {
02720 int status=0;
02721 int segcount = 0;
02722 int irec;
02723 int all_online = 1;
02724 char dsquery[DRMS_MAXQUERYLEN];
02725 char *p;
02726 char *file, *filename;
02727 int filesize;
02728 DRMS_RecordSet_t *rs;
02729 int compressedStorage;
02730 int compressedDownload;
02731 export_series = kExportSeriesNew;
02732 char dieStr[1024];
02733 int caStatus = 0;
02734 HContainer_t *argsCont = NULL;
02735 HIterator_t *hIter = NULL;
02736 void *pCmdParamArg = NULL;
02737 CmdParams_Arg_t *cmdParamArg = NULL;
02738 char cmdParamArgBuf[512] = {0};
02739
02740 if (internal)
02741 {
02742 lfname = kLogFileExpReqInt;
02743 }
02744 else
02745 {
02746 lfname = kLogFileExpReqExt;
02747 }
02748
02749
02750 LogReqInfo(lfname, instanceID, fileupload, op, dsin, requestid, dbhost, from_web, webarglist, fetch_time);
02751
02752
02753 argsCont = cmdparams_get_argscont(&cmdparams);
02754 if (argsCont)
02755 {
02756 hIter = hiter_create(argsCont);
02757 if (hIter)
02758 {
02759 while ((pCmdParamArg = hiter_getnext(hIter)) != NULL)
02760 {
02761 cmdParamArg = (CmdParams_Arg_t *)pCmdParamArg;
02762
02763 if (cmdParamArg->strval)
02764 {
02765 snprintf(cmdParamArgBuf, sizeof(cmdParamArgBuf), "%s=%s\n", cmdParamArg->name ? cmdParamArg->name : "Unnamed", cmdParamArg->strval);
02766 }
02767
02768 WriteLog(lfname, cmdParamArgBuf);
02769 }
02770
02771 hiter_destroy(&hIter);
02772 }
02773 }
02774
02775 caStatus = CheckEmailAddress(lfname, requestor, notify, dieStr, sizeof(dieStr));
02776
02777 if (caStatus == 1)
02778 {
02779 if (gLogs)
02780 {
02781 hcon_destroy(&gLogs);
02782 }
02783 JSONDIE(dieStr);
02784 }
02785 else if (caStatus == 2 || caStatus == 3)
02786 {
02787 if (gLogs)
02788 {
02789 hcon_destroy(&gLogs);
02790 }
02791 JSONDIE2(dieStr, "");
02792 }
02793
02794 size=0;
02795 strncpy(dsquery,dsin,DRMS_MAXQUERYLEN);
02796 fileupload = strncmp(dsquery, "*file*", 6) == 0;
02797 if (fileupload)
02798 {
02799 file = (char *)cmdparams_get_str (&cmdparams, kArgFile, NULL);
02800 filesize = cmdparams_get_int (&cmdparams, kArgFile".length", NULL);
02801 filename = (char *)cmdparams_get_str (&cmdparams, kArgFile".filename", NULL);
02802 if (filesize >= DRMS_MAXQUERYLEN)
02803 {
02804 JSONDIE("Uploaded file limit 4096 chars for a bit longer, will fix later.");
02805
02806 }
02807 else if (filesize == 0)
02808 {
02809 JSONDIE("Uploaded file is empty");
02810 }
02811 else
02812 {
02813 int i;
02814 char c, *p = dsquery;
02815 int newline = 1;
02816 int discard = 0;
02817 strcpy(dsquery, file);
02818 for (i=0; (c = file[i]) && i<DRMS_MAXQUERYLEN; i++)
02819 {
02820 if (newline && c == '#')
02821 discard = 1;
02822 if (c == '\r')
02823 continue;
02824 if (c == '\n')
02825 {
02826 if (!newline && !discard)
02827 *p++ = ',';
02828 newline = 1;
02829 discard = 0;
02830 }
02831 else
02832 {
02833 if (!discard)
02834 *p++ = c;
02835 newline = 0;
02836 }
02837 }
02838 *p = '\0';
02839 if (p > dsquery && *(p-1) == ',')
02840 *(p-1) = '\0';
02841 }
02842 }
02843 else
02844 {
02845
02846 if (index(dsquery,'[') == NULL)
02847 {
02848 char *cb = index(dsquery, '{');
02849 if (cb)
02850 {
02851 char *cbin = index(dsin, '{');
02852 *cb = '\0';
02853 strcat(dsquery, "[]");
02854 strcat(dsquery, cbin);
02855 }
02856 else
02857 strcat(dsquery,"[]");
02858 }
02859 if (strcmp(seglist,kNotSpecified) != 0)
02860 {
02861 if (index(dsquery,'{') != NULL)
02862 JSONDIE("Can not give segment list both in key and explicitly in recordset.");
02863 strncat(dsquery, "{", DRMS_MAXQUERYLEN);
02864 strncat(dsquery, seglist, DRMS_MAXQUERYLEN);
02865 strncat(dsquery, "}", DRMS_MAXQUERYLEN);
02866 }
02867 if ((p=index(dsquery,'{')) != NULL && strncmp(p+1, "**ALL**", 7) == 0)
02868 *p = '\0';
02869 }
02870
02871
02872
02873
02874
02875
02876 char mbuf[1024];
02877 char *allvers = NULL;
02878 char **sets = NULL;
02879 DRMS_RecordSetType_t *settypes = NULL;
02880 char **snames = NULL;
02881 char **filts = NULL;
02882 char **segs = NULL;
02883 int nsets = 0;
02884 DRMS_RecQueryInfo_t rsinfo;
02885 int iset;
02886 int firstlastExists = 0;
02887 const char *setName = NULL;
02888
02889 if (drms_record_parserecsetspec_plussegs(dsquery, &allvers, &sets, &settypes, &snames, &filts, &segs, &nsets, &rsinfo) == DRMS_SUCCESS)
02890 {
02891
02892
02893
02894
02895
02896
02897
02898
02899 char *query = NULL;
02900 char *pkwhere = NULL;
02901 char *npkwhere = NULL;
02902 char *seriesname = NULL;
02903 int filter;
02904 int mixed;
02905 HContainer_t *firstlast = NULL;
02906 HContainer_t *pkwhereNFL = NULL;
02907 int recnumq;
02908
02909 if (nsets > 0)
02910 {
02911 setName = snames[0];
02912 }
02913
02914 for (iset = 0; iset < nsets; iset++)
02915 {
02916 if (strcmp(setName, snames[iset]) != 0)
02917 {
02918 snprintf(mbuf, sizeof(mbuf), "Cannot specify subsets of records from different series.\n");
02919 JSONDIE(mbuf);
02920 }
02921
02922 if (!drms_series_exists(drms_env, snames[iset], &status))
02923 {
02924 snprintf(mbuf, sizeof(mbuf), "Cannot export series '%s' - it does not exist.\n", snames[iset]);
02925 JSONDIE(mbuf);
02926 }
02927
02928 status = drms_recordset_query(drms_env, sets[iset], &query, &pkwhere, &npkwhere, &seriesname, &filter, &mixed, NULL, &firstlast, &pkwhereNFL, &recnumq);
02929 if (status != DRMS_SUCCESS)
02930 {
02931 snprintf(mbuf, sizeof(mbuf), "Bad record-set subset specification '%s'.\n", sets[iset]);
02932 JSONDIE(mbuf);
02933 }
02934
02935
02936 if (firstlast)
02937 {
02938 HIterator_t *hiter = NULL;
02939 char *code = NULL;
02940
02941 hiter = hiter_create(firstlast);
02942 if (hiter)
02943 {
02944 while ((code = hiter_getnext(hiter)) != NULL)
02945 {
02946 if (*code != 'N')
02947 {
02948 firstlastExists = 1;
02949 break;
02950 }
02951 }
02952
02953 hiter_destroy(&hiter);
02954 }
02955 else
02956 {
02957 JSONDIE("Out of memory.\n");
02958 }
02959 }
02960
02961 if (query)
02962 {
02963 free(query);
02964 }
02965
02966 if (pkwhere)
02967 {
02968 free(pkwhere);
02969 }
02970
02971 if (npkwhere)
02972 {
02973 free(npkwhere);
02974 }
02975
02976 if (seriesname)
02977 {
02978 free(seriesname);
02979 }
02980
02981 if (firstlast)
02982 {
02983 hcon_destroy(&firstlast);
02984 }
02985
02986 if (pkwhereNFL)
02987 {
02988 hcon_destroy(&pkwhereNFL);
02989 }
02990 }
02991 }
02992 else
02993 {
02994 snprintf(mbuf, sizeof(mbuf), "Bad record-set query '%s'.\n", dsquery);
02995 JSONDIE(mbuf);
02996 }
02997
02998 if (rcountlimit == 0)
02999 {
03000 rs = drms_open_records(drms_env, dsquery, &status);
03001 }
03002 else
03003 {
03004
03005 rs = drms_open_nrecords (drms_env, dsquery, rcountlimit, &status);
03006 }
03007
03008 if (!rs)
03009 {
03010 int tmpstatus = status;
03011 rcount = drms_count_records(drms_env, dsquery, &status);
03012 if (status == 0)
03013 {
03014
03015 char errmsg[100];
03016
03017 sprintf(errmsg, "%d is too many records in one request.", rcount);
03018 drms_record_freerecsetspecarr_plussegs(&allvers, &sets, &settypes, &snames, &filts, &segs, nsets);
03019 JSONDIE2("Can not open RecordSet ",errmsg);
03020 }
03021 status = tmpstatus;
03022 drms_record_freerecsetspecarr_plussegs(&allvers, &sets, &settypes, &snames, &filts, &segs, nsets);
03023 JSONDIE2("Can not open RecordSet, bad query or too many records: ", dsquery);
03024 }
03025
03026
03027
03028
03029
03030
03031
03032
03033
03034
03035
03036
03037 char *newSpec = NULL;
03038 size_t szNewSpec = DRMS_MAXQUERYLEN;
03039 char recnumStr[64];
03040
03041 newSpec = calloc(1, szNewSpec);
03042
03043 if (newSpec) newSpec = base_strcatalloc(newSpec, setName, &szNewSpec);
03044 if (newSpec) newSpec = base_strcatalloc(newSpec, "[", &szNewSpec);
03045
03046 for (irec = 0; irec < rs->n && newSpec; irec++)
03047 {
03048 snprintf(recnumStr, sizeof(recnumStr), "%lld", rs->records[irec]->recnum);
03049
03050 if (irec == 0)
03051 {
03052 newSpec = base_strcatalloc(newSpec, ":#" , &szNewSpec);
03053 }
03054 else
03055 {
03056 newSpec = base_strcatalloc(newSpec, ",#" , &szNewSpec);
03057 }
03058
03059 if (newSpec) newSpec = base_strcatalloc(newSpec, recnumStr, &szNewSpec);
03060 }
03061
03062 if (newSpec) newSpec = base_strcatalloc(newSpec, "]", &szNewSpec);
03063
03064 if (segs && segs[0])
03065 {
03066 if (newSpec) newSpec = base_strcatalloc(newSpec, segs[0], &szNewSpec);
03067 }
03068
03069 if (!newSpec)
03070 {
03071 JSONDIE("Out of memory.\n");
03072 }
03073
03074 if (firstlastExists)
03075 {
03076 snprintf(dsquery, sizeof(dsquery), "%s", newSpec);
03077 }
03078
03079 rcount = rs->n;
03080
03081
03082
03083
03084
03085
03086
03087
03088
03089
03090 char *existReqID = NULL;
03091 TIME timeToCompletion;
03092 int expSize;
03093 size_t szInput = 64;
03094 char *md5Input = NULL;
03095 unsigned char md5[MD5_DIGEST_LENGTH];
03096 char md5Str[2 * MD5_DIGEST_LENGTH + 1];
03097
03098
03099 memset(md5, '\0', sizeof(md5));
03100 md5Input = calloc(szInput, sizeof(char));
03101
03102 if (md5Input) md5Input = base_strcatalloc(md5Input, newSpec, &szInput);
03103
03104 if (filenamefmt && *filenamefmt)
03105 {
03106 if (md5Input) md5Input = base_strcatalloc(md5Input, filenamefmt, &szInput);
03107 }
03108
03109 if (process && *process)
03110 {
03111 if (md5Input) md5Input = base_strcatalloc(md5Input, process, &szInput);
03112 }
03113
03114 if (protocol && *protocol)
03115 {
03116 if (md5Input) md5Input = base_strcatalloc(md5Input, protocol, &szInput);
03117 }
03118
03119 if (method && *method)
03120 {
03121 if (md5Input) md5Input = base_strcatalloc(md5Input, method, &szInput);
03122 }
03123
03124 if (md5Input)
03125 {
03126 MD5((const unsigned char *)md5Input, strlen(md5Input), md5);
03127
03128
03129 int ibyte;
03130
03131 for (ibyte = 0; ibyte < MD5_DIGEST_LENGTH; ibyte++)
03132 {
03133 snprintf(md5Str + ibyte * 2, sizeof(md5Str) - ibyte * 2, "%02x", md5[ibyte]);
03134 }
03135 }
03136 else
03137 {
03138 JSONDIE("Out of memory.\n");
03139 }
03140
03141 existReqID = GetExistReqID(drms_env, md5Str, DUP_EXPORT_WINDOW, &timeToCompletion, &expSize);
03142
03143 free(newSpec);
03144
03145
03146
03147 if (existReqID)
03148 {
03149 char numBuf[64];
03150 char *jsonStr = NULL;
03151 char *jsonText = NULL;
03152 json_t *jroot = NULL;
03153 TIME waitTime = 0;
03154
03155 if (dojson)
03156 {
03157 jroot = json_new_object();
03158
03159 if (!jroot)
03160 {
03161 JSONDIE("Out of memory.");
03162 }
03163
03164 sprintf(numBuf, "%d", testmode ? 12 : 2);
03165 json_insert_pair_into_object(jroot, "status", json_new_number(numBuf));
03166
03167 jsonStr = string_to_json((char *)existReqID);
03168 json_insert_pair_into_object(jroot, kArgRequestid, json_new_string(jsonStr));
03169 free(jsonStr);
03170
03171 jsonStr = string_to_json((char *)method);
03172 json_insert_pair_into_object(jroot, kArgMethod, json_new_string(jsonStr));
03173 free(jsonStr);
03174
03175 jsonStr = string_to_json((char *)protocol);
03176 json_insert_pair_into_object(jroot, kArgProtocol, json_new_string(jsonStr));
03177 free(jsonStr);
03178
03179 waitTime = timeToCompletion - timenow();
03180 if (waitTime < 0)
03181 {
03182 waitTime = 0;
03183 }
03184
03185 sprintf(numBuf, "%1.0lf", waitTime);
03186 json_insert_pair_into_object(jroot, "wait", json_new_number(numBuf));
03187
03188 sprintf(numBuf, "%d", rcount);
03189 json_insert_pair_into_object(jroot, "rcount", json_new_number(numBuf));
03190
03191 sprintf(numBuf, "%d", expSize);
03192 json_insert_pair_into_object(jroot, "size", json_new_number(numBuf));
03193
03194 json_tree_to_string(jroot, &jsonText);
03195
03196 json_free_value(&jroot);
03197
03198 if (genWebPage)
03199 {
03200 if (fileupload)
03201 {
03202
03203 printf("Content-type: text/html\n\n");
03204 }
03205 else
03206 {
03207 printf("Content-type: application/json\n\n");
03208 }
03209 }
03210
03211 if (jsonText)
03212 {
03213 printf("%s\n", jsonText);
03214 free(jsonText);
03215 }
03216 }
03217 else
03218 {
03219 if (genWebPage)
03220 {
03221 printf("Content-type: text/plain\n\n");
03222 }
03223 printf("# JSOC Data Export Not Ready.\n");
03224 printf("status=%d\n", testmode ? 12 : 2);
03225 printf("requestid=%s\n", existReqID);
03226 printf("method=%s\n", method);
03227 printf("protocol=%s\n", protocol);
03228 printf("wait=%f\n", timeToCompletion);
03229 printf("size=%d\n", expSize);
03230 }
03231
03232 fflush(stdout);
03233
03234 CleanUp(&sunumarr, &infostructs, &webarglist, &series, &paths, &susize, arrsize, userhandle);
03235 free(existReqID);
03236 existReqID = NULL;
03237 drms_record_freerecsetspecarr_plussegs(&allvers, &sets, &settypes, &snames, &filts, &segs, nsets);
03238 drms_close_records(rs, DRMS_FREE_RECORD);
03239 return(0);
03240 }
03241
03242 drms_record_freerecsetspecarr_plussegs(&allvers, &sets, &settypes, &snames, &filts, &segs, nsets);
03243
03244 drms_stage_records(rs, 0, 0);
03245
03246
03247
03248
03249 drms_record_getinfo(rs);
03250
03251
03252
03253
03254
03255
03256 all_online = 1;
03257 compressedStorage = -1;
03258 for (irec=0; irec < rcount; irec++)
03259 {
03260
03261 DRMS_Record_t *rec = drms_recordset_fetchnext(drms_env, rs, &status, NULL, NULL);
03262
03263 if (!rec)
03264 {
03265
03266 break;
03267 }
03268
03269 DRMS_Segment_t *seg;
03270 HIterator_t *segp = NULL;
03271
03272 if (strncmp(rec->seriesinfo->seriesname, "jsoc.export", 11)== 0)
03273 JSONDIE("Export of jsoc_export series not allowed.");
03274
03275 DRMS_Record_t *tRec = NULL;
03276 DRMS_Record_t *segrec = NULL;
03277 SUM_info_t *sinfo = NULL;
03278 DRMS_Segment_t *tSeg = NULL;
03279
03280
03281
03282
03283
03284
03285
03286
03287
03288
03289
03290 while (seg = drms_record_nextseg(rec, &segp, 0))
03291 {
03292
03293 if (seg->info->islink)
03294 {
03295
03296
03297
03298 tSeg = drms_segment_lookup(rec, seg->info->name);
03299
03300 if (!tSeg)
03301 {
03302
03303
03304
03305
03306
03307
03308
03309
03310 status = DRMS_SUCCESS;
03311 continue;
03312 }
03313
03314 tRec = tSeg->record;
03315
03316
03317 segrec = tRec;
03318 }
03319 else
03320 {
03321 tSeg = seg;
03322 segrec = seg->record;
03323 }
03324
03325
03326
03327
03328 if (compressedStorage == -1)
03329 {
03330
03331 if (strstr(tSeg->cparms, "compress"))
03332 {
03333 compressedStorage = 1;
03334 }
03335 }
03336
03337 sinfo = segrec->suinfo;
03338
03339 if (!sinfo)
03340 {
03341
03342 all_online = 0;
03343
03344
03345 break;
03346 }
03347 else if (*(sinfo->online_loc) == '\0')
03348 {
03349
03350 fprintf(stderr, "JSOC_FETCH Bad sunum %lld for recnum %s:%lld in RecordSet: %s\n", segrec->sunum, segrec->seriesinfo->seriesname, segrec->recnum, dsquery);
03351
03352 all_online = 0;
03353
03354 break;
03355 }
03356 else if (strcmp(sinfo->online_status,"N") == 0)
03357 {
03358
03359
03360
03361 all_online = 0;
03362
03363
03364 size += (long long)sinfo->bytes;
03365 if ((long long)sinfo->bytes > 0)
03366 {
03367
03368 segcount += 1;
03369 }
03370
03371
03372 break;
03373 }
03374 else
03375 {
03376
03377 struct stat buf;
03378 char path[DRMS_MAXPATHLEN];
03379
03380 drms_segment_filename(tSeg, path);
03381 if (stat(path, &buf) != 0)
03382 {
03383
03384
03385 if (*(tSeg->filename))
03386 {
03387 DRMS_Keyword_t *quality = drms_keyword_lookup(segrec, "QUALITY",1);
03388 if (quality && drms_getkey_int(segrec, "QUALITY", 0) >= 0)
03389 {
03390 fprintf(stderr,"QUALITY >=0, filename=%s, but %s not found\n",tSeg->filename,path);
03391
03392 }
03393 }
03394 }
03395 else
03396 {
03397 if (S_ISDIR(buf.st_mode))
03398 {
03399 char cmd[DRMS_MAXPATHLEN+100];
03400 FILE *du;
03401 long long dirsize=0;
03402 sprintf(cmd,"/usr/bin/du -s -b %s", path);
03403 du = popen(cmd, "r");
03404 if (du)
03405 {
03406 if (fscanf(du,"%lld",&dirsize) == 1)
03407 {
03408 size += dirsize;
03409 segcount += 1;
03410 }
03411 pclose(du);
03412 }
03413
03414 }
03415 else
03416 {
03417 size += buf.st_size;
03418 segcount += 1;
03419 }
03420 }
03421 }
03422 }
03423
03424 if (compressedStorage == -1)
03425 {
03426
03427 compressedStorage = 0;
03428 }
03429
03430 if (segp)
03431 {
03432 hiter_free(segp);
03433 free(segp);
03434 segp = NULL;
03435 }
03436 }
03437 if (size > 0 && size < 1024*1024) size = 1024*1024;
03438 size /= 1024*1024;
03439
03440
03441 if ((strcmp(method,"url_quick")==0 && (strcmp(protocol,kOptProtocolAsIs)==0 || strcmp(protocol,kOptProtocolSuAsIs)==0) || strcmp(protocol,"su")==0) && segcount == 0)
03442 JSONDIE("There are no files in this RecordSet");
03443
03444
03445
03446
03447
03448
03449
03450
03451
03452
03453
03454
03455
03456
03457
03458
03459
03460
03461
03462
03463
03464
03465
03466
03467
03468
03469
03470 long long sizeLimit;
03471
03472 compressedDownload = (strstr(protocol, "**NONE**") == NULL);
03473
03474
03475 if (compressedStorage && !compressedDownload)
03476 {
03477 sizeLimit = MAX_UNCOMPRESSING_EXPORT_SIZE / sizeRatio;
03478 }
03479 else if (!compressedStorage && compressedDownload)
03480 {
03481 sizeLimit = MAX_COMPRESSING_EXPORT_SIZE / sizeRatio;
03482 }
03483 else
03484 {
03485 sizeLimit = MAX_STRAIGHT_EXPORT_SIZE / sizeRatio;
03486 }
03487
03488
03489 WriteLog(lfname, "size is %lld.\n", size);
03490 WriteLog(lfname, "sizeRatio is %lf.\n", sizeRatio);
03491 WriteLog(lfname, "sizeLimit is %lld.\n", sizeLimit);
03492
03493 if (size > sizeLimit)
03494 {
03495 if (dojson)
03496 {
03497 char *json;
03498 char *strval;
03499 char numval[100];
03500 json_t *jroot = json_new_object();
03501 json_insert_pair_into_object(jroot, kArgRequestid, json_new_string("VOID"));
03502
03503 strval = string_to_json((char *)method);
03504 json_insert_pair_into_object(jroot, kArgMethod, json_new_string(strval));
03505 free(strval);
03506 strval = string_to_json((char *)protocol);
03507 json_insert_pair_into_object(jroot, kArgProtocol, json_new_string(strval));
03508 free(strval);
03509 json_insert_pair_into_object(jroot, "wait", json_new_number("0"));
03510 json_insert_pair_into_object(jroot, "status", json_new_number("3"));
03511 sprintf(numval, "%d", rcount);
03512 json_insert_pair_into_object(jroot, "count", json_new_number(numval));
03513 sprintf(numval, "%d", (int)size);
03514 json_insert_pair_into_object(jroot, "size", json_new_number(numval));
03515 sprintf(numval,"Request exceeds max byte limit of %lldMB", sizeLimit);
03516 strval = string_to_json(numval);
03517 json_insert_pair_into_object(jroot, "error", json_new_string(strval));
03518 free(strval);
03519 json_tree_to_string(jroot,&json);
03520 if (genWebPage)
03521 {
03522 if (fileupload)
03523 printf("Content-type: text/html\n\n");
03524 else
03525 printf("Content-type: application/json\n\n");
03526 }
03527 printf("%s\n",json);
03528 fflush(stdout);
03529 free(json);
03530 }
03531 else
03532 {
03533 if (genWebPage)
03534 {
03535 printf("Content-type: text/plain\n\n");
03536 }
03537 printf("# JSOC Data Export Failure.\n");
03538 printf("status=3\n");
03539 printf("size=%lld\n",size);
03540 printf("count=%d\n",rcount);
03541 printf("requestid=VOID\n");
03542 printf("wait=0\n");
03543 }
03544
03545 CleanUp(&sunumarr, &infostructs, &webarglist, &series, &paths, &susize, arrsize, userhandle);
03546 return(0);
03547 }
03548
03549
03550 if ((strcmp(method,"url_quick")==0 && (strcmp(protocol,kOptProtocolAsIs)==0 || strcmp(protocol,kOptProtocolSuAsIs)==0) || strcmp(protocol,"su")==0) && all_online)
03551 {
03552 if (0 && segcount == 1)
03553 {
03554 char sfpath[DRMS_MAXPATHLEN];
03555 int sfret = send_file(rs->records[0], 0, sfpath, sizeof(sfpath));
03556 if (sfret == 1)
03557 {
03558 JSONDIE2("Can not open file for export: ",sfpath);
03559 }
03560 else
03561 {
03562 CleanUp(&sunumarr, &infostructs, &webarglist, &series, &paths, &susize, arrsize, userhandle);
03563 return(sfret);
03564 }
03565 }
03566 else if (dojson)
03567 {
03568 char *json;
03569 char *strval;
03570 int count;
03571 json_t *jroot = json_new_object();
03572 count = quick_export_rs(jroot, rs, 0, size);
03573 json_insert_pair_into_object(jroot, kArgRequestid, json_new_string(""));
03574
03575 strval = string_to_json((char *)method);
03576 json_insert_pair_into_object(jroot, kArgMethod, json_new_string(strval));
03577 free(strval);
03578 strval = string_to_json((char *)protocol);
03579 json_insert_pair_into_object(jroot, kArgProtocol, json_new_string(strval));
03580 free(strval);
03581 json_insert_pair_into_object(jroot, "wait", json_new_number("0"));
03582 json_insert_pair_into_object(jroot, "status", json_new_number("0"));
03583 json_tree_to_string(jroot,&json);
03584 if (genWebPage)
03585 {
03586 if (fileupload)
03587 printf("Content-type: text/html\n\n");
03588 else
03589 printf("Content-type: application/json\n\n");
03590 }
03591 printf("%s\n",json);
03592 fflush(stdout);
03593 free(json);
03594 }
03595 else
03596 {
03597 if (genWebPage)
03598 {
03599 printf("Content-type: text/plain\n\n");
03600 }
03601 printf("# JSOC Quick Data Export of as-is files.\n");
03602 printf("status=0\n");
03603 printf("requestid=\"%s\"\n", kNotSpecified);
03604 printf("method=%s\n", method);
03605 printf("protocol=%s\n", protocol);
03606 printf("wait=0\n");
03607 quick_export_rs(NULL, rs, 0, size);
03608 }
03609 CleanUp(&sunumarr, &infostructs, &webarglist, &series, &paths, &susize, arrsize, userhandle);
03610 return(0);
03611 }
03612
03613
03614
03615
03616 char jsocFetchPath[PATH_MAX];
03617 char reqidGenPath[PATH_MAX];
03618 char *binPath = NULL;
03619
03620 memset(jsocFetchPath, '\0', sizeof(jsocFetchPath));
03621
03622
03623 if (readlink("/proc/self/exe", jsocFetchPath, sizeof(jsocFetchPath)) == -1)
03624 {
03625 JSONDIE("Cannot obtain jsoc_fetch path.\n");
03626 }
03627 else
03628 {
03629 binPath = dirname(jsocFetchPath);
03630 snprintf(reqidGenPath, sizeof(reqidGenPath), "%s/GetJsocRequestID", binPath);
03631 }
03632
03633 FILE *fp = popen(reqidGenPath, "r");
03634
03635 if (fp)
03636 {
03637 if (fscanf(fp, "%s", new_requestid) != 1)
03638 {
03639 pclose(fp);
03640 JSONDIE("Cant get new RequestID");
03641 }
03642
03643 pclose(fp);
03644 }
03645 else
03646 {
03647 JSONDIE("Cant get new RequestID");
03648 }
03649
03650 if (strcmp(dbhost, SERVER) == 0)
03651 {
03652 if (passthrough)
03653 {
03654
03655
03656
03657 strcat(new_requestid, "_X");
03658 }
03659
03660 strcat(new_requestid, "_IN");
03661 }
03662
03663 requestid = new_requestid;
03664
03665
03666
03667 char cmd[DRMS_MAXQUERYLEN];
03668 char timeStrBuf[64];
03669
03670 time_t secs;
03671 struct tm *currentUT;
03672
03673 secs = time(NULL);
03674 currentUT = gmtime(&secs);
03675
03676 strftime(timeStrBuf, sizeof(timeStrBuf), "%Y-%m-%d %H:%M:%S UTC", currentUT);
03677 snprintf(cmd, sizeof(cmd), "INSERT INTO jsoc.export_md5 (md5, requestid, exporttime) VALUES('%s', '%s', '%s')", md5Str, requestid, timeStrBuf);
03678 if (drms_dms(drms_env->session, NULL, cmd))
03679 {
03680 fprintf(stderr, "Failure obtaining estimated completion time and size: %s.\n", cmd);
03681 JSONDIE("Cant save new export-request hash.");
03682 }
03683
03684
03685 if (1)
03686 {
03687 char exportlogfile[1000];
03688 char timebuf[50];
03689 FILE *exportlog;
03690 sprintf(exportlogfile, "/home/jsoc/exports/tmp/%s.reqlog", requestid);
03691 exportlog = fopen(exportlogfile, "w");
03692 sprint_ut(timebuf, fetch_time);
03693 fprintf(exportlog,"XXXX New export request started at %s\n", timebuf);
03694 fprintf(exportlog,"REMOTE_ADDR=%s\nHTTP_REFERER=%s\nREQUEST_METHOD=%s\nQUERY_STRING=%s\n",
03695 getenv("REMOTE_ADDR"), getenv("HTTP_REFERER"), getenv("REQUEST_METHOD"), getenv("QUERY_STRING"));
03696 fclose(exportlog);
03697 }
03698
03699
03700
03701
03702
03703 if (strcmp(requestor, kNotSpecified) != 0)
03704 {
03705 DRMS_Record_t *requestor_rec;
03706
03707 #ifdef IN_MY_DREAMS
03708 DRMS_RecordSet_t *requestor_rs;
03709 char requestorquery[2000];
03710 sprintf(requestorquery, "%s[? Requestor = '%s' ?]", kExportUser, requestor);
03711 requestor_rs = drms_open_records(drms_env, requestorquery, &status);
03712 if (!requestor_rs)
03713 JSONDIE("Cant find requestor info series");
03714 if (requestor_rs->n == 0)
03715 {
03716 drms_close_records(requestor_rs, DRMS_FREE_RECORD);
03717 #endif
03718
03719 requestor_rec = drms_create_record(drms_env, kExportUser, DRMS_PERMANENT, &status);
03720 if (!requestor_rec)
03721 JSONDIE("Cant create new user info record");
03722
03723 requestorid = requestor_rec->recnum;
03724 drms_setkey_int(requestor_rec, "RequestorID", requestorid);
03725 drms_setkey_string(requestor_rec, "Requestor", requestor);
03726 if (strncasecmp(notify,"solarmail",9) == 0)
03727 {
03728 char tmp_notify[1024];
03729 sprintf(tmp_notify, "%s@spd.aas.org", requestor);
03730 drms_setkey_string(requestor_rec, "Notify", tmp_notify);
03731 }
03732 else
03733 drms_setkey_string(requestor_rec, "Notify", notify);
03734 drms_setkey_string(requestor_rec, "ShipTo", shipto);
03735 drms_setkey_time(requestor_rec, "FirstTime", fetch_time);
03736 drms_setkey_time(requestor_rec, "UpdateTime", fetch_time);
03737 drms_close_record(requestor_rec, DRMS_INSERT_RECORD);
03738
03739 #ifdef IN_MY_DREAMS
03740 }
03741 else
03742 {
03743
03744 requestor_rec = requestor_rs->records[0];
03745 requestorid = drms_getkey_int(requestor_rec, "RequestorID", NULL);
03746 drms_close_records(requestor_rs, DRMS_FREE_RECORD);
03747 }
03748 #endif
03749 }
03750 else
03751 requestorid = 0;
03752
03753
03754
03755 if ( !requestid || !*requestid || strcmp(requestid, "none") == 0)
03756 JSONDIE("Must have valid requestID - internal error.");
03757 if (strcmp(dsin, "Not Specified") == 0)
03758 JSONDIE("Must have Recordset specified");
03759
03760
03761 exprec = drms_create_record(drms_env, export_series, DRMS_PERMANENT, &status);
03762 if (!exprec)
03763 JSONDIE("Cant create new export control record");
03764 drms_setkey_string(exprec, "RequestID", requestid);
03765 drms_setkey_string(exprec, "DataSet", dsquery);
03766 drms_setkey_string(exprec, "Processing", process);
03767 drms_setkey_string(exprec, "Protocol", protocol);
03768 drms_setkey_string(exprec, "FilenameFmt", filenamefmt);
03769 drms_setkey_string(exprec, "Method", method);
03770 drms_setkey_string(exprec, "Format", format);
03771 drms_setkey_time(exprec, "ReqTime", fetch_time);
03772 drms_setkey_time(exprec, "EstTime", fetch_time+10);
03773 drms_setkey_longlong(exprec, "Size", (int)size);
03774 drms_setkey_int(exprec, "Status", (testmode ? 12 : 2));
03775 drms_setkey_int(exprec, "Requestor", requestorid);
03776
03777 }
03778
03779
03780 else if (strcmp(op,kOpExpRepeat) == 0)
03781 {
03782 char logpath[DRMS_MAXPATHLEN];
03783
03784
03785 if (strcmp(requestid, kNotSpecified) == 0)
03786 JSONDIE("RequestID must be provided");
03787
03788
03789 if (1)
03790 {
03791 char exportlogfile[1000];
03792 char timebuf[50];
03793 FILE *exportlog;
03794 sprintf(exportlogfile, "/home/jsoc/exports/tmp/%s.reqlog", requestid);
03795 exportlog = fopen(exportlogfile, "a");
03796 sprint_ut(timebuf, fetch_time);
03797 fprintf(exportlog,"XXX New repeat request started at %s\n", timebuf);
03798 fprintf(exportlog,"REMOTE_ADDR=%s\nHTTP_REFERER=%s\nREQUEST_METHOD=%s\nQUERY_STRING=%s\n",
03799 getenv("REMOTE_ADDR"), getenv("HTTP_REFERER"), getenv("REQUEST_METHOD"), getenv("QUERY_STRING"));
03800 fclose(exportlog);
03801 }
03802
03803 JSONDIE("Re-Export requests temporarily disabled.");
03804
03805
03806 export_series = kExportSeries;
03807 sprintf(status_query, "%s[%s]", export_series, requestid);
03808 exports = drms_open_records(drms_env, status_query, &status);
03809 if (!exports)
03810 JSONDIE3("Cant locate export series: ", status_query);
03811 if (exports->n < 1)
03812 JSONDIE3("Cant locate export request: ", status_query);
03813 status = drms_getkey_int(exports->records[0], "Status", NULL);
03814 if (status != 0)
03815 JSONDIE("Can't re-request a failed or incomplete prior request");
03816
03817
03818
03819
03820
03821
03822 if (drms_record_directory(exprec, logpath, 0) != DRMS_SUCCESS || *logpath == '\0')
03823 {
03824 drms_close_records(exports, DRMS_FREE_RECORD);
03825
03826
03827 if (strcmp(notify, kNotSpecified) != 0)
03828 {
03829 DRMS_Record_t *requestor_rec;
03830 requestor_rec = drms_create_record(drms_env, kExportUser, DRMS_PERMANENT, &status);
03831 if (!requestor_rec)
03832 JSONDIE("Cant create new user info record");
03833 requestorid = requestor_rec->recnum;
03834 drms_setkey_int(requestor_rec, "RequestorID", requestorid);
03835 drms_setkey_string(requestor_rec, "Requestor", "NA");
03836 drms_setkey_string(requestor_rec, "Notify", notify);
03837 drms_setkey_string(requestor_rec, "ShipTo", "NA");
03838 drms_setkey_time(requestor_rec, "FirstTime", fetch_time);
03839 drms_setkey_time(requestor_rec, "UpdateTime", fetch_time);
03840 drms_close_record(requestor_rec, DRMS_INSERT_RECORD);
03841 }
03842 else
03843 requestorid = 0;
03844
03845
03846 export_series = kExportSeriesNew;
03847 sprintf(status_query, "%s[%s]", export_series, requestid);
03848
03849
03850 exports = drms_open_records(drms_env, status_query, &status);
03851 if (!exports)
03852 JSONDIE3("Cant locate export series: ", status_query);
03853 if (exports->n < 1)
03854 JSONDIE3("Cant locate export request: ", status_query);
03855 exprec = drms_clone_record(exports->records[0], DRMS_PERMANENT, DRMS_SHARE_SEGMENTS, &status);
03856 if (!exprec)
03857 JSONDIE("Cant create new export control record");
03858
03859 drms_setkey_int(exprec, "Status", 2);
03860 if (requestorid)
03861 drms_setkey_int(exprec, "Requestor", requestorid);
03862 drms_setkey_time(exprec, "ReqTime", fetch_time);
03863
03864 drms_close_records(exports, DRMS_FREE_RECORD);
03865 }
03866 else
03867 {
03868 drms_close_records(exports, DRMS_FREE_RECORD);
03869 }
03870
03871
03872 }
03873
03874
03875
03876
03877
03878
03879 if (strcmp(op,kOpExpStatus) == 0)
03880 {
03881 char mybuf[128];
03882
03883
03884
03885
03886
03887 if (!requestid || !*requestid || strcmp(requestid, kNotSpecified) == 0)
03888 {
03889 JSONDIE("RequestID must be provided");
03890 }
03891 else
03892 {
03893 regex_t regexp;
03894
03895 if (regcomp(®exp, kDefRegexp, REG_EXTENDED) != 0)
03896 {
03897 snprintf(mybuf, sizeof(mybuf), "Bad regular expression '%s'.", kDefRegexp);
03898 JSONDIE(mybuf);
03899 }
03900 else
03901 {
03902 if (regexec(®exp, requestid, (size_t)0, (regmatch_t *)NULL, 0) != 0)
03903 {
03904
03905 regfree(®exp);
03906 snprintf(mybuf, sizeof(mybuf), "Bad RequestID '%s' provided.", requestid);
03907 JSONDIE(mybuf);
03908 }
03909
03910 regfree(®exp);
03911 }
03912 }
03913
03914 if (internal)
03915 {
03916 lfname = kLogFileExpStatInt;
03917 }
03918 else
03919 {
03920 lfname = kLogFileExpStatExt;
03921 }
03922
03923 LogReqInfo(lfname, instanceID, fileupload, op, dsin, requestid, dbhost, from_web, webarglist, fetch_time);
03924
03925
03926 sprintf(status_query, "%s[%s]", kExportSeries, requestid);
03927 exports = drms_open_records(drms_env, status_query, &status);
03928 if (!exports)
03929 JSONDIE3("Cant locate export series: ", status_query);
03930 if (exports->n < 1)
03931 JSONDIE3("Cant locate export request: ", status_query);
03932 exprec = exports->records[0];
03933 exports->records[0] = NULL;
03934 drms_close_records(exports, DRMS_FREE_RECORD);
03935 insertexprec = 0;
03936 }
03937
03938
03939
03940
03941
03942
03943
03944
03945
03946
03947
03948
03949 if (strcmp(requestid, kNotSpecified) == 0)
03950 {
03951
03952 JSONCOMMIT("RequestID must be provided", &exprec, !insertexprec);
03953 }
03954
03955
03956
03957 status = drms_getkey_int(exprec, "Status", NULL);
03958 process = drms_getkey_string(exprec, "Processing", NULL);
03959 protocol = drms_getkey_string(exprec, "Protocol", NULL);
03960 filenamefmt = drms_getkey_string(exprec, "FilenameFmt", NULL);
03961 method = drms_getkey_string(exprec, "Method", NULL);
03962 format = drms_getkey_string(exprec, "Format", NULL);
03963 reqtime = drms_getkey_time(exprec, "ReqTime", NULL);
03964 esttime = drms_getkey_time(exprec, "EstTime", NULL);
03965 size = drms_getkey_longlong(exprec, "Size", NULL);
03966 requestorid = drms_getkey_int(exprec, "Requestor", NULL);
03967 char *export_errmsg = drms_getkey_string(exprec, "errmsg", NULL);
03968
03969
03970 switch (status)
03971 {
03972 case 0:
03973 errorreply = NULL;
03974 waittime = 0;
03975 break;
03976 case 1:
03977 errorreply = NULL;
03978 waittime = esttime - fetch_time;
03979 break;
03980 case 12:
03981 case 2:
03982 errorreply = NULL;
03983 waittime = esttime - fetch_time;
03984 break;
03985 case 3:
03986 errorreply = "Request too large";
03987 waittime = 999999;
03988 break;
03989 case 4:
03990 waittime = 999999;
03991 if (strcmp("NA", export_errmsg))
03992 errorreply = export_errmsg;
03993 else
03994 errorreply = "RecordSet specified does not exist";
03995 break;
03996 case 5:
03997 waittime = 999999;
03998 errorreply = "Request was completed but is now deleted, 7 day limit exceeded";
03999 break;
04000 default:
04001 {
04002
04003 JSONCOMMIT("Illegal status in export record", &exprec, !insertexprec);
04004 }
04005 }
04006
04007
04008 if (1)
04009 {
04010 char *json;
04011 char *strval;
04012 char numval[100];
04013 json_t *jroot=NULL;
04014
04015 if (status == 0)
04016 {
04017
04018
04019 char logpath[DRMS_MAXPATHLEN];
04020 FILE *fp;
04021 int c;
04022 char *indexfile = (dojson ? "index.json" : "index.txt");
04023 jroot = json_new_object();
04024 if (drms_record_directory(exprec, logpath, 0) != DRMS_SUCCESS || *logpath == '\0')
04025 {
04026 status = 5;
04027 waittime = 999999;
04028 errorreply = "Request was completed but is now deleted, 7 day limit exceeded";
04029 }
04030 else
04031 {
04032 strncat(logpath, "/", DRMS_MAXPATHLEN);
04033 strncat(logpath, indexfile, DRMS_MAXPATHLEN);
04034 fp = fopen(logpath, "r");
04035 if (!fp)
04036 {
04037
04038 char dbuf[1024];
04039
04040 snprintf(dbuf, sizeof(dbuf), "Export should be complete but return %s file not found", indexfile);
04041 JSONCOMMIT(dbuf, &exprec, !insertexprec);
04042 }
04043
04044 if (genWebPage)
04045 {
04046 if (dojson)
04047 printf("Content-type: application/json\n\n");
04048 else
04049 printf("Content-type: text/plain\n\n");
04050 }
04051
04052 while ((c = fgetc(fp)) != EOF)
04053 putchar(c);
04054 fclose(fp);
04055 fflush(stdout);
04056 }
04057 }
04058
04059 if (status > 0)
04060 {
04061 if (dojson)
04062 {
04063 jroot = json_new_object();
04064 json_t *data = NULL;
04065
04066 if (strcmp(op, kOpExpSu) == 0)
04067 {
04068 int i;
04069 data = json_new_array();
04070 for (i = 0; i < expsucount; i++)
04071 {
04072 json_t *suobj = json_new_object();
04073 char *jsonstr;
04074 char numval[40];
04075 sprintf(numval,"%lld",sunums[i]);
04076 jsonstr = string_to_json(numval);
04077 json_insert_pair_into_object(jroot, kArgSunum, json_new_string(jsonstr));
04078 free(jsonstr);
04079 jsonstr = string_to_json(series[i]);
04080 json_insert_pair_into_object(suobj, "series", json_new_string(jsonstr));
04081 free(jsonstr);
04082 jsonstr = string_to_json(paths[i]);
04083 json_insert_pair_into_object(suobj, "path", json_new_string(jsonstr));
04084 free(jsonstr);
04085 numval[0] = sustatus[i];
04086 numval[1] = '\0';
04087
04088 json_insert_pair_into_object(suobj, "sustatus", json_new_string(numval));
04089 json_insert_pair_into_object(suobj, "susize", json_new_string(susize[i]));
04090
04091 json_insert_child(data, suobj);
04092 }
04093 }
04094
04095 sprintf(numval, "%d", status);
04096 json_insert_pair_into_object(jroot, "status", json_new_number(numval));
04097 strval = string_to_json((char *)requestid);
04098 json_insert_pair_into_object(jroot, kArgRequestid, json_new_string(strval));
04099 free(strval);
04100 strval = string_to_json((char *)method);
04101 json_insert_pair_into_object(jroot, kArgMethod, json_new_string(strval));
04102 free(strval);
04103 strval = string_to_json((char *)protocol);
04104 json_insert_pair_into_object(jroot, kArgProtocol, json_new_string(strval));
04105 free(strval);
04106 sprintf(numval, "%1.0lf", waittime);
04107 json_insert_pair_into_object(jroot, "wait", json_new_number(numval));
04108 sprintf(numval, "%d", rcount);
04109 json_insert_pair_into_object(jroot, "rcount", json_new_number(numval));
04110 sprintf(numval, "%d", (int)size);
04111 json_insert_pair_into_object(jroot, "size", json_new_number(numval));
04112 if (strcmp(op, kOpExpSu) == 0)
04113 json_insert_pair_into_object(jroot, "data", data);
04114 if (errorreply)
04115 {
04116 strval = string_to_json(errorreply);
04117 json_insert_pair_into_object(jroot, "error", json_new_string(strval));
04118 free(strval);
04119 }
04120 if (status > 2 )
04121 {
04122 strval = string_to_json("jsoc_help@jsoc.stanford.edu");
04123 json_insert_pair_into_object(jroot, "contact", json_new_string(strval));
04124 free(strval);
04125 }
04126 json_tree_to_string(jroot,&json);
04127 json_free_value(&jroot);
04128
04129 if (genWebPage)
04130 {
04131 if (fileupload)
04132 printf("Content-type: text/html\n\n");
04133 else
04134 printf("Content-type: application/json\n\n");
04135 }
04136
04137 printf("%s\n",json);
04138 free(json);
04139 json = NULL;
04140 }
04141 else
04142 {
04143 if (genWebPage)
04144 {
04145 printf("Content-type: text/plain\n\n");
04146 }
04147 printf("# JSOC Data Export Not Ready.\n");
04148 printf("status=%d\n", status);
04149 printf("requestid=%s\n", requestid);
04150 printf("method=%s\n", method);
04151 printf("protocol=%s\n", protocol);
04152 printf("wait=%f\n",waittime);
04153 printf("size=%lld\n",size);
04154 if (errorreply)
04155 printf("error=\"%s\"\n", errorreply);
04156 if (status > 2)
04157 {
04158 printf("contact=jsoc_help@jsoc.stanford.edu\n");
04159 }
04160 else if (strcmp(op, kOpExpSu) == 0)
04161 {
04162 int i;
04163 printf("# DATA\n");
04164 for (i = 0; i < expsucount; i++)
04165 {
04166 printf("%lld\t%s\t%s\t%c\t%s\n", sunums[i], series[i], paths[i], sustatus[i], susize[i]);
04167 }
04168 }
04169 }
04170 fflush(stdout);
04171 }
04172 }
04173
04174 if (sustatus)
04175 {
04176 free(sustatus);
04177 sustatus = NULL;
04178 }
04179
04180 if (sunums)
04181 {
04182 free(sunums);
04183 sunums = NULL;
04184 }
04185
04186 report_summary(Server, StartTime, Remote_Address, op, dsin, rcountlimit, internal, status);
04187 CleanUp(&sunumarr, &infostructs, &webarglist, &series, &paths, &susize, arrsize, userhandle);
04188
04189 if (exprec)
04190 {
04191 insertexprec ? drms_close_record(exprec, DRMS_INSERT_RECORD) : drms_close_record(exprec, DRMS_FREE_RECORD);
04192 }
04193
04194 return(0);
04195 }